[polly] e822780 - [Polly] Update ISL to isl-0.22.1-87-gfee05a13.

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 10 17:06:15 PST 2020


Author: Michael Kruse
Date: 2020-02-10T19:03:08-06:00
New Revision: e8227804ac7eef212f989339e04322113e77ec64

URL: https://github.com/llvm/llvm-project/commit/e8227804ac7eef212f989339e04322113e77ec64
DIFF: https://github.com/llvm/llvm-project/commit/e8227804ac7eef212f989339e04322113e77ec64.diff

LOG: [Polly] Update ISL to isl-0.22.1-87-gfee05a13.

The primary motivation is to fix an assertion failure in
isl_basic_map_alloc_equality:

    isl_assert(ctx, room_for_con(bmap, 1), return -1);

Although the assertion does not occur anymore, I could not identify
which of ISL's commits fixed it.

Compared to the previous ISL version, Polly requires some changes for this update

 * Since ISL commit
   20d3574 "perform parameter alignment by modifying both arguments to function"
   isl_*_gist_* and similar functions do not always align the paramter
   list anymore. This caused the parameter lists in JScop files to
   become out-of-sync. Since many regression tests use JScop files with
   a fixed parameter list and order, we explicitly call align_params to
   ensure a predictable parameter list.

 * ISL changed some return types to isl_size, a typedef of (signed) int.
   This caused some issues where the return type was unsigned int before:
   - No overload for std::max(unsigned,isl_size)
   - It cause additional 'mixed signed/unsigned comparison' warnings.
     Since they do not break compilation, and sizes larger than 2^31
     were never supported, I am going to fix it separately.

 * With the change to isl_size, commit
   57d547 "isl_*_list_size: return isl_size"
   also changed the return value in case of an error from 0 to -1. This
   caused undefined looping over isl_iterator since the 'end iterator'
   got index -1, never reached from the 'begin iterator' with index 0.

 * Some internal changes in ISL caused the number of operations to
   increase when determining access ranges to determine aliasing
   overlaps. In one test, this caused exceeding the default limit of
   800000. The operations-limit was disabled for this test.

Added: 
    polly/lib/External/isl/check_reparse_templ.c
    polly/lib/External/isl/check_reparse_test_templ.c
    polly/lib/External/isl/check_type_range_templ.c
    polly/lib/External/isl/dep.c
    polly/lib/External/isl/has_single_reference_templ.c
    polly/lib/External/isl/isl_align_params_bin_templ.c
    polly/lib/External/isl/isl_align_params_templ.c
    polly/lib/External/isl/isl_bind_domain_templ.c
    polly/lib/External/isl/isl_check_named_params_templ.c
    polly/lib/External/isl/isl_domain_factor_templ.c
    polly/lib/External/isl/isl_list_macro.h
    polly/lib/External/isl/isl_local_private.h
    polly/lib/External/isl/isl_map_bound_templ.c
    polly/lib/External/isl/isl_maybe_ast_graft_list.h
    polly/lib/External/isl/isl_multi_add_constant_templ.c
    polly/lib/External/isl/isl_multi_arith_templ.c
    polly/lib/External/isl/isl_multi_bind_domain_templ.c
    polly/lib/External/isl/isl_multi_bind_templ.c
    polly/lib/External/isl/isl_multi_dim_id_templ.c
    polly/lib/External/isl/isl_multi_domain_templ.c
    polly/lib/External/isl/isl_multi_from_base_templ.c
    polly/lib/External/isl/isl_multi_identity_templ.c
    polly/lib/External/isl/isl_multi_locals_templ.c
    polly/lib/External/isl/isl_multi_move_dims_templ.c
    polly/lib/External/isl/isl_multi_nan_templ.c
    polly/lib/External/isl/isl_multi_no_domain_templ.c
    polly/lib/External/isl/isl_multi_param_templ.c
    polly/lib/External/isl/isl_multi_product_templ.c
    polly/lib/External/isl/isl_multi_read_no_explicit_domain_templ.c
    polly/lib/External/isl/isl_multi_splice_templ.c
    polly/lib/External/isl/isl_multi_tuple_id_templ.c
    polly/lib/External/isl/isl_multi_zero_templ.c
    polly/lib/External/isl/isl_project_out_all_params_templ.c
    polly/lib/External/isl/isl_pw_add_constant_multi_val_templ.c
    polly/lib/External/isl/isl_pw_add_constant_templ.c
    polly/lib/External/isl/isl_pw_add_constant_val_templ.c
    polly/lib/External/isl/isl_pw_bind_domain_templ.c
    polly/lib/External/isl/isl_pw_insert_dims_templ.c
    polly/lib/External/isl/isl_pw_lift_templ.c
    polly/lib/External/isl/isl_pw_morph_templ.c
    polly/lib/External/isl/isl_pw_move_dims_templ.c
    polly/lib/External/isl/isl_pw_neg_templ.c
    polly/lib/External/isl/isl_pw_opt_templ.c
    polly/lib/External/isl/isl_pw_pullback_templ.c
    polly/lib/External/isl/isl_pw_sub_templ.c
    polly/lib/External/isl/isl_set_to_ast_graft_list.c
    polly/lib/External/isl/isl_set_to_ast_graft_list.h
    polly/lib/External/isl/isl_test_list_templ.c
    polly/lib/External/isl/isl_test_plain_equal_templ.c
    polly/lib/External/isl/isl_type_check_equal_space_templ.c
    polly/lib/External/isl/isl_type_has_equal_space_bin_templ.c
    polly/lib/External/isl/isl_type_has_equal_space_templ.c
    polly/lib/External/isl/m4/ax_cxx_compile_stdcxx_11_no_override.m4
    polly/lib/External/isl/opt_type.h
    polly/lib/External/isl/print_yaml_field_templ.c
    polly/lib/External/isl/py-compile
    polly/lib/External/isl/test_inputs/codegen/bilinear.c
    polly/lib/External/isl/test_inputs/codegen/bilinear.st
    polly/lib/External/isl/test_inputs/codegen/group.c
    polly/lib/External/isl/test_inputs/codegen/group.st
    polly/lib/External/isl/test_inputs/schedule/flat1.sc
    polly/lib/External/isl/test_inputs/schedule/flat1.st
    polly/lib/External/isl/test_inputs/schedule/flat2.sc
    polly/lib/External/isl/test_inputs/schedule/flat2.st
    polly/lib/External/isl/test_inputs/schedule/flat3.sc
    polly/lib/External/isl/test_inputs/schedule/flat3.st
    polly/lib/External/isl/test_inputs/schedule/flat4.sc
    polly/lib/External/isl/test_inputs/schedule/flat4.st
    polly/lib/External/isl/test_inputs/schedule/flat5.sc
    polly/lib/External/isl/test_inputs/schedule/flat5.st
    polly/lib/External/isl/test_inputs/schedule/flat6.sc
    polly/lib/External/isl/test_inputs/schedule/flat6.st
    polly/lib/External/isl/test_inputs/schedule/poliwoda.sc
    polly/lib/External/isl/test_inputs/schedule/poliwoda.st

Modified: 
    polly/include/polly/Support/ISLTools.h
    polly/lib/Analysis/ScopInfo.cpp
    polly/lib/CodeGen/PPCGCodeGeneration.cpp
    polly/lib/External/CMakeLists.txt
    polly/lib/External/isl/AUTHORS
    polly/lib/External/isl/ChangeLog
    polly/lib/External/isl/GIT_HEAD_ID
    polly/lib/External/isl/Makefile.am
    polly/lib/External/isl/Makefile.in
    polly/lib/External/isl/README
    polly/lib/External/isl/aclocal.m4
    polly/lib/External/isl/all.h
    polly/lib/External/isl/basis_reduction_templ.c
    polly/lib/External/isl/bound.c
    polly/lib/External/isl/cat.c
    polly/lib/External/isl/closure.c
    polly/lib/External/isl/codegen.c
    polly/lib/External/isl/configure
    polly/lib/External/isl/configure.ac
    polly/lib/External/isl/cpp/cpp-checked.h.pre
    polly/lib/External/isl/cpp/cpp.h.pre
    polly/lib/External/isl/doc/Makefile.in
    polly/lib/External/isl/doc/user.pod
    polly/lib/External/isl/include/isl/aff.h
    polly/lib/External/isl/include/isl/aff_type.h
    polly/lib/External/isl/include/isl/arg.h
    polly/lib/External/isl/include/isl/ast.h
    polly/lib/External/isl/include/isl/ast_build.h
    polly/lib/External/isl/include/isl/ast_type.h
    polly/lib/External/isl/include/isl/constraint.h
    polly/lib/External/isl/include/isl/cpp-checked-conversion.h
    polly/lib/External/isl/include/isl/cpp-checked.h
    polly/lib/External/isl/include/isl/cpp.h
    polly/lib/External/isl/include/isl/ctx.h
    polly/lib/External/isl/include/isl/fixed_box.h
    polly/lib/External/isl/include/isl/flow.h
    polly/lib/External/isl/include/isl/hash.h
    polly/lib/External/isl/include/isl/hmap_templ.c
    polly/lib/External/isl/include/isl/id.h
    polly/lib/External/isl/include/isl/id_type.h
    polly/lib/External/isl/include/isl/list.h
    polly/lib/External/isl/include/isl/local_space.h
    polly/lib/External/isl/include/isl/map.h
    polly/lib/External/isl/include/isl/mat.h
    polly/lib/External/isl/include/isl/multi.h
    polly/lib/External/isl/include/isl/point.h
    polly/lib/External/isl/include/isl/polynomial.h
    polly/lib/External/isl/include/isl/polynomial_type.h
    polly/lib/External/isl/include/isl/schedule.h
    polly/lib/External/isl/include/isl/schedule_node.h
    polly/lib/External/isl/include/isl/set.h
    polly/lib/External/isl/include/isl/space.h
    polly/lib/External/isl/include/isl/space_type.h
    polly/lib/External/isl/include/isl/stream.h
    polly/lib/External/isl/include/isl/union_map.h
    polly/lib/External/isl/include/isl/union_map_type.h
    polly/lib/External/isl/include/isl/union_set.h
    polly/lib/External/isl/include/isl/val.h
    polly/lib/External/isl/include/isl/val_type.h
    polly/lib/External/isl/include/isl/vec.h
    polly/lib/External/isl/include/isl/vertices.h
    polly/lib/External/isl/interface/Makefile.am
    polly/lib/External/isl/interface/Makefile.in
    polly/lib/External/isl/interface/cpp.cc
    polly/lib/External/isl/interface/cpp.h
    polly/lib/External/isl/interface/cpp_conversion.cc
    polly/lib/External/isl/interface/cpp_conversion.h
    polly/lib/External/isl/interface/extract_interface.cc
    polly/lib/External/isl/interface/generator.cc
    polly/lib/External/isl/interface/generator.h
    polly/lib/External/isl/interface/isl.py
    polly/lib/External/isl/interface/python.cc
    polly/lib/External/isl/interface/python.h
    polly/lib/External/isl/isl_aff.c
    polly/lib/External/isl/isl_aff_map.c
    polly/lib/External/isl/isl_aff_private.h
    polly/lib/External/isl/isl_affine_hull.c
    polly/lib/External/isl/isl_arg.c
    polly/lib/External/isl/isl_ast.c
    polly/lib/External/isl/isl_ast_build.c
    polly/lib/External/isl/isl_ast_build_expr.c
    polly/lib/External/isl/isl_ast_build_private.h
    polly/lib/External/isl/isl_ast_codegen.c
    polly/lib/External/isl/isl_ast_graft.c
    polly/lib/External/isl/isl_ast_graft_private.h
    polly/lib/External/isl/isl_ast_private.h
    polly/lib/External/isl/isl_bernstein.c
    polly/lib/External/isl/isl_bound.c
    polly/lib/External/isl/isl_box.c
    polly/lib/External/isl/isl_coalesce.c
    polly/lib/External/isl/isl_config.h.in
    polly/lib/External/isl/isl_config_post.h
    polly/lib/External/isl/isl_constraint.c
    polly/lib/External/isl/isl_convex_hull.c
    polly/lib/External/isl/isl_ctx.c
    polly/lib/External/isl/isl_dim_map.c
    polly/lib/External/isl/isl_dim_map.h
    polly/lib/External/isl/isl_equalities.c
    polly/lib/External/isl/isl_factorization.c
    polly/lib/External/isl/isl_farkas.c
    polly/lib/External/isl/isl_flow.c
    polly/lib/External/isl/isl_fold.c
    polly/lib/External/isl/isl_hash.c
    polly/lib/External/isl/isl_id.c
    polly/lib/External/isl/isl_id_private.h
    polly/lib/External/isl/isl_id_to_ast_expr.c
    polly/lib/External/isl/isl_id_to_id.c
    polly/lib/External/isl/isl_id_to_pw_aff.c
    polly/lib/External/isl/isl_ilp.c
    polly/lib/External/isl/isl_input.c
    polly/lib/External/isl/isl_list_templ.c
    polly/lib/External/isl/isl_local.c
    polly/lib/External/isl/isl_local.h
    polly/lib/External/isl/isl_local_space.c
    polly/lib/External/isl/isl_local_space_private.h
    polly/lib/External/isl/isl_lp.c
    polly/lib/External/isl/isl_map.c
    polly/lib/External/isl/isl_map_list.c
    polly/lib/External/isl/isl_map_private.h
    polly/lib/External/isl/isl_map_simplify.c
    polly/lib/External/isl/isl_map_subtract.c
    polly/lib/External/isl/isl_mat.c
    polly/lib/External/isl/isl_mat_private.h
    polly/lib/External/isl/isl_morph.c
    polly/lib/External/isl/isl_morph.h
    polly/lib/External/isl/isl_multi_dims.c
    polly/lib/External/isl/isl_multi_macro.h
    polly/lib/External/isl/isl_multi_no_explicit_domain.c
    polly/lib/External/isl/isl_multi_templ.c
    polly/lib/External/isl/isl_options.c
    polly/lib/External/isl/isl_output.c
    polly/lib/External/isl/isl_point.c
    polly/lib/External/isl/isl_point_private.h
    polly/lib/External/isl/isl_polynomial.c
    polly/lib/External/isl/isl_polynomial_private.h
    polly/lib/External/isl/isl_printer.c
    polly/lib/External/isl/isl_pw_macro.h
    polly/lib/External/isl/isl_pw_templ.c
    polly/lib/External/isl/isl_range.c
    polly/lib/External/isl/isl_reordering.c
    polly/lib/External/isl/isl_reordering.h
    polly/lib/External/isl/isl_sample.c
    polly/lib/External/isl/isl_scan.c
    polly/lib/External/isl/isl_schedule_band.c
    polly/lib/External/isl/isl_schedule_band.h
    polly/lib/External/isl/isl_schedule_constraints.c
    polly/lib/External/isl/isl_schedule_constraints.h
    polly/lib/External/isl/isl_schedule_node.c
    polly/lib/External/isl/isl_schedule_read.c
    polly/lib/External/isl/isl_schedule_tree.c
    polly/lib/External/isl/isl_schedule_tree.h
    polly/lib/External/isl/isl_scheduler.c
    polly/lib/External/isl/isl_set_list.c
    polly/lib/External/isl/isl_space.c
    polly/lib/External/isl/isl_space_private.h
    polly/lib/External/isl/isl_srcdir.c.in
    polly/lib/External/isl/isl_stream.c
    polly/lib/External/isl/isl_stride.c
    polly/lib/External/isl/isl_tab.c
    polly/lib/External/isl/isl_tab.h
    polly/lib/External/isl/isl_tab_lexopt_templ.c
    polly/lib/External/isl/isl_tab_pip.c
    polly/lib/External/isl/isl_test.c
    polly/lib/External/isl/isl_test_cpp-checked.cc
    polly/lib/External/isl/isl_test_cpp-generic.cc
    polly/lib/External/isl/isl_test_cpp.cc
    polly/lib/External/isl/isl_test_python.py
    polly/lib/External/isl/isl_transitive_closure.c
    polly/lib/External/isl/isl_union_eval.c
    polly/lib/External/isl/isl_union_map.c
    polly/lib/External/isl/isl_union_map_private.h
    polly/lib/External/isl/isl_union_multi.c
    polly/lib/External/isl/isl_union_single.c
    polly/lib/External/isl/isl_union_templ.c
    polly/lib/External/isl/isl_val.c
    polly/lib/External/isl/isl_val_gmp.c
    polly/lib/External/isl/isl_val_imath.c
    polly/lib/External/isl/isl_val_private.h
    polly/lib/External/isl/isl_val_sioimath.c
    polly/lib/External/isl/isl_vec.c
    polly/lib/External/isl/isl_vertices.c
    polly/lib/External/isl/m4/ax_detect_clang.m4
    polly/lib/External/isl/pip.c
    polly/lib/External/isl/polyhedron_minimize.c
    polly/lib/External/isl/polytope_scan.c
    polly/lib/External/isl/print.c
    polly/lib/External/isl/print_templ.c
    polly/lib/External/isl/python/isl.py.top
    polly/lib/External/isl/test_inputs/codegen/unroll4.c
    polly/lib/Transform/ForwardOpTree.cpp
    polly/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll

Removed: 
    polly/lib/External/isl/all.c
    polly/lib/External/isl/isl_hash_private.h


################################################################################
diff  --git a/polly/include/polly/Support/ISLTools.h b/polly/include/polly/Support/ISLTools.h
index eb57bf581f45..41a9021896bc 100644
--- a/polly/include/polly/Support/ISLTools.h
+++ b/polly/include/polly/Support/ISLTools.h
@@ -32,7 +32,7 @@ struct isl_iterator
   using ElementT = list_element_type<ListT>;
 
   explicit isl_iterator(const ListT &List)
-      : List(&List), Position(List.size()) {}
+      : List(&List), Position(std::max(List.size(), 0)) {}
   isl_iterator(const ListT &List, int Position)
       : List(&List), Position(Position) {}
   isl_iterator &operator=(const isl_iterator &R) = default;

diff  --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index 71bf8a0e6d3a..fe3514cb7ddd 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -916,6 +916,12 @@ void MemoryAccess::realignParams() {
   isl::set Ctx = Statement->getParent()->getContext();
   InvalidDomain = InvalidDomain.gist_params(Ctx);
   AccessRelation = AccessRelation.gist_params(Ctx);
+
+  // Predictable parameter order is required for JSON imports. Ensure alignment
+  // by explicitly calling align_params.
+  isl::space CtxSpace = Ctx.get_space();
+  InvalidDomain = InvalidDomain.align_params(CtxSpace);
+  AccessRelation = AccessRelation.align_params(CtxSpace);
 }
 
 const std::string MemoryAccess::getReductionOperatorStr() const {
@@ -1174,6 +1180,12 @@ void ScopStmt::realignParams() {
   isl::set Ctx = Parent.getContext();
   InvalidDomain = InvalidDomain.gist_params(Ctx);
   Domain = Domain.gist_params(Ctx);
+
+  // Predictable parameter order is required for JSON imports. Ensure alignment
+  // by explicitly calling align_params.
+  isl::space CtxSpace = Ctx.get_space();
+  InvalidDomain = InvalidDomain.align_params(CtxSpace);
+  Domain = Domain.align_params(CtxSpace);
 }
 
 ScopStmt::ScopStmt(Scop &parent, Region &R, StringRef Name,
@@ -1595,6 +1607,8 @@ void Scop::realignParams() {
 
   // Align the parameters of all data structures to the model.
   Context = Context.align_params(Space);
+  AssumedContext = AssumedContext.align_params(Space);
+  InvalidContext = InvalidContext.align_params(Space);
 
   // Bound the size of the fortran array dimensions.
   Context = boundFortranArrayParams(Context, arrays());
@@ -1606,6 +1620,10 @@ void Scop::realignParams() {
     Stmt.realignParams();
   // Simplify the schedule according to the context too.
   Schedule = Schedule.gist_domain_params(getContext());
+
+  // Predictable parameter order is required for JSON imports. Ensure alignment
+  // by explicitly calling align_params.
+  Schedule = Schedule.align_params(Space);
 }
 
 static isl::set simplifyAssumptionContext(isl::set AssumptionContext,

diff  --git a/polly/lib/CodeGen/PPCGCodeGeneration.cpp b/polly/lib/CodeGen/PPCGCodeGeneration.cpp
index 522dc3e3674b..db5546906703 100644
--- a/polly/lib/CodeGen/PPCGCodeGeneration.cpp
+++ b/polly/lib/CodeGen/PPCGCodeGeneration.cpp
@@ -37,6 +37,7 @@
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "isl/union_map.h"
+#include <algorithm>
 
 extern "C" {
 #include "ppcg/cuda.h"
@@ -1780,11 +1781,11 @@ void GPUNodeBuilder::createKernel(__isl_take isl_ast_node *KernelStmt) {
   isl_ast_node_free(KernelStmt);
 
   if (Kernel->n_grid > 1)
-    DeepestParallel =
-        std::max(DeepestParallel, isl_space_dim(Kernel->space, isl_dim_set));
+    DeepestParallel = std::max(
+        DeepestParallel, (unsigned)isl_space_dim(Kernel->space, isl_dim_set));
   else
-    DeepestSequential =
-        std::max(DeepestSequential, isl_space_dim(Kernel->space, isl_dim_set));
+    DeepestSequential = std::max(
+        DeepestSequential, (unsigned)isl_space_dim(Kernel->space, isl_dim_set));
 
   Value *BlockDimX, *BlockDimY, *BlockDimZ;
   std::tie(BlockDimX, BlockDimY, BlockDimZ) = getBlockSizes(Kernel);

diff  --git a/polly/lib/External/CMakeLists.txt b/polly/lib/External/CMakeLists.txt
index 8ffd984e542b..1039079cb49c 100644
--- a/polly/lib/External/CMakeLists.txt
+++ b/polly/lib/External/CMakeLists.txt
@@ -241,6 +241,7 @@ if (POLLY_BUNDLED_ISL)
     isl/isl_scheduler.c
     isl/isl_seq.c
     isl/isl_set_list.c
+    isl/isl_set_to_ast_graft_list.c
     isl/isl_sort.c
     isl/isl_space.c
     isl/isl_stride.c

diff  --git a/polly/lib/External/isl/AUTHORS b/polly/lib/External/isl/AUTHORS
index f2c3393553eb..8ce92234c4f4 100644
--- a/polly/lib/External/isl/AUTHORS
+++ b/polly/lib/External/isl/AUTHORS
@@ -23,7 +23,11 @@ isl was written by
 	    Domaine de Voluceau - Rocquencourt, B.P. 105
 	    78153 Le Chesnay
 	    France
-2015-2016   Polly Labs
+2015-2019   Polly Labs
+2018-2019   Cerebras Systems
+	    175 S San Antonio Rd
+	    Los Altos, CA
+	    USA
 
 Contributions by
 
@@ -33,11 +37,15 @@ Serge Belyshev
 Albert Cohen
 Ray Donnelly
 Johannes Doerfert
+Andi Drebes
+Clement Foyer
 Armin Groesslinger
 Tobias Grosser
+Frederik Harwath
 Alexandre Isoard
 Andreas Kloeckner
 Michael Kruse
+Manjunath Kudlur
 Alexander Matz
 Sebastian Pop
 Louis-Noel Pouchet
@@ -45,6 +53,7 @@ Benoit Pradelle
 Uday Bondhugula
 Andreas Simbuerger
 Malhar Thakkar
+Sergei Trofimovich
 Sven van Haastregt
 Oleksandr Zinenko
 

diff  --git a/polly/lib/External/isl/ChangeLog b/polly/lib/External/isl/ChangeLog
index c09ebdff6136..2193a72a037c 100644
--- a/polly/lib/External/isl/ChangeLog
+++ b/polly/lib/External/isl/ChangeLog
@@ -1,3 +1,26 @@
+version: 0.22.1
+date: Sun Jan 12 10:48:18 CET 2020
+changes:
+	- fix error handling
+---
+version: 0.22
+date: Fri Nov  1 18:39:30 CET 2019
+changes:
+	- improved bindings
+	- scheduler fix involving fixed dimensions
+	- accept ranges in tuples during parsing
+	- add some convenience functions
+---
+version: 0.21
+date: Sat Mar  9 15:25:29 CET 2019
+changes:
+	- preliminary C++ bindings
+	- use incremental scheduler by default
+	- introduce isl_size type
+	- rename isl_ast_op_type to isl_ast_expr_op_type
+	- fix coalescing bugs
+	- use isl_bool to return extra boolean argument
+---
 version: 0.20
 date: Sat Jul 21 18:10:08 CEST 2018
 changes:

diff  --git a/polly/lib/External/isl/GIT_HEAD_ID b/polly/lib/External/isl/GIT_HEAD_ID
index c977f09659da..dea4caca0b26 100644
--- a/polly/lib/External/isl/GIT_HEAD_ID
+++ b/polly/lib/External/isl/GIT_HEAD_ID
@@ -1 +1 @@
-isl-0.20-65-gb822a210
+isl-0.22.1-87-gfee05a13

diff  --git a/polly/lib/External/isl/Makefile.am b/polly/lib/External/isl/Makefile.am
index 6c1729b84cdd..81cfdc91538e 100644
--- a/polly/lib/External/isl/Makefile.am
+++ b/polly/lib/External/isl/Makefile.am
@@ -1,9 +1,11 @@
 if HAVE_CLANG
+if HAVE_CXX11
 MAYBE_INTERFACE = interface
 FORCE:
 interface/extract_interface: FORCE
 	$(MAKE) $(AM_MAKEFLAGS) -C interface extract_interface
 endif
+endif
 SUBDIRS = . $(MAYBE_INTERFACE) doc
 DIST_SUBDIRS = $(MAYBE_INTERFACE) doc
 
@@ -29,16 +31,18 @@ if HAVE_CLANG
 if HAVE_CXX11
   noinst_PROGRAMS += isl_test_cpp-checked isl_test_cpp-checked-conversion
   TESTS += isl_test_cpp-checked isl_test_cpp-checked-conversion
-endif
 if HAVE_PYTHON
   TESTS += isl_test_python.py
+  noinst_PYTHON = interface/isl.py
   isl_test_python.py: interface/isl.py libisl.la
 endif
 endif
+endif
 TEST_EXTENSIONS = .py
 AM_TESTS_ENVIRONMENT = \
 	export PYTHONPATH=interface; \
-	export LD_LIBRARY_PATH=.libs;
+	export ISL_DYLD_LIBRARY_PATH=.libs; \
+	export LD_LIBRARY_PATH=".libs:$(LD_LIBRARY_PATH)";
 PY_LOG_COMPILER = $(PYTHON)
 
 if IMATH_FOR_MP
@@ -85,7 +89,7 @@ endif
 
 includes = -I. -I$(srcdir) -I$(srcdir)/include -Iinclude/
 AM_CPPFLAGS = $(includes) @MP_CPPFLAGS@
-AM_CFLAGS = @WARNING_FLAGS@
+AM_CFLAGS = @WARNING_FLAGS@ @MP_CFLAGS@
 
 libisl_la_SOURCES = \
 	$(MP_SRC) \
@@ -130,7 +134,6 @@ libisl_la_SOURCES = \
 	isl_flow.c \
 	isl_fold.c \
 	isl_hash.c \
-	isl_hash_private.h \
 	isl_id_to_ast_expr.c \
 	isl_id_to_id.c \
 	isl_id_to_pw_aff.c \
@@ -138,6 +141,7 @@ libisl_la_SOURCES = \
 	isl_ilp_private.h \
 	isl_input.c \
 	isl_int.h \
+	isl_local_private.h \
 	isl_local.h \
 	isl_local.c \
 	isl_local_space_private.h \
@@ -197,6 +201,8 @@ libisl_la_SOURCES = \
 	isl_stream_private.h \
 	isl_seq.c \
 	isl_seq.h \
+	isl_set_to_ast_graft_list.c \
+	isl_set_to_ast_graft_list.h \
 	isl_stride.c \
 	isl_tab.c \
 	isl_tab.h \
@@ -290,21 +296,18 @@ isl_closure_LDADD = libisl.la
 isl_closure_SOURCES = \
 	closure.c
 
-isl_test_cpp_CXXFLAGS = @CXX11FLAGS@
 isl_test_cpp_SOURCES = \
 	isl_test_cpp.cc \
 	include/isl/cpp.h
 isl_test_cpp_LDFLAGS = @MP_LDFLAGS@
 isl_test_cpp_LDADD = libisl.la @MP_LIBS@
 
-isl_test_cpp_checked_CXXFLAGS = @CXX11FLAGS@
 isl_test_cpp_checked_SOURCES = \
 	isl_test_cpp-checked.cc \
 	include/isl/cpp-checked.h
 isl_test_cpp_checked_LDFLAGS = @MP_LDFLAGS@
 isl_test_cpp_checked_LDADD = libisl.la @MP_LIBS@
 
-isl_test_cpp_checked_conversion_CXXFLAGS = @CXX11FLAGS@
 isl_test_cpp_checked_conversion_SOURCES = \
 	isl_test_cpp-checked-conversion.cc \
 	include/isl/cpp-checked-conversion.h
@@ -314,11 +317,15 @@ isl_test_cpp_checked_conversion_LDADD = libisl.la @MP_LIBS@
 # dummy library that captures the dependencies on all headers
 # that are relevant for the bindings
 noinst_LIBRARIES = libdep.a
-libdep_a_SOURCES = all.c
+libdep_a_SOURCES = dep.c
 
 if HAVE_CLANG
-interface/isl.py: interface/extract_interface libdep.a python/isl.py.top
-	(cat $(srcdir)/python/isl.py.top && \
+if HAVE_CXX11
+interface/isldlname.py: libisl.la
+	$(AM_V_GEN) $(GREP) dlname $< | $(SED) -e 's/dlname/isl_dlname/' > $@
+interface/isl.py: interface/extract_interface libdep.a python/isl.py.top \
+		interface/isldlname.py
+	(cat interface/isldlname.py $(srcdir)/python/isl.py.top && \
 		interface/extract_interface$(EXEEXT) --language=python \
 			$(includes) $(srcdir)/all.h) \
 			> $@ || (rm $@ && false)
@@ -354,6 +361,7 @@ include/isl/cpp-checked-conversion.h: interface/extract_interface libdep.a \
 		cat $(srcdir)/cpp/cpp-checked-conversion.h.bot) \
 			> $@ || (rm $@ && false)
 endif
+endif
 
 nodist_pkginclude_HEADERS = \
 	include/isl/stdint.h
@@ -420,13 +428,20 @@ pkginclude_HEADERS = \
 	include/isl/vertices.h
 
 if HAVE_CLANG
+if HAVE_CXX11
     CPP_INTERFACES = \
 	include/isl/cpp.h \
 	include/isl/cpp-checked.h \
 	include/isl/cpp-checked-conversion.h
 endif
+endif
 BUILT_SOURCES = gitversion.h $(CPP_INTERFACES)
-CLEANFILES = gitversion.h interface/isl.py $(CPP_INTERFACES)
+CLEANFILES = \
+	gitversion.h \
+	interface/isldlname.py \
+	interface/isl.py \
+	interface/isl.pyc \
+	$(CPP_INTERFACES)
 
 DISTCLEANFILES = \
 	isl-uninstalled.sh \
@@ -438,48 +453,98 @@ DISTCLEANFILES = \
 EXTRA_DIST = \
 	LICENSE \
 	isl_config_post.h \
+	isl_align_params_templ.c \
+	isl_align_params_bin_templ.c \
 	basis_reduction_templ.c \
+	isl_bind_domain_templ.c \
 	bset_to_bmap.c \
 	bset_from_bmap.c \
+	isl_check_named_params_templ.c \
+	check_reparse_templ.c \
+	check_reparse_test_templ.c \
+	check_type_range_templ.c \
+	isl_domain_factor_templ.c \
 	extract_key.c \
+	has_single_reference_templ.c \
+	isl_list_macro.h \
 	isl_list_templ.c \
 	isl_list_templ.h \
+	isl_map_bound_templ.c \
 	isl_map_lexopt_templ.c \
+	isl_maybe_ast_graft_list.h \
 	isl_maybe_map.h \
 	isl_multi_macro.h \
+	isl_multi_bind_templ.c \
 	isl_multi_explicit_domain.c \
 	isl_multi_pw_aff_explicit_domain.c \
 	isl_multi_union_pw_aff_explicit_domain.c \
 	isl_multi_no_explicit_domain.c \
+	isl_multi_no_domain_templ.c \
 	isl_multi_templ.c \
 	isl_multi_templ.h \
+	isl_multi_add_constant_templ.c \
 	isl_multi_align_templ.c \
 	isl_multi_align_set.c \
 	isl_multi_align_union_set.c \
 	isl_multi_apply_templ.c \
 	isl_multi_apply_set.c \
 	isl_multi_apply_union_set.c \
+	isl_multi_arith_templ.c \
+	isl_multi_bind_domain_templ.c \
 	isl_multi_cmp.c \
 	isl_multi_coalesce.c \
+	isl_multi_dim_id_templ.c \
 	isl_multi_dims.c \
+	isl_multi_domain_templ.c \
 	isl_multi_floor.c \
+	isl_multi_from_base_templ.c \
 	isl_multi_gist.c \
 	isl_multi_hash.c \
 	isl_multi_intersect.c \
+	isl_multi_identity_templ.c \
+	isl_multi_locals_templ.c \
+	isl_multi_move_dims_templ.c \
+	isl_multi_nan_templ.c \
+	isl_multi_param_templ.c \
+	isl_multi_product_templ.c \
+	isl_multi_read_no_explicit_domain_templ.c \
+	isl_multi_splice_templ.c \
+	isl_multi_tuple_id_templ.c \
+	isl_multi_zero_templ.c \
+	opt_type.h \
 	print_templ.c \
 	print_templ_yaml.c \
+	print_yaml_field_templ.c \
 	isl_power_templ.c \
+	isl_project_out_all_params_templ.c \
 	isl_pw_macro.h \
 	isl_pw_templ.c \
 	isl_pw_templ.h \
+	isl_pw_add_constant_templ.c \
+	isl_pw_add_constant_multi_val_templ.c \
+	isl_pw_add_constant_val_templ.c \
+	isl_pw_bind_domain_templ.c \
 	isl_pw_eval.c \
 	isl_pw_hash.c \
+	isl_pw_insert_dims_templ.c \
+	isl_pw_lift_templ.c \
+	isl_pw_morph_templ.c \
+	isl_pw_move_dims_templ.c \
+	isl_pw_neg_templ.c \
+	isl_pw_opt_templ.c \
+	isl_pw_pullback_templ.c \
+	isl_pw_sub_templ.c \
 	isl_pw_union_opt.c \
 	read_in_string_templ.c \
 	set_to_map.c \
 	set_from_map.c \
 	set_list_from_map_list_inl.c \
 	isl_tab_lexopt_templ.c \
+	isl_test_list_templ.c \
+	isl_test_plain_equal_templ.c \
+	isl_type_check_equal_space_templ.c \
+	isl_type_has_equal_space_bin_templ.c \
+	isl_type_has_equal_space_templ.c \
 	uset_to_umap.c \
 	uset_from_umap.c \
 	isl_union_macro.h \
@@ -510,12 +575,7 @@ EXTRA_DIST = \
 	isl_test_python.py \
 	test_inputs
 
-if HAVE_CLANG
-dist-hook: interface/isl.py
-	cp interface/isl.py $(distdir)/interface/
-else
 dist-hook:
-endif
 	echo @GIT_HEAD_VERSION@ > $(distdir)/GIT_HEAD_ID
 	(cd doc; make manual.pdf)
 	cp doc/manual.pdf $(distdir)/doc/

diff  --git a/polly/lib/External/isl/Makefile.in b/polly/lib/External/isl/Makefile.in
index 0f962532b021..114136b5b59d 100644
--- a/polly/lib/External/isl/Makefile.in
+++ b/polly/lib/External/isl/Makefile.in
@@ -108,7 +108,7 @@ TESTS = isl_test$(EXEEXT) codegen_test.sh pip_test.sh bound_test.sh \
 @HAVE_CPP_ISL_H_TRUE@@HAVE_CXX11_TRUE at am__append_2 = isl_test_cpp
 @HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at am__append_3 = isl_test_cpp-checked isl_test_cpp-checked-conversion
 @HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at am__append_4 = isl_test_cpp-checked isl_test_cpp-checked-conversion
- at HAVE_CLANG_TRUE@@HAVE_PYTHON_TRUE at am__append_5 = isl_test_python.py
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@@HAVE_PYTHON_TRUE at am__append_5 = isl_test_python.py
 @IMATH_FOR_MP_TRUE at am__append_6 = isl_test_imath
 @IMATH_FOR_MP_TRUE at am__append_7 = isl_test_imath
 @IMATH_FOR_MP_TRUE@@SMALL_INT_OPT_TRUE at am__append_8 = isl_int_sioimath.h \
@@ -126,6 +126,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
 	$(top_srcdir)/m4/ax_create_stdint_h.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11_no_override.m4 \
 	$(top_srcdir)/m4/ax_detect_clang.m4 \
 	$(top_srcdir)/m4/ax_detect_git_head.m4 \
 	$(top_srcdir)/m4/ax_detect_gmp.m4 \
@@ -141,8 +142,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
-	$(am__configure_deps) $(am__pkginclude_HEADERS_DIST) \
-	$(am__DIST_COMMON)
+	$(am__configure_deps) $(am__noinst_PYTHON_DIST) \
+	$(am__pkginclude_HEADERS_DIST) $(am__DIST_COMMON)
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(install_sh) -d
@@ -158,7 +159,7 @@ am__v_AR_0 = @echo "  AR      " $@;
 am__v_AR_1 = 
 libdep_a_AR = $(AR) $(ARFLAGS)
 libdep_a_LIBADD =
-am_libdep_a_OBJECTS = all.$(OBJEXT)
+am_libdep_a_OBJECTS = dep.$(OBJEXT)
 libdep_a_OBJECTS = $(am_libdep_a_OBJECTS)
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
@@ -208,9 +209,9 @@ am__libisl_la_SOURCES_DIST = mp_get_memory_functions.c isl_int_gmp.h \
 	isl_convex_hull.c isl_ctx.c isl_ctx_private.h isl_deprecated.c \
 	isl_dim_map.h isl_dim_map.c isl_equalities.c isl_equalities.h \
 	isl_factorization.c isl_factorization.h isl_farkas.c isl_ffs.c \
-	isl_flow.c isl_fold.c isl_hash.c isl_hash_private.h \
-	isl_id_to_ast_expr.c isl_id_to_id.c isl_id_to_pw_aff.c \
-	isl_ilp.c isl_ilp_private.h isl_input.c isl_int.h isl_local.h \
+	isl_flow.c isl_fold.c isl_hash.c isl_id_to_ast_expr.c \
+	isl_id_to_id.c isl_id_to_pw_aff.c isl_ilp.c isl_ilp_private.h \
+	isl_input.c isl_int.h isl_local_private.h isl_local.h \
 	isl_local.c isl_local_space_private.h isl_local_space.c \
 	isl_lp.c isl_lp_private.h isl_map.c isl_map_list.c \
 	isl_map_simplify.c isl_map_subtract.c isl_map_private.h \
@@ -227,9 +228,10 @@ am__libisl_la_SOURCES_DIST = mp_get_memory_functions.c isl_int_gmp.h \
 	isl_schedule_constraints.c isl_schedule_constraints.h \
 	isl_scheduler.c isl_set_list.c isl_sort.c isl_sort.h \
 	isl_space.c isl_space_private.h isl_stream.c \
-	isl_stream_private.h isl_seq.c isl_seq.h isl_stride.c \
-	isl_tab.c isl_tab.h isl_tab_pip.c isl_tarjan.c isl_tarjan.h \
-	isl_transitive_closure.c isl_union_map.c \
+	isl_stream_private.h isl_seq.c isl_seq.h \
+	isl_set_to_ast_graft_list.c isl_set_to_ast_graft_list.h \
+	isl_stride.c isl_tab.c isl_tab.h isl_tab_pip.c isl_tarjan.c \
+	isl_tarjan.h isl_transitive_closure.c isl_union_map.c \
 	isl_union_map_private.h isl_union_set_private.h isl_val.c \
 	isl_val_private.h isl_vec_private.h isl_vec.c isl_version.c \
 	isl_vertices_private.h isl_vertices.c isl_yaml.h
@@ -267,9 +269,10 @@ am_libisl_la_OBJECTS = $(am__objects_4) isl_aff.lo isl_aff_map.lo \
 	isl_schedule_read.lo isl_schedule_tree.lo \
 	isl_schedule_constraints.lo isl_scheduler.lo isl_set_list.lo \
 	isl_sort.lo isl_space.lo isl_stream.lo isl_seq.lo \
-	isl_stride.lo isl_tab.lo isl_tab_pip.lo isl_tarjan.lo \
-	isl_transitive_closure.lo isl_union_map.lo isl_val.lo \
-	isl_vec.lo isl_version.lo isl_vertices.lo
+	isl_set_to_ast_graft_list.lo isl_stride.lo isl_tab.lo \
+	isl_tab_pip.lo isl_tarjan.lo isl_transitive_closure.lo \
+	isl_union_map.lo isl_val.lo isl_vec.lo isl_version.lo \
+	isl_vertices.lo
 libisl_la_OBJECTS = $(am_libisl_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -358,27 +361,27 @@ isl_test_DEPENDENCIES = libisl.la
 isl_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(isl_test_LDFLAGS) $(LDFLAGS) -o $@
-am_isl_test_cpp_OBJECTS = isl_test_cpp-isl_test_cpp.$(OBJEXT)
+am_isl_test_cpp_OBJECTS = isl_test_cpp.$(OBJEXT)
 isl_test_cpp_OBJECTS = $(am_isl_test_cpp_OBJECTS)
 isl_test_cpp_DEPENDENCIES = libisl.la
 isl_test_cpp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(isl_test_cpp_CXXFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
 	$(CXXFLAGS) $(isl_test_cpp_LDFLAGS) $(LDFLAGS) -o $@
-am_isl_test_cpp_checked_OBJECTS =  \
-	isl_test_cpp_checked-isl_test_cpp-checked.$(OBJEXT)
+am_isl_test_cpp_checked_OBJECTS = isl_test_cpp-checked.$(OBJEXT)
 isl_test_cpp_checked_OBJECTS = $(am_isl_test_cpp_checked_OBJECTS)
 isl_test_cpp_checked_DEPENDENCIES = libisl.la
 isl_test_cpp_checked_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
-	$(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) \
-	$(isl_test_cpp_checked_LDFLAGS) $(LDFLAGS) -o $@
-am_isl_test_cpp_checked_conversion_OBJECTS = isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.$(OBJEXT)
+	$(AM_CXXFLAGS) $(CXXFLAGS) $(isl_test_cpp_checked_LDFLAGS) \
+	$(LDFLAGS) -o $@
+am_isl_test_cpp_checked_conversion_OBJECTS =  \
+	isl_test_cpp-checked-conversion.$(OBJEXT)
 isl_test_cpp_checked_conversion_OBJECTS =  \
 	$(am_isl_test_cpp_checked_conversion_OBJECTS)
 isl_test_cpp_checked_conversion_DEPENDENCIES = libisl.la
 isl_test_cpp_checked_conversion_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
-	$(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS) \
 	$(isl_test_cpp_checked_conversion_LDFLAGS) $(LDFLAGS) -o $@
 isl_test_imath_SOURCES = isl_test_imath.c
 isl_test_imath_OBJECTS = isl_test_imath.$(OBJEXT)
@@ -480,6 +483,9 @@ am__can_run_installinfo = \
     n|no|NO) false;; \
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
+am__noinst_PYTHON_DIST = interface/isl.py
+am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
+py_compile = $(top_srcdir)/py-compile
 DATA = $(pkgconfig_DATA)
 am__pkginclude_HEADERS_DIST = include/isl/cpp.h include/isl/val_gmp.h \
 	include/isl/aff.h include/isl/aff_type.h include/isl/arg.h \
@@ -717,7 +723,7 @@ am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/bound_test.sh.in \
 	$(srcdir)/isl_config.h.in $(srcdir)/isl_srcdir.c.in \
 	$(srcdir)/pip_test.sh.in $(srcdir)/schedule_test.sh.in AUTHORS \
 	ChangeLog README compile config.guess config.sub depcomp \
-	install-sh ltmain.sh missing test-driver
+	install-sh ltmain.sh missing py-compile test-driver
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -774,13 +780,15 @@ CFLAGS = @CFLAGS@
 CLANG_CXXFLAGS = @CLANG_CXXFLAGS@
 CLANG_LDFLAGS = @CLANG_LDFLAGS@
 CLANG_LIBS = @CLANG_LIBS@
+CLANG_RFLAG = @CLANG_RFLAG@
+CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
-CXX11FLAGS = @CXX11FLAGS@
 CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
+CYGPATH = @CYGPATH@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -810,12 +818,14 @@ LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIB_CLANG_EDIT = @LIB_CLANG_EDIT@
 LIPO = @LIPO@
+LLVM_CONFIG = @LLVM_CONFIG@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
 MKDIR_P = @MKDIR_P@
+MP_CFLAGS = @MP_CFLAGS@
 MP_CPPFLAGS = @MP_CPPFLAGS@
 MP_LDFLAGS = @MP_LDFLAGS@
 MP_LIBS = @MP_LIBS@
@@ -823,6 +833,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OS_SRCDIR = @OS_SRCDIR@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -885,7 +896,6 @@ infodir = @infodir@
 install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
-llvm_config_found = @llvm_config_found@
 localedir = @localedir@
 localstatedir = @localstatedir@
 mandir = @mandir@
@@ -911,17 +921,19 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 versioninfo = @versioninfo@
- at HAVE_CLANG_TRUE@MAYBE_INTERFACE = interface
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at MAYBE_INTERFACE = interface
 SUBDIRS = . $(MAYBE_INTERFACE) doc
 DIST_SUBDIRS = $(MAYBE_INTERFACE) doc
 ACLOCAL_AMFLAGS = -I m4
 AUTOMAKE_OPTIONS = nostdinc subdir-objects
 lib_LTLIBRARIES = libisl.la
 @HAVE_CPP_ISL_H_TRUE at CPP_H = include/isl/cpp.h
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@@HAVE_PYTHON_TRUE at noinst_PYTHON = interface/isl.py
 TEST_EXTENSIONS = .py
 AM_TESTS_ENVIRONMENT = \
 	export PYTHONPATH=interface; \
-	export LD_LIBRARY_PATH=.libs;
+	export ISL_DYLD_LIBRARY_PATH=.libs; \
+	export LD_LIBRARY_PATH=".libs:$(LD_LIBRARY_PATH)";
 
 PY_LOG_COMPILER = $(PYTHON)
 @GMP_FOR_MP_TRUE at MP_SRC = \
@@ -941,7 +953,7 @@ PY_LOG_COMPILER = $(PYTHON)
 @GMP_FOR_MP_TRUE@@NEED_GET_MEMORY_FUNCTIONS_TRUE at GET_MEMORY_FUNCTIONS = mp_get_memory_functions.c
 includes = -I. -I$(srcdir) -I$(srcdir)/include -Iinclude/
 AM_CPPFLAGS = $(includes) @MP_CPPFLAGS@
-AM_CFLAGS = @WARNING_FLAGS@
+AM_CFLAGS = @WARNING_FLAGS@ @MP_CFLAGS@
 libisl_la_SOURCES = \
 	$(MP_SRC) \
 	isl_aff.c \
@@ -985,7 +997,6 @@ libisl_la_SOURCES = \
 	isl_flow.c \
 	isl_fold.c \
 	isl_hash.c \
-	isl_hash_private.h \
 	isl_id_to_ast_expr.c \
 	isl_id_to_id.c \
 	isl_id_to_pw_aff.c \
@@ -993,6 +1004,7 @@ libisl_la_SOURCES = \
 	isl_ilp_private.h \
 	isl_input.c \
 	isl_int.h \
+	isl_local_private.h \
 	isl_local.h \
 	isl_local.c \
 	isl_local_space_private.h \
@@ -1052,6 +1064,8 @@ libisl_la_SOURCES = \
 	isl_stream_private.h \
 	isl_seq.c \
 	isl_seq.h \
+	isl_set_to_ast_graft_list.c \
+	isl_set_to_ast_graft_list.h \
 	isl_stride.c \
 	isl_tab.c \
 	isl_tab.h \
@@ -1141,21 +1155,18 @@ isl_closure_LDADD = libisl.la
 isl_closure_SOURCES = \
 	closure.c
 
-isl_test_cpp_CXXFLAGS = @CXX11FLAGS@
 isl_test_cpp_SOURCES = \
 	isl_test_cpp.cc \
 	include/isl/cpp.h
 
 isl_test_cpp_LDFLAGS = @MP_LDFLAGS@
 isl_test_cpp_LDADD = libisl.la @MP_LIBS@
-isl_test_cpp_checked_CXXFLAGS = @CXX11FLAGS@
 isl_test_cpp_checked_SOURCES = \
 	isl_test_cpp-checked.cc \
 	include/isl/cpp-checked.h
 
 isl_test_cpp_checked_LDFLAGS = @MP_LDFLAGS@
 isl_test_cpp_checked_LDADD = libisl.la @MP_LIBS@
-isl_test_cpp_checked_conversion_CXXFLAGS = @CXX11FLAGS@
 isl_test_cpp_checked_conversion_SOURCES = \
 	isl_test_cpp-checked-conversion.cc \
 	include/isl/cpp-checked-conversion.h
@@ -1166,7 +1177,7 @@ isl_test_cpp_checked_conversion_LDADD = libisl.la @MP_LIBS@
 # dummy library that captures the dependencies on all headers
 # that are relevant for the bindings
 noinst_LIBRARIES = libdep.a
-libdep_a_SOURCES = all.c
+libdep_a_SOURCES = dep.c
 nodist_pkginclude_HEADERS = \
 	include/isl/stdint.h
 
@@ -1232,13 +1243,19 @@ pkginclude_HEADERS = \
 	include/isl/version.h \
 	include/isl/vertices.h
 
- at HAVE_CLANG_TRUE@CPP_INTERFACES = \
- at HAVE_CLANG_TRUE@	include/isl/cpp.h \
- at HAVE_CLANG_TRUE@	include/isl/cpp-checked.h \
- at HAVE_CLANG_TRUE@	include/isl/cpp-checked-conversion.h
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at CPP_INTERFACES = \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	include/isl/cpp.h \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	include/isl/cpp-checked.h \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	include/isl/cpp-checked-conversion.h
 
 BUILT_SOURCES = gitversion.h $(CPP_INTERFACES)
-CLEANFILES = gitversion.h interface/isl.py $(CPP_INTERFACES)
+CLEANFILES = \
+	gitversion.h \
+	interface/isldlname.py \
+	interface/isl.py \
+	interface/isl.pyc \
+	$(CPP_INTERFACES)
+
 DISTCLEANFILES = \
 	isl-uninstalled.sh \
 	isl-uninstalled.pc \
@@ -1249,48 +1266,98 @@ DISTCLEANFILES = \
 EXTRA_DIST = \
 	LICENSE \
 	isl_config_post.h \
+	isl_align_params_templ.c \
+	isl_align_params_bin_templ.c \
 	basis_reduction_templ.c \
+	isl_bind_domain_templ.c \
 	bset_to_bmap.c \
 	bset_from_bmap.c \
+	isl_check_named_params_templ.c \
+	check_reparse_templ.c \
+	check_reparse_test_templ.c \
+	check_type_range_templ.c \
+	isl_domain_factor_templ.c \
 	extract_key.c \
+	has_single_reference_templ.c \
+	isl_list_macro.h \
 	isl_list_templ.c \
 	isl_list_templ.h \
+	isl_map_bound_templ.c \
 	isl_map_lexopt_templ.c \
+	isl_maybe_ast_graft_list.h \
 	isl_maybe_map.h \
 	isl_multi_macro.h \
+	isl_multi_bind_templ.c \
 	isl_multi_explicit_domain.c \
 	isl_multi_pw_aff_explicit_domain.c \
 	isl_multi_union_pw_aff_explicit_domain.c \
 	isl_multi_no_explicit_domain.c \
+	isl_multi_no_domain_templ.c \
 	isl_multi_templ.c \
 	isl_multi_templ.h \
+	isl_multi_add_constant_templ.c \
 	isl_multi_align_templ.c \
 	isl_multi_align_set.c \
 	isl_multi_align_union_set.c \
 	isl_multi_apply_templ.c \
 	isl_multi_apply_set.c \
 	isl_multi_apply_union_set.c \
+	isl_multi_arith_templ.c \
+	isl_multi_bind_domain_templ.c \
 	isl_multi_cmp.c \
 	isl_multi_coalesce.c \
+	isl_multi_dim_id_templ.c \
 	isl_multi_dims.c \
+	isl_multi_domain_templ.c \
 	isl_multi_floor.c \
+	isl_multi_from_base_templ.c \
 	isl_multi_gist.c \
 	isl_multi_hash.c \
 	isl_multi_intersect.c \
+	isl_multi_identity_templ.c \
+	isl_multi_locals_templ.c \
+	isl_multi_move_dims_templ.c \
+	isl_multi_nan_templ.c \
+	isl_multi_param_templ.c \
+	isl_multi_product_templ.c \
+	isl_multi_read_no_explicit_domain_templ.c \
+	isl_multi_splice_templ.c \
+	isl_multi_tuple_id_templ.c \
+	isl_multi_zero_templ.c \
+	opt_type.h \
 	print_templ.c \
 	print_templ_yaml.c \
+	print_yaml_field_templ.c \
 	isl_power_templ.c \
+	isl_project_out_all_params_templ.c \
 	isl_pw_macro.h \
 	isl_pw_templ.c \
 	isl_pw_templ.h \
+	isl_pw_add_constant_templ.c \
+	isl_pw_add_constant_multi_val_templ.c \
+	isl_pw_add_constant_val_templ.c \
+	isl_pw_bind_domain_templ.c \
 	isl_pw_eval.c \
 	isl_pw_hash.c \
+	isl_pw_insert_dims_templ.c \
+	isl_pw_lift_templ.c \
+	isl_pw_morph_templ.c \
+	isl_pw_move_dims_templ.c \
+	isl_pw_neg_templ.c \
+	isl_pw_opt_templ.c \
+	isl_pw_pullback_templ.c \
+	isl_pw_sub_templ.c \
 	isl_pw_union_opt.c \
 	read_in_string_templ.c \
 	set_to_map.c \
 	set_from_map.c \
 	set_list_from_map_list_inl.c \
 	isl_tab_lexopt_templ.c \
+	isl_test_list_templ.c \
+	isl_test_plain_equal_templ.c \
+	isl_type_check_equal_space_templ.c \
+	isl_type_has_equal_space_bin_templ.c \
+	isl_type_has_equal_space_templ.c \
 	uset_to_umap.c \
 	uset_from_umap.c \
 	isl_union_macro.h \
@@ -1540,12 +1607,12 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/all.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/basis_reduction_tab.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/bound.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/closure.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/codegen.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dep.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/flow.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/flow_cmp.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_aff.Plo at am__quote@
@@ -1612,6 +1679,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_scheduler.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_seq.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_set_list.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_set_to_ast_graft_list.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_sort.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_space.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_stream.Plo at am__quote@
@@ -1620,9 +1688,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_tab_pip.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_tarjan.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_cpp-isl_test_cpp.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_cpp-checked-conversion.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_cpp-checked.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_cpp.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_imath.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_test_int.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/isl_transitive_closure.Plo at am__quote@
@@ -1695,48 +1763,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
 
-isl_test_cpp-isl_test_cpp.o: isl_test_cpp.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp-isl_test_cpp.o -MD -MP -MF $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo -c -o isl_test_cpp-isl_test_cpp.o `test -f 'isl_test_cpp.cc' || echo '$(srcdir)/'`isl_test_cpp.cc
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo $(DEPDIR)/isl_test_cpp-isl_test_cpp.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp.cc' object='isl_test_cpp-isl_test_cpp.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp-isl_test_cpp.o `test -f 'isl_test_cpp.cc' || echo '$(srcdir)/'`isl_test_cpp.cc
-
-isl_test_cpp-isl_test_cpp.obj: isl_test_cpp.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp-isl_test_cpp.obj -MD -MP -MF $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo -c -o isl_test_cpp-isl_test_cpp.obj `if test -f 'isl_test_cpp.cc'; then $(CYGPATH_W) 'isl_test_cpp.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp.cc'; fi`
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp-isl_test_cpp.Tpo $(DEPDIR)/isl_test_cpp-isl_test_cpp.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp.cc' object='isl_test_cpp-isl_test_cpp.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp-isl_test_cpp.obj `if test -f 'isl_test_cpp.cc'; then $(CYGPATH_W) 'isl_test_cpp.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp.cc'; fi`
-
-isl_test_cpp_checked-isl_test_cpp-checked.o: isl_test_cpp-checked.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked-isl_test_cpp-checked.o -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo -c -o isl_test_cpp_checked-isl_test_cpp-checked.o `test -f 'isl_test_cpp-checked.cc' || echo '$(srcdir)/'`isl_test_cpp-checked.cc
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked.cc' object='isl_test_cpp_checked-isl_test_cpp-checked.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked-isl_test_cpp-checked.o `test -f 'isl_test_cpp-checked.cc' || echo '$(srcdir)/'`isl_test_cpp-checked.cc
-
-isl_test_cpp_checked-isl_test_cpp-checked.obj: isl_test_cpp-checked.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked-isl_test_cpp-checked.obj -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo -c -o isl_test_cpp_checked-isl_test_cpp-checked.obj `if test -f 'isl_test_cpp-checked.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked.cc'; fi`
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Tpo $(DEPDIR)/isl_test_cpp_checked-isl_test_cpp-checked.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked.cc' object='isl_test_cpp_checked-isl_test_cpp-checked.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked-isl_test_cpp-checked.obj `if test -f 'isl_test_cpp-checked.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked.cc'; fi`
-
-isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o: isl_test_cpp-checked-conversion.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o `test -f 'isl_test_cpp-checked-conversion.cc' || echo '$(srcdir)/'`isl_test_cpp-checked-conversion.cc
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked-conversion.cc' object='isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.o `test -f 'isl_test_cpp-checked-conversion.cc' || echo '$(srcdir)/'`isl_test_cpp-checked-conversion.cc
-
-isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj: isl_test_cpp-checked-conversion.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -MT isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj -MD -MP -MF $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj `if test -f 'isl_test_cpp-checked-conversion.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked-conversion.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked-conversion.cc'; fi`
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Tpo $(DEPDIR)/isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='isl_test_cpp-checked-conversion.cc' object='isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(isl_test_cpp_checked_conversion_CXXFLAGS) $(CXXFLAGS) -c -o isl_test_cpp_checked_conversion-isl_test_cpp-checked-conversion.obj `if test -f 'isl_test_cpp-checked-conversion.cc'; then $(CYGPATH_W) 'isl_test_cpp-checked-conversion.cc'; else $(CYGPATH_W) '$(srcdir)/isl_test_cpp-checked-conversion.cc'; fi`
-
 mostlyclean-libtool:
 	-rm -f *.lo
 
@@ -2497,51 +2523,52 @@ uninstall-am: uninstall-libLTLIBRARIES uninstall-local \
 
 .PRECIOUS: Makefile
 
- at HAVE_CLANG_TRUE@FORCE:
- at HAVE_CLANG_TRUE@interface/extract_interface: FORCE
- at HAVE_CLANG_TRUE@	$(MAKE) $(AM_MAKEFLAGS) -C interface extract_interface
- at HAVE_CLANG_TRUE@@HAVE_PYTHON_TRUE@  isl_test_python.py: interface/isl.py libisl.la
-
- at HAVE_CLANG_TRUE@interface/isl.py: interface/extract_interface libdep.a python/isl.py.top
- at HAVE_CLANG_TRUE@	(cat $(srcdir)/python/isl.py.top && \
- at HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) --language=python \
- at HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h) \
- at HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
-
- at HAVE_CLANG_TRUE@include/isl/cpp.h: interface/extract_interface libdep.a \
- at HAVE_CLANG_TRUE@		cpp/cpp.h.top cpp/cpp.h.pre cpp/cpp.h.bot
- at HAVE_CLANG_TRUE@	$(MKDIR_P) "include/isl/cpp" && \
- at HAVE_CLANG_TRUE@	(cat $(srcdir)/cpp/cpp.h.top $(srcdir)/all.h \
- at HAVE_CLANG_TRUE@	    $(srcdir)/cpp/cpp.h.pre && \
- at HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) --language=cpp \
- at HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h && \
- at HAVE_CLANG_TRUE@		cat $(srcdir)/cpp/cpp.h.bot) \
- at HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
-
- at HAVE_CLANG_TRUE@include/isl/cpp-checked.h: interface/extract_interface libdep.a \
- at HAVE_CLANG_TRUE@		cpp/cpp-checked.h.top \
- at HAVE_CLANG_TRUE@		cpp/cpp-checked.h.pre cpp/cpp-checked.h.bot
- at HAVE_CLANG_TRUE@	(cat $(srcdir)/cpp/cpp-checked.h.top $(srcdir)/all.h \
- at HAVE_CLANG_TRUE@	    $(srcdir)/cpp/cpp-checked.h.pre && \
- at HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) \
- at HAVE_CLANG_TRUE@			--language=cpp-checked \
- at HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h && \
- at HAVE_CLANG_TRUE@		cat $(srcdir)/cpp/cpp-checked.h.bot) \
- at HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
-
- at HAVE_CLANG_TRUE@include/isl/cpp-checked-conversion.h: interface/extract_interface libdep.a \
- at HAVE_CLANG_TRUE@		cpp/cpp-checked-conversion.h.top \
- at HAVE_CLANG_TRUE@		cpp/cpp-checked-conversion.h.bot
- at HAVE_CLANG_TRUE@	(cat $(srcdir)/cpp/cpp-checked-conversion.h.top && \
- at HAVE_CLANG_TRUE@		interface/extract_interface$(EXEEXT) \
- at HAVE_CLANG_TRUE@			--language=cpp-checked-conversion \
- at HAVE_CLANG_TRUE@			$(includes) $(srcdir)/all.h && \
- at HAVE_CLANG_TRUE@		cat $(srcdir)/cpp/cpp-checked-conversion.h.bot) \
- at HAVE_CLANG_TRUE@			> $@ || (rm $@ && false)
-
- at HAVE_CLANG_TRUE@dist-hook: interface/isl.py
- at HAVE_CLANG_TRUE@	cp interface/isl.py $(distdir)/interface/
- at HAVE_CLANG_FALSE@dist-hook:
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at FORCE:
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at interface/extract_interface: FORCE
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	$(MAKE) $(AM_MAKEFLAGS) -C interface extract_interface
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@@HAVE_PYTHON_TRUE@  isl_test_python.py: interface/isl.py libisl.la
+
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at interface/isldlname.py: libisl.la
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	$(AM_V_GEN) $(GREP) dlname $< | $(SED) -e 's/dlname/isl_dlname/' > $@
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at interface/isl.py: interface/extract_interface libdep.a python/isl.py.top \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		interface/isldlname.py
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	(cat interface/isldlname.py $(srcdir)/python/isl.py.top && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		interface/extract_interface$(EXEEXT) --language=python \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			$(includes) $(srcdir)/all.h) \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			> $@ || (rm $@ && false)
+
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at include/isl/cpp.h: interface/extract_interface libdep.a \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cpp/cpp.h.top cpp/cpp.h.pre cpp/cpp.h.bot
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	$(MKDIR_P) "include/isl/cpp" && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	(cat $(srcdir)/cpp/cpp.h.top $(srcdir)/all.h \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	    $(srcdir)/cpp/cpp.h.pre && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		interface/extract_interface$(EXEEXT) --language=cpp \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			$(includes) $(srcdir)/all.h && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cat $(srcdir)/cpp/cpp.h.bot) \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			> $@ || (rm $@ && false)
+
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at include/isl/cpp-checked.h: interface/extract_interface libdep.a \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cpp/cpp-checked.h.top \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cpp/cpp-checked.h.pre cpp/cpp-checked.h.bot
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	(cat $(srcdir)/cpp/cpp-checked.h.top $(srcdir)/all.h \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	    $(srcdir)/cpp/cpp-checked.h.pre && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		interface/extract_interface$(EXEEXT) \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			--language=cpp-checked \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			$(includes) $(srcdir)/all.h && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cat $(srcdir)/cpp/cpp-checked.h.bot) \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			> $@ || (rm $@ && false)
+
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE at include/isl/cpp-checked-conversion.h: interface/extract_interface libdep.a \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cpp/cpp-checked-conversion.h.top \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cpp/cpp-checked-conversion.h.bot
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@	(cat $(srcdir)/cpp/cpp-checked-conversion.h.top && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		interface/extract_interface$(EXEEXT) \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			--language=cpp-checked-conversion \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			$(includes) $(srcdir)/all.h && \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@		cat $(srcdir)/cpp/cpp-checked-conversion.h.bot) \
+ at HAVE_CLANG_TRUE@@HAVE_CXX11_TRUE@			> $@ || (rm $@ && false)
+
+dist-hook:
 	echo @GIT_HEAD_VERSION@ > $(distdir)/GIT_HEAD_ID
 	(cd doc; make manual.pdf)
 	cp doc/manual.pdf $(distdir)/doc/

diff  --git a/polly/lib/External/isl/README b/polly/lib/External/isl/README
index 9f48a0a76f9c..e7a5f7d20c7d 100644
--- a/polly/lib/External/isl/README
+++ b/polly/lib/External/isl/README
@@ -21,10 +21,10 @@ need to do
 
 For more information, see doc/user.pod or the generated documentation.
 
-New releases are announced on http://freecode.com/projects/isl
+New releases are announced on http://groups.google.com/group/isl-announce
 
 If you use isl, you can let me know by stacking
-https://www.ohloh.net/p/isl on ohloh.
+https://www.openhub.net/p/isl on Open Hub.
 
 For bug reports, feature requests and questions,
 contact http://groups.google.com/group/isl-development

diff  --git a/polly/lib/External/isl/aclocal.m4 b/polly/lib/External/isl/aclocal.m4
index 2a7bc3536e12..3387306e41cf 100644
--- a/polly/lib/External/isl/aclocal.m4
+++ b/polly/lib/External/isl/aclocal.m4
@@ -1394,6 +1394,7 @@ m4_include([m4/ax_create_pkgconfig_info.m4])
 m4_include([m4/ax_create_stdint_h.m4])
 m4_include([m4/ax_cxx_compile_stdcxx.m4])
 m4_include([m4/ax_cxx_compile_stdcxx_11.m4])
+m4_include([m4/ax_cxx_compile_stdcxx_11_no_override.m4])
 m4_include([m4/ax_detect_clang.m4])
 m4_include([m4/ax_detect_git_head.m4])
 m4_include([m4/ax_detect_gmp.m4])

diff  --git a/polly/lib/External/isl/all.h b/polly/lib/External/isl/all.h
index ea0b4982f590..dea77ddd02ed 100644
--- a/polly/lib/External/isl/all.h
+++ b/polly/lib/External/isl/all.h
@@ -1,3 +1,5 @@
+#include <isl/id.h>
+#include <isl/space.h>
 #include <isl/val.h>
 #include <isl/aff.h>
 #include <isl/set.h>
@@ -9,3 +11,4 @@
 #include <isl/schedule.h>
 #include <isl/schedule_node.h>
 #include <isl/ast_build.h>
+#include <isl/fixed_box.h>

diff  --git a/polly/lib/External/isl/basis_reduction_templ.c b/polly/lib/External/isl/basis_reduction_templ.c
index a5da1e6dbb27..5c03eab18f35 100644
--- a/polly/lib/External/isl/basis_reduction_templ.c
+++ b/polly/lib/External/isl/basis_reduction_templ.c
@@ -319,16 +319,10 @@ __isl_give isl_mat *isl_basic_set_reduced_basis(__isl_keep isl_basic_set *bset)
 	struct isl_mat *basis;
 	struct isl_tab *tab;
 
-	if (!bset)
+	if (isl_basic_set_check_no_locals(bset) < 0 ||
+	    isl_basic_set_check_no_params(bset) < 0)
 		return NULL;
 
-	if (isl_basic_set_dim(bset, isl_dim_div) != 0)
-		isl_die(bset->ctx, isl_error_invalid,
-			"no integer division allowed", return NULL);
-	if (isl_basic_set_dim(bset, isl_dim_param) != 0)
-		isl_die(bset->ctx, isl_error_invalid,
-			"no parameters allowed", return NULL);
-
 	tab = isl_tab_from_basic_set(bset, 0);
 	if (!tab)
 		return NULL;
@@ -337,7 +331,9 @@ __isl_give isl_mat *isl_basic_set_reduced_basis(__isl_keep isl_basic_set *bset)
 		tab->basis = isl_mat_identity(bset->ctx, 1 + tab->n_var);
 	else {
 		isl_mat *eq;
-		unsigned nvar = isl_basic_set_total_dim(bset);
+		isl_size nvar = isl_basic_set_dim(bset, isl_dim_all);
+		if (nvar < 0)
+			goto error;
 		eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq,
 					1, nvar);
 		eq = isl_mat_left_hermite(eq, 0, NULL, &tab->basis);
@@ -354,4 +350,7 @@ __isl_give isl_mat *isl_basic_set_reduced_basis(__isl_keep isl_basic_set *bset)
 	isl_tab_free(tab);
 
 	return basis;
+error:
+	isl_tab_free(tab);
+	return NULL;
 }

diff  --git a/polly/lib/External/isl/bound.c b/polly/lib/External/isl/bound.c
index cfb2b6148947..ec79b3be506f 100644
--- a/polly/lib/External/isl/bound.c
+++ b/polly/lib/External/isl/bound.c
@@ -25,12 +25,14 @@ ISL_ARG_DEF(bound_options, struct bound_options, bound_options_args)
 
 static __isl_give isl_set *set_bounds(__isl_take isl_set *set)
 {
-	unsigned nparam;
+	isl_size nparam;
 	int i, r;
 	isl_point *pt, *pt2;
 	isl_set *box;
 
 	nparam = isl_set_dim(set, isl_dim_param);
+	if (nparam < 0)
+		return isl_set_free(set);
 	r = nparam >= 8 ? 5 : nparam >= 5 ? 15 : 50;
 
 	pt = isl_set_sample_point(isl_set_copy(set));
@@ -60,7 +62,7 @@ struct verify_point_bound {
 static isl_stat verify_point(__isl_take isl_point *pnt, void *user)
 {
 	int i;
-	unsigned nparam;
+	isl_size nparam;
 	struct verify_point_bound *vpb = (struct verify_point_bound *) user;
 	isl_val *v;
 	isl_ctx *ctx;
@@ -91,6 +93,8 @@ static isl_stat verify_point(__isl_take isl_point *pnt, void *user)
 	pwf = isl_pw_qpolynomial_fold_copy(vpb->pwf);
 
 	nparam = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_param);
+	if (nparam < 0)
+		pwf = isl_pw_qpolynomial_fold_free(pwf);
 	for (i = 0; i < nparam; ++i) {
 		v = isl_point_get_coordinate_val(pnt, isl_dim_param, i);
 		pwf = isl_pw_qpolynomial_fold_fix_val(pwf, isl_dim_param, i, v);
@@ -239,7 +243,7 @@ int main(int argc, char **argv)
 	isl_stream *s;
 	struct isl_obj obj;
 	struct bound_options *options;
-	int exact;
+	isl_bool exact;
 	int r = 0;
 
 	options = bound_options_new_with_defaults();

diff  --git a/polly/lib/External/isl/cat.c b/polly/lib/External/isl/cat.c
index 4f871331f183..c483383d94f8 100644
--- a/polly/lib/External/isl/cat.c
+++ b/polly/lib/External/isl/cat.c
@@ -10,6 +10,7 @@ struct isl_arg_choice cat_format[] = {
 	{"polylib",	ISL_FORMAT_POLYLIB},
 	{"ext-polylib",	ISL_FORMAT_EXT_POLYLIB},
 	{"latex",	ISL_FORMAT_LATEX},
+	{"C",		ISL_FORMAT_C},
 	{0}
 };
 

diff  --git a/polly/lib/External/isl/check_reparse_templ.c b/polly/lib/External/isl/check_reparse_templ.c
new file mode 100644
index 000000000000..333c44cbc52f
--- /dev/null
+++ b/polly/lib/External/isl/check_reparse_templ.c
@@ -0,0 +1,32 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef TYPE
+#define TYPE CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Check that printing "obj" and parsing the output results
+ * in the same expression.
+ */
+static isl_stat FN(check_reparse,BASE)(isl_ctx *ctx,
+	__isl_take TYPE *obj)
+{
+	char *str;
+	isl_bool equal;
+	TYPE *obj2;
+
+	str = FN(TYPE,to_str)(obj);
+	obj2 = FN(TYPE,read_from_str)(ctx, str);
+	free(str);
+	equal = FN(TYPE,plain_is_equal)(obj, obj2);
+	FN(TYPE,free)(obj);
+	FN(TYPE,free)(obj2);
+	if (equal < 0)
+		return isl_stat_error;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown,
+			"parsed function not equal to original",
+			return isl_stat_error);
+
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/check_reparse_test_templ.c b/polly/lib/External/isl/check_reparse_test_templ.c
new file mode 100644
index 000000000000..58c194ceae93
--- /dev/null
+++ b/polly/lib/External/isl/check_reparse_test_templ.c
@@ -0,0 +1,28 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef TYPE
+#define TYPE CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+#define TESTS CAT(reparse_,CAT(BASE,_tests))
+
+/* Test parsing of objects of type TYPE by printing
+ * the expressions and checking that parsing the output results
+ * in the same expression.
+ * Do this for a set of expressions parsed from strings.
+ */
+static isl_stat FN(check,TESTS)(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(TESTS); ++i) {
+		TYPE *obj;
+
+		obj = FN(TYPE,read_from_str)(ctx, TESTS[i]);
+		if (FN(check_reparse,BASE)(ctx, obj) < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/check_type_range_templ.c b/polly/lib/External/isl/check_type_range_templ.c
new file mode 100644
index 000000000000..4e4c1e2fc36f
--- /dev/null
+++ b/polly/lib/External/isl/check_type_range_templ.c
@@ -0,0 +1,20 @@
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Check that there are "n" dimensions of type "type" starting at "first"
+ * in "obj".
+ */
+isl_stat FN(TYPE,check_range)(__isl_keep TYPE *obj,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	isl_size dim;
+
+	dim = FN(TYPE,dim)(obj, type);
+	if (dim < 0)
+		return isl_stat_error;
+	if (first + n > dim || first + n < first)
+		isl_die(FN(TYPE,get_ctx)(obj), isl_error_invalid,
+			"position or range out of bounds",
+			return isl_stat_error);
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/closure.c b/polly/lib/External/isl/closure.c
index c76fb298fda0..22235b051ced 100644
--- a/polly/lib/External/isl/closure.c
+++ b/polly/lib/External/isl/closure.c
@@ -8,7 +8,7 @@ int main(int argc, char **argv)
 	struct isl_map *map;
 	struct isl_options *options;
 	isl_printer *p;
-	int exact;
+	isl_bool exact;
 
 	options = isl_options_new_with_defaults();
 	assert(options);

diff  --git a/polly/lib/External/isl/codegen.c b/polly/lib/External/isl/codegen.c
index af2e18c03780..38dab49e24af 100644
--- a/polly/lib/External/isl/codegen.c
+++ b/polly/lib/External/isl/codegen.c
@@ -142,12 +142,15 @@ static __isl_give isl_schedule_node *node_set_options(
 	__isl_take isl_schedule_node *node, void *user)
 {
 	enum isl_ast_loop_type *type = user;
-	int i, n;
+	int i;
+	isl_size n;
 
 	if (isl_schedule_node_get_type(node) != isl_schedule_node_band)
 		return node;
 
 	n = isl_schedule_node_band_n_member(node);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	for (i = 0; i < n; ++i)
 		node = isl_schedule_node_band_member_set_ast_loop_type(node,
 								i, *type);

diff  --git a/polly/lib/External/isl/configure b/polly/lib/External/isl/configure
index 2b08755e5118..af8dd9beec16 100755
--- a/polly/lib/External/isl/configure
+++ b/polly/lib/External/isl/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for isl 0.20.
+# Generated by GNU Autoconf 2.69 for isl 0.22.1.
 #
 # Report bugs to <isl-development at googlegroups.com>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='isl'
 PACKAGE_TARNAME='isl'
-PACKAGE_VERSION='0.20'
-PACKAGE_STRING='isl 0.20'
+PACKAGE_VERSION='0.22.1'
+PACKAGE_STRING='isl 0.22.1'
 PACKAGE_BUGREPORT='isl-development at googlegroups.com'
 PACKAGE_URL=''
 
@@ -635,6 +635,7 @@ ac_subst_vars='am__EXEEXT_FALSE
 am__EXEEXT_TRUE
 LTLIBOBJS
 LIBOBJS
+CONFIG_STATUS_DEPENDENCIES
 GIT_HEAD_VERSION
 GIT_HEAD
 GIT_HEAD_ID
@@ -646,8 +647,9 @@ HAVE_CPP_ISL_H_TRUE
 HAVE_CLANG_FALSE
 HAVE_CLANG_TRUE
 LIB_CLANG_EDIT
-llvm_config_found
+LLVM_CONFIG
 CLANG_LIBS
+CLANG_RFLAG
 CLANG_LDFLAGS
 CLANG_CXXFLAGS
 SMALL_INT_OPT_FALSE
@@ -662,12 +664,15 @@ NEED_GET_MEMORY_FUNCTIONS_FALSE
 NEED_GET_MEMORY_FUNCTIONS_TRUE
 MP_LIBS
 MP_LDFLAGS
+MP_CFLAGS
 MP_CPPFLAGS
 GENERATE_DOC_FALSE
 GENERATE_DOC_TRUE
+OS_SRCDIR
 POD2HTML
 PDFLATEX
 PERL
+CYGPATH
 HAVE_PYTHON_FALSE
 HAVE_PYTHON_TRUE
 pkgpyexecdir
@@ -702,9 +707,8 @@ FGREP
 EGREP
 SED
 LIBTOOL
-GREP
 HAVE_CXX11
-CXX11FLAGS
+GREP
 PRTDIAG
 host_os
 host_vendor
@@ -1393,7 +1397,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures isl 0.20 to adapt to many kinds of systems.
+\`configure' configures isl 0.22.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1464,7 +1468,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of isl 0.20:";;
+     short | recursive ) echo "Configuration of isl 0.22.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1595,7 +1599,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-isl configure 0.20
+isl configure 0.22.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2490,7 +2494,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by isl $as_me 0.20, which was
+It was created by isl $as_me 0.22.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3354,7 +3358,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='isl'
- VERSION='0.20'
+ VERSION='0.22.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3487,7 +3491,7 @@ fi
 AM_BACKSLASH='\'
 
 
-versioninfo=20:0:1
+versioninfo=22:1:0
 
 if test "x$prefix" != "xNONE"; then
 	prefix_wd=`cd $prefix && pwd`
@@ -5940,14 +5944,402 @@ $as_echo "#define HAVE___ATTRIBUTE__ 1" >>confdefs.h
   fi
 
 
-# CXX11FLAGS contains the flags (if any) added by AX_CXX_COMPILE_STDCXX_11
-# Original state of CXX and CXXCPP is preserved because CXX11FLAGS
-# is only needed for compiling interface/isl_test_cpp
 
-ac_save_CXX="$CXX"
-ac_save_CXXCPP="$CXXCPP"
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    
diff  "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+	echo $CXX | $GREP -e "-std=" > /dev/null 2> /dev/null
+	if test $? -eq 0; then
+		  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+  ac_success=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5
+$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; }
+if ${ax_cv_cxx_compile_cxx11+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
 
-  ax_cxx_compile_alternatives="11 0x"    ax_cxx_compile_cxx11_required=false
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_cxx_compile_cxx11=yes
+else
+  ax_cv_cxx_compile_cxx11=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5
+$as_echo "$ax_cv_cxx_compile_cxx11" >&6; }
+  if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+    ac_success=yes
+  fi
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+  if test x$ac_success = xno; then
+    HAVE_CXX11=0
+  else
+    HAVE_CXX11=1
+
+$as_echo "#define HAVE_CXX11 1" >>confdefs.h
+
+  fi
+
+
+	else
+		  ax_cxx_compile_alternatives="11 0x"    ax_cxx_compile_cxx11_required=false
   ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -6612,9 +7004,8 @@ $as_echo "#define HAVE_CXX11 1" >>confdefs.h
 
 
 
-CXX11FLAGS=${CXX#$ac_save_CXX}
-CXX="$ac_save_CXX"
-CXXCPP="$ac_save_CXXCPP"
+	fi
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
 $as_echo_n "checking for grep that handles long lines and -e... " >&6; }
@@ -18297,6 +18688,43 @@ else
 fi
 
 
+# Extract the first word of "cygpath", so it can be a program name with args.
+set dummy cygpath; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CYGPATH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CYGPATH"; then
+  ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CYGPATH="cygpath"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CYGPATH=$ac_cv_prog_CYGPATH
+if test -n "$CYGPATH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5
+$as_echo "$CYGPATH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
 # Extract the first word of "perl", so it can be a program name with args.
 set dummy perl; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -18409,6 +18837,13 @@ fi
 
 
 
+
+if test "$host_os" = "mingw32" -a -n "$CYGPATH"; then
+	OS_SRCDIR=`$CYGPATH -m "$srcdir"`
+else
+	OS_SRCDIR="$srcdir"
+fi
+
  if test -n "$PERL" -a -n "$PDFLATEX" -a -n "$POD2HTML"; then
   GENERATE_DOC_TRUE=
   GENERATE_DOC_FALSE='#'
@@ -18899,6 +19334,7 @@ esac
 
 
 
+
 case "$with_int" in
 gmp)
 
@@ -19168,7 +19604,7 @@ fi
 	;;
 esac
 if test "x$with_int" = "ximath-32" -a "x$GCC" = "xyes"; then
-	MP_CPPFLAGS="-std=gnu99 $MP_CPPFLAGS"
+	MP_CFLAGS="-std=gnu99 $MP_CFLAGS"
 fi
 
  if test x$with_int = ximath -o x$with_int = ximath-32; then
@@ -19424,6 +19860,7 @@ system)
 
 
 
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
 $as_echo_n "checking for grep that handles long lines and -e... " >&6; }
 if ${ac_cv_path_GREP+:} false; then :
@@ -19556,25 +19993,29 @@ $as_echo "$ac_cv_path_SED" >&6; }
  SED="$ac_cv_path_SED"
   rm -f conftest.sed
 
-llvm_config="llvm-config"
-# Extract the first word of ""$llvm_config"", so it can be a program name with args.
-set dummy "$llvm_config"; ac_word=$2
+if test "x$with_clang_prefix" != "x"; then
+	LLVM_CONFIG="$with_clang_prefix/bin/llvm-config"
+fi
+# Extract the first word of ""llvm-config"", so it can be a program name with args.
+set dummy "llvm-config"; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_llvm_config_found+:} false; then :
+if ${ac_cv_path_LLVM_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$llvm_config_found"; then
-  ac_cv_prog_llvm_config_found="$llvm_config_found" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+  case $LLVM_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LLVM_CONFIG="$LLVM_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_llvm_config_found="yes"
+    ac_cv_path_LLVM_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -19582,42 +20023,40 @@ done
   done
 IFS=$as_save_IFS
 
+  ;;
+esac
 fi
-fi
-llvm_config_found=$ac_cv_prog_llvm_config_found
-if test -n "$llvm_config_found"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $llvm_config_found" >&5
-$as_echo "$llvm_config_found" >&6; }
+LLVM_CONFIG=$ac_cv_path_LLVM_CONFIG
+if test -n "$LLVM_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LLVM_CONFIG" >&5
+$as_echo "$LLVM_CONFIG" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
 
-if test "x$with_clang_prefix" != "x"; then
-	llvm_config="$with_clang_prefix/bin/llvm-config"
-	if test -x "$llvm_config"; then
-		llvm_config_found=yes
-	fi
-fi
-if test "$llvm_config_found" != yes; then
+if test -z "$LLVM_CONFIG" || test ! -x "$LLVM_CONFIG"; then
 	as_fn_error $? "llvm-config not found" "$LINENO" 5
 fi
-CLANG_CXXFLAGS=`$llvm_config --cxxflags | \
+CLANG_CXXFLAGS=`$LLVM_CONFIG --cxxflags | \
 	$SED -e 's/-Wcovered-switch-default//;s/-gsplit-dwarf//'`
-CLANG_LDFLAGS=`$llvm_config --ldflags`
-targets=`$llvm_config --targets-built`
+CLANG_LDFLAGS=`$LLVM_CONFIG --ldflags`
+# Construct a -R argument for libtool.
+# This is needed in case some of the clang libraries are shared libraries.
+CLANG_RFLAG=`echo "$CLANG_LDFLAGS" | $SED -e 's/-L/-R/g'`
+targets=`$LLVM_CONFIG --targets-built`
 components="$targets asmparser bitreader support mc"
-$llvm_config --components | $GREP option > /dev/null 2> /dev/null
+$LLVM_CONFIG --components | $GREP option > /dev/null 2> /dev/null
 if test $? -eq 0; then
 	components="$components option"
 fi
-CLANG_LIBS=`$llvm_config --libs $components`
-systemlibs=`$llvm_config --system-libs 2> /dev/null | tail -1`
+CLANG_LIBS=`$LLVM_CONFIG --libs $components`
+systemlibs=`$LLVM_CONFIG --system-libs 2> /dev/null | tail -1`
 if test $? -eq 0; then
 	CLANG_LIBS="$CLANG_LIBS $systemlibs"
 fi
-CLANG_PREFIX=`$llvm_config --prefix`
+CLANG_PREFIX=`$LLVM_CONFIG --prefix`
 
 cat >>confdefs.h <<_ACEOF
 #define CLANG_PREFIX "$CLANG_PREFIX"
@@ -19711,6 +20150,21 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
 
 $as_echo "#define USE_ARRAYREF /**/" >>confdefs.h
 
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <clang/Frontend/CompilerInvocation.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ArrayRef.*CommandLineArgs" >/dev/null 2>&1; then :
+
+$as_echo "#define CREATE_FROM_ARGS_TAKES_ARRAYREF /**/" >>confdefs.h
+
+
+fi
+rm -f conftest*
+
+
 fi
 rm -f conftest*
 
@@ -19987,8 +20441,19 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   $EGREP "IK_C" >/dev/null 2>&1; then :
 
 else
+  ac_fn_cxx_check_header_mongrel "$LINENO" "clang/Basic/LangStandard.h" "ac_cv_header_clang_Basic_LangStandard_h" "$ac_includes_default"
+if test "x$ac_cv_header_clang_Basic_LangStandard_h" = xyes; then :
+  IK_C=Language::C
+else
+  IK_C=InputKind::C
+fi
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define IK_C $IK_C
+_ACEOF
 
-$as_echo "#define IK_C InputKind::C" >>confdefs.h
 
 fi
 rm -f conftest*
@@ -20047,6 +20512,14 @@ $as_echo "#define SETINVOCATION_TAKES_SHARED_PTR /**/" >>confdefs.h
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_fn_cxx_check_header_mongrel "$LINENO" "llvm/Option/Arg.h" "ac_cv_header_llvm_Option_Arg_h" "$ac_includes_default"
+if test "x$ac_cv_header_llvm_Option_Arg_h" = xyes; then :
+
+$as_echo "#define HAVE_LLVM_OPTION_ARG_H /**/" >>confdefs.h
+
+fi
+
+
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -20104,7 +20577,8 @@ else
   HAVE_CLANG_FALSE=
 fi
 
- if test $with_clang = system -o -f $srcdir/include/isl/cpp.h; then
+ if (test $with_clang = system -a "x$HAVE_CXX11" = "x1") || \
+     test -f $srcdir/include/isl/cpp.h; then
   HAVE_CPP_ISL_H_TRUE=
   HAVE_CPP_ISL_H_FALSE='#'
 else
@@ -20379,6 +20853,8 @@ ac_config_commands="$ac_config_commands $ax_create_pkgconfig_generate"
 	fi
 
 
+CONFIG_STATUS_DEPENDENCIES=$LLVM_CONFIG
+
 
 ac_config_headers="$ac_config_headers isl_config.h"
 
@@ -20977,7 +21453,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by isl $as_me 0.20, which was
+This file was extended by isl $as_me 0.22.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21043,7 +21519,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-isl config.status 0.20
+isl config.status 0.22.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 

diff  --git a/polly/lib/External/isl/configure.ac b/polly/lib/External/isl/configure.ac
index 5d7fc6954fb3..6321ac985cbc 100644
--- a/polly/lib/External/isl/configure.ac
+++ b/polly/lib/External/isl/configure.ac
@@ -1,10 +1,10 @@
-AC_INIT([isl], [0.20], [isl-development at googlegroups.com])
+AC_INIT([isl], [0.22.1], [isl-development at googlegroups.com])
 AC_CONFIG_AUX_DIR([.])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign])
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 AC_SUBST(versioninfo)
-versioninfo=20:0:1
+versioninfo=22:1:0
 
 if test "x$prefix" != "xNONE"; then
 	prefix_wd=`cd $prefix && pwd`
@@ -25,16 +25,7 @@ AX_CC_MAXOPT
 AX_GCC_WARN_UNUSED_RESULT
 AX_C___ATTRIBUTE__
 
-# CXX11FLAGS contains the flags (if any) added by AX_CXX_COMPILE_STDCXX_11
-# Original state of CXX and CXXCPP is preserved because CXX11FLAGS
-# is only needed for compiling interface/isl_test_cpp
-AC_SUBST(CXX11FLAGS)
-ac_save_CXX="$CXX"
-ac_save_CXXCPP="$CXXCPP"
-AX_CXX_COMPILE_STDCXX_11([noext], [optional])
-CXX11FLAGS=${CXX#$ac_save_CXX}
-CXX="$ac_save_CXX"
-CXXCPP="$ac_save_CXXCPP"
+AX_CXX_COMPILE_STDCXX_11_NO_OVERRIDE
 
 AC_PROG_GREP
 AC_PROG_LIBTOOL
@@ -42,10 +33,18 @@ AC_PROG_SED
 AM_PATH_PYTHON([2.5], [], [:])
 AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])
 
+AC_CHECK_PROG(CYGPATH, cygpath, cygpath, [])
 AC_CHECK_PROG(PERL, perl, perl, [])
 AC_CHECK_PROG(PDFLATEX, pdflatex, pdflatex, [])
 AC_CHECK_PROG(POD2HTML, pod2html, pod2html, [])
 
+AC_SUBST(OS_SRCDIR)
+if test "$host_os" = "mingw32" -a -n "$CYGPATH"; then
+	OS_SRCDIR=`$CYGPATH -m "$srcdir"`
+else
+	OS_SRCDIR="$srcdir"
+fi
+
 AM_CONDITIONAL(GENERATE_DOC, test -n "$PERL" -a -n "$PDFLATEX" -a -n "$POD2HTML")
 
 AX_CREATE_STDINT_H(include/isl/stdint.h)
@@ -64,6 +63,7 @@ gmp|imath|imath-32)
 esac
 
 AC_SUBST(MP_CPPFLAGS)
+AC_SUBST(MP_CFLAGS)
 AC_SUBST(MP_LDFLAGS)
 AC_SUBST(MP_LIBS)
 case "$with_int" in
@@ -75,7 +75,7 @@ imath|imath-32)
 	;;
 esac
 if test "x$with_int" = "ximath-32" -a "x$GCC" = "xyes"; then
-	MP_CPPFLAGS="-std=gnu99 $MP_CPPFLAGS"
+	MP_CFLAGS="-std=gnu99 $MP_CFLAGS"
 fi
 
 AM_CONDITIONAL(IMATH_FOR_MP, test x$with_int = ximath -o x$with_int = ximath-32)
@@ -119,7 +119,8 @@ system)
 esac
 AM_CONDITIONAL(HAVE_CLANG, test $with_clang = system)
 AM_CONDITIONAL(HAVE_CPP_ISL_H,
-    [test $with_clang = system -o -f $srcdir/include/isl/cpp.h])
+    [(test $with_clang = system -a "x$HAVE_CXX11" = "x1") || \
+     test -f $srcdir/include/isl/cpp.h])
 
 AX_SET_WARNING_FLAGS
 
@@ -132,6 +133,7 @@ AX_CREATE_PKGCONFIG_INFO
 
 AX_DETECT_GIT_HEAD
 
+AC_SUBST([CONFIG_STATUS_DEPENDENCIES], [$LLVM_CONFIG])
 AH_BOTTOM([#include <isl_config_post.h>])
 AC_CONFIG_HEADERS(isl_config.h)
 AC_CONFIG_FILES(isl_srcdir.c)

diff  --git a/polly/lib/External/isl/cpp/cpp-checked.h.pre b/polly/lib/External/isl/cpp/cpp-checked.h.pre
index 43911e5791ea..988bedbd8146 100644
--- a/polly/lib/External/isl/cpp/cpp-checked.h.pre
+++ b/polly/lib/External/isl/cpp/cpp-checked.h.pre
@@ -3,7 +3,10 @@
 #include <stdlib.h>
 
 #include <functional>
+#include <memory>
+#include <ostream>
 #include <string>
+#include <type_traits>
 
 namespace isl {
 namespace checked {
@@ -21,37 +24,60 @@ namespace checked {
     abort();                                                 \
   } while (0)
 
+/* Class used to check that isl::checked::boolean,
+ * isl::checked::stat and isl::checked::size values are checked for errors.
+ */
+struct checker {
+	bool checked = false;
+	~checker() {
+		ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
+	}
+};
+
 class boolean {
 private:
-  mutable bool checked = false;
+  mutable std::shared_ptr<checker> check = std::make_shared<checker>();
   isl_bool val;
 
   friend boolean manage(isl_bool val);
   boolean(isl_bool val): val(val) {}
 public:
+  static boolean error() {
+    return boolean(isl_bool_error);
+  }
   boolean()
       : val(isl_bool_error) {}
-  ~boolean() {
-    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
-  }
 
   /* implicit */ boolean(bool val)
       : val(val ? isl_bool_true : isl_bool_false) {}
 
-  bool is_error() const { checked = true; return val == isl_bool_error; }
-  bool is_false() const { checked = true; return val == isl_bool_false; }
-  bool is_true() const { checked = true; return val == isl_bool_true; }
+  isl_bool release() {
+    auto tmp = val;
+    val = isl_bool_error;
+    check->checked = true;
+    return tmp;
+  }
+
+  bool is_error() const { check->checked = true; return val == isl_bool_error; }
+  bool is_false() const { check->checked = true; return val == isl_bool_false; }
+  bool is_true() const { check->checked = true; return val == isl_bool_true; }
 
   explicit operator bool() const {
-    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked error state");
+    ISLPP_ASSERT(check->checked, "IMPLEMENTATION ERROR: Unchecked error state");
     ISLPP_ASSERT(!is_error(), "IMPLEMENTATION ERROR: Unhandled error state");
     return is_true();
   }
 
+  boolean negate() {
+    if (val == isl_bool_true)
+      val = isl_bool_false;
+    else if (val == isl_bool_false)
+      val = isl_bool_true;
+    return *this;
+  }
+
   boolean operator!() const {
-    if (is_error())
-      return *this;
-    return !is_true();
+    return boolean(*this).negate();
   }
 };
 
@@ -78,11 +104,11 @@ public:
  */
 class stat {
 private:
-	mutable bool checked = false;
+	mutable std::shared_ptr<checker> check = std::make_shared<checker>();
 	isl_stat val;
 
 	friend stat manage(isl_stat val);
-	constexpr stat(isl_stat val) : val(val) {}
+	stat(isl_stat val) : val(val) {}
 public:
 	static stat ok() {
 		return stat(isl_stat_ok);
@@ -91,21 +117,18 @@ public:
 		return stat(isl_stat_error);
 	}
 	stat() : val(isl_stat_error) {}
-	~stat() {
-		ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
-	}
 
 	isl_stat release() {
-		checked = true;
+		check->checked = true;
 		return val;
 	}
 
 	bool is_error() const {
-		checked = true;
+		check->checked = true;
 		return val == isl_stat_error;
 	}
 	bool is_ok() const {
-		checked = true;
+		check->checked = true;
 		return val == isl_stat_ok;
 	}
 };
@@ -115,5 +138,43 @@ inline stat manage(isl_stat val)
 	return stat(val);
 }
 
+/* Class encapsulating an isl_size value.
+ */
+class size {
+private:
+	mutable std::shared_ptr<checker> check = std::make_shared<checker>();
+	isl_size val;
+
+	friend size manage(isl_size val);
+	size(isl_size val) : val(val) {}
+public:
+	size() : val(isl_size_error) {}
+
+	isl_size release() {
+		auto tmp = val;
+		val = isl_size_error;
+		check->checked = true;
+		return tmp;
+	}
+
+	bool is_error() const {
+		check->checked = true;
+		return val == isl_size_error;
+	}
+
+	explicit operator unsigned() const {
+		ISLPP_ASSERT(check->checked,
+			    "IMPLEMENTATION ERROR: Unchecked error state");
+		ISLPP_ASSERT(!is_error(),
+			    "IMPLEMENTATION ERROR: Unhandled error state");
+		return val;
+	}
+};
+
+inline size manage(isl_size val)
+{
+	return size(val);
+}
+
 }
 } // namespace isl

diff  --git a/polly/lib/External/isl/cpp/cpp.h.pre b/polly/lib/External/isl/cpp/cpp.h.pre
index bf1fdf809715..1ac70c597603 100644
--- a/polly/lib/External/isl/cpp/cpp.h.pre
+++ b/polly/lib/External/isl/cpp/cpp.h.pre
@@ -4,16 +4,19 @@
 
 #include <functional>
 #include <memory>
+#include <ostream>
 #include <stdexcept>
 #include <string>
+#include <type_traits>
 
 /* ISL_USE_EXCEPTIONS should be defined to 1 if exceptions are available.
  * gcc and clang define __cpp_exceptions; MSVC and xlC define _CPPUNWIND.
+ * Older versions of gcc (e.g., 4.9) only define __EXCEPTIONS.
  * If exceptions are not available, any error condition will result
  * in an abort.
  */
 #ifndef ISL_USE_EXCEPTIONS
-#if defined(__cpp_exceptions) || defined(_CPPUNWIND)
+#if defined(__cpp_exceptions) || defined(_CPPUNWIND) || defined(__EXCEPTIONS)
 #define ISL_USE_EXCEPTIONS	1
 #else
 #define ISL_USE_EXCEPTIONS	0
@@ -80,10 +83,10 @@ public:
 	 * will be included in the exception thrown from inside the bindings.
 	 */
 	static constexpr auto on_error = ISL_ON_ERROR_CONTINUE;
-	/* Wrapper for throwing an exception on NULL input.
+	/* Wrapper for throwing an exception with the given message.
 	 */
-	static void throw_NULL_input(const char *file, int line) {
-		throw_error(isl_error_invalid, "NULL input", file, line);
+	static void throw_invalid(const char *msg, const char *file, int line) {
+		throw_error(isl_error_invalid, msg, file, line);
 	}
 	static inline void throw_last_error(ctx ctx);
 };
@@ -204,11 +207,11 @@ public:
 	 * In the case exceptions are not available, isl should abort.
 	 */
 	static constexpr auto on_error = ISL_ON_ERROR_ABORT;
-	/* Wrapper for throwing an exception on NULL input.
+	/* Wrapper for throwing an exception with the given message.
 	 * In the case exceptions are not available, print an error and abort.
 	 */
-	static void throw_NULL_input(const char *file, int line) {
-		fprintf(stderr, "%s:%d: NULL input\n", file, line);
+	static void throw_invalid(const char *msg, const char *file, int line) {
+		fprintf(stderr, "%s:%d: %s\n", file, line, msg);
 		abort();
 	}
 	/* Throw an exception corresponding to the last

diff  --git a/polly/lib/External/isl/all.c b/polly/lib/External/isl/dep.c
similarity index 100%
rename from polly/lib/External/isl/all.c
rename to polly/lib/External/isl/dep.c

diff  --git a/polly/lib/External/isl/doc/Makefile.in b/polly/lib/External/isl/doc/Makefile.in
index 57dc445054c0..fc03ecca56fa 100644
--- a/polly/lib/External/isl/doc/Makefile.in
+++ b/polly/lib/External/isl/doc/Makefile.in
@@ -97,6 +97,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
 	$(top_srcdir)/m4/ax_create_stdint_h.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11_no_override.m4 \
 	$(top_srcdir)/m4/ax_detect_clang.m4 \
 	$(top_srcdir)/m4/ax_detect_git_head.m4 \
 	$(top_srcdir)/m4/ax_detect_gmp.m4 \
@@ -152,13 +153,15 @@ CFLAGS = @CFLAGS@
 CLANG_CXXFLAGS = @CLANG_CXXFLAGS@
 CLANG_LDFLAGS = @CLANG_LDFLAGS@
 CLANG_LIBS = @CLANG_LIBS@
+CLANG_RFLAG = @CLANG_RFLAG@
+CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
-CXX11FLAGS = @CXX11FLAGS@
 CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
+CYGPATH = @CYGPATH@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -188,12 +191,14 @@ LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIB_CLANG_EDIT = @LIB_CLANG_EDIT@
 LIPO = @LIPO@
+LLVM_CONFIG = @LLVM_CONFIG@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
 MKDIR_P = @MKDIR_P@
+MP_CFLAGS = @MP_CFLAGS@
 MP_CPPFLAGS = @MP_CPPFLAGS@
 MP_LDFLAGS = @MP_LDFLAGS@
 MP_LIBS = @MP_LIBS@
@@ -201,6 +206,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OS_SRCDIR = @OS_SRCDIR@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -263,7 +269,6 @@ infodir = @infodir@
 install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
-llvm_config_found = @llvm_config_found@
 localedir = @localedir@
 localstatedir = @localstatedir@
 mandir = @mandir@

diff  --git a/polly/lib/External/isl/doc/user.pod b/polly/lib/External/isl/doc/user.pod
index c8e57b5d848f..5eda8dd0b89a 100644
--- a/polly/lib/External/isl/doc/user.pod
+++ b/polly/lib/External/isl/doc/user.pod
@@ -281,6 +281,30 @@ by various operations that take such objects as input.
 
 =back
 
+=head3 Changes since isl-0.20
+
+=over
+
+=item * Several functions that used to return C<unsigned>
+now return C<isl_size>.  This means that these functions may
+now return a negative value in case an error occurred.
+The same holds for functions that used to return C<int>,
+although some of those were already returning
+a negative value in case of error.
+
+=item * The C<isl_ast_op_type> enumeration type has been
+renamed to C<isl_ast_expr_op_type>.  The corresponding
+enumeration constants have been similarly renamed.
+The old names are defined to the new names for backward
+compatibility.
+
+=item * Several functions returning an extra boolean value
+through an C<int *> argument now do so through an C<isl_bool *>
+argument.  The returned values are the same, only the type
+of the pointer has been changed.
+
+=back
+
 =head1 License
 
 C<isl> is released under the MIT license.
@@ -535,6 +559,8 @@ in which the object was created.
 
 	#include <isl/id.h>
 	isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id);
+	isl_ctx *isl_multi_id_get_ctx(
+		__isl_keep isl_multi_id *mi);
 
 	#include <isl/local_space.h>
 	isl_ctx *isl_local_space_get_ctx(
@@ -617,25 +643,42 @@ in which the object was created.
 
 =head2 Return Types
 
-C<isl> uses two special return types for functions that either return
+C<isl> uses the special return type C<isl_size> for functions
+that return a non-negative value, typically a number or a position.
+Besides the regular non-negative return values, a special (negative)
+value C<isl_size_error> may be returned, indicating that something
+went wrong.
+
+C<isl> also uses two special return types for functions that either return
 a boolean or that in principle do not return anything.
 In particular, the C<isl_bool> type has three possible values:
 C<isl_bool_true> (a positive integer value), indicating I<true> or I<yes>;
 C<isl_bool_false> (the integer value zero), indicating I<false> or I<no>; and
 C<isl_bool_error> (a negative integer value), indicating that something
-went wrong.  The following function can be used to negate an C<isl_bool>,
-where the negation of C<isl_bool_error> is C<isl_bool_error> again.
+went wrong.  The following operations are defined on C<isl_bool>. The function
+C<isl_bool_not> can be used to negate an C<isl_bool>, where the negation of
+C<isl_bool_error> is C<isl_bool_error> again. The function C<isl_bool_ok>
+converts an integer to an C<isl_bool>. Any non-zero values yields
+C<isl_bool_true> and zero yields C<isl_bool_false>.
 
-	#include <isl/val.h>
+	#include <isl/ctx.h>
 	isl_bool isl_bool_not(isl_bool b);
+	isl_bool isl_bool_ok(int b);
 
 The C<isl_stat> type has two possible values:
 C<isl_stat_ok> (the integer value zero), indicating a successful
 operation; and
 C<isl_stat_error> (a negative integer value), indicating that something
 went wrong.
+The function C<isl_stat_non_null> converts an isl object pointer
+to an C<isl_stat>, returning C<isl_stat_ok> if the object pointer is valid and
+C<isl_stat_error> if it is C<NULL>.
+
+	#include <isl/ctx.h>
+	isl_stat isl_stat_non_null(void *obj);
+
 See L</"Error Handling"> for more information on
-C<isl_bool_error> and C<isl_stat_error>.
+C<isl_size_error>, C<isl_bool_error> and C<isl_stat_error>.
 
 =head2 Values
 
@@ -679,9 +722,9 @@ They can be inspected using the following functions.
 	__isl_give isl_val *isl_val_get_den_val(
 		__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,
+	isl_size 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,
+	isl_stat isl_val_get_abs_num_chunks(__isl_keep isl_val *v,
 		size_t size, void *chunks);
 
 C<isl_val_n_abs_num_chunks> returns the number of I<digits>
@@ -860,8 +903,9 @@ The default behavior is to warn. In this mode, C<isl> prints a warning, stores
 the last error in the corresponding C<isl_ctx> and the function in which the
 error was triggered returns a value indicating that some error has
 occurred.  In case of functions returning a pointer, this value is
-C<NULL>.  In case of functions returning an C<isl_bool> or an
-C<isl_stat>, this value is C<isl_bool_error> or C<isl_stat_error>.
+C<NULL>.  In case of functions returning an C<isl_size>, C<isl_bool> or an
+C<isl_stat>, this value is C<isl_size_error>,
+C<isl_bool_error> or C<isl_stat_error>.
 An error does not corrupt internal state,
 such that isl can continue to be used. C<isl> also provides functions to
 read the last error, including the specific error message,
@@ -962,6 +1006,7 @@ are identified by their positions across objects.  The use of unnamed
 parameters is discouraged.
 
 	#include <isl/space.h>
+	__isl_give isl_space *isl_space_unit(isl_ctx *ctx);
 	__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
 		unsigned nparam, unsigned n_in, unsigned n_out);
 	__isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx,
@@ -972,11 +1017,14 @@ parameters is discouraged.
 	__isl_null isl_space *isl_space_free(__isl_take isl_space *space);
 
 The space used for creating a parameter domain
-needs to be created using C<isl_space_params_alloc>.
+needs to be created using C<isl_space_unit> or C<isl_space_params_alloc>.
 For other sets, the space
 needs to be created using C<isl_space_set_alloc>, while
 for a relation, the space
 needs to be created using C<isl_space_alloc>.
+The use of C<isl_space_params_alloc>,
+C<isl_space_set_alloc> and C<isl_space_alloc> is discouraged as they allow
+for the introduction of unnamed parameters.
 
 To check whether a given space is that of a set or a map
 or whether it is a parameter space, use these functions:
@@ -1081,6 +1129,10 @@ of the original object.
 	__isl_give isl_space *isl_union_pw_qpolynomial_fold_get_space(
 		__isl_keep isl_union_pw_qpolynomial_fold *upwf);
 
+	#include <isl/id.h>
+	__isl_give isl_space *isl_multi_id_get_space(
+		__isl_keep isl_multi_id *mi);
+
 	#include <isl/val.h>
 	__isl_give isl_space *isl_multi_val_get_space(
 		__isl_keep isl_multi_val *mv);
@@ -1134,65 +1186,65 @@ C<isl_dim_out> (only for relations), C<isl_dim_set>
 (only for sets) or C<isl_dim_all>.
 
 	#include <isl/space.h>
-	unsigned isl_space_dim(__isl_keep isl_space *space,
+	isl_size isl_space_dim(__isl_keep isl_space *space,
 		enum isl_dim_type type);
 
 	#include <isl/local_space.h>
-	int isl_local_space_dim(__isl_keep isl_local_space *ls,
+	isl_size isl_local_space_dim(__isl_keep isl_local_space *ls,
 		enum isl_dim_type type);
 
 	#include <isl/set.h>
-	unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
+	isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
 		enum isl_dim_type type);
-	unsigned isl_set_dim(__isl_keep isl_set *set,
+	isl_size isl_set_dim(__isl_keep isl_set *set,
 		enum isl_dim_type type);
 
 	#include <isl/union_set.h>
-	unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+	isl_size isl_union_set_dim(__isl_keep isl_union_set *uset,
 		enum isl_dim_type type);
 
 	#include <isl/map.h>
-	unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
+	isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
 		enum isl_dim_type type);
-	unsigned isl_map_dim(__isl_keep isl_map *map,
+	isl_size isl_map_dim(__isl_keep isl_map *map,
 		enum isl_dim_type type);
 
 	#include <isl/union_map.h>
-	unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+	isl_size isl_union_map_dim(__isl_keep isl_union_map *umap,
 		enum isl_dim_type type);
 
 	#include <isl/val.h>
-	unsigned isl_multi_val_dim(__isl_keep isl_multi_val *mv,
+	isl_size isl_multi_val_dim(__isl_keep isl_multi_val *mv,
 		enum isl_dim_type type);
 
 	#include <isl/aff.h>
-	int isl_aff_dim(__isl_keep isl_aff *aff,
+	isl_size isl_aff_dim(__isl_keep isl_aff *aff,
 		enum isl_dim_type type);
-	unsigned isl_multi_aff_dim(__isl_keep isl_multi_aff *maff,
+	isl_size isl_multi_aff_dim(__isl_keep isl_multi_aff *maff,
 		enum isl_dim_type type);
-	unsigned isl_pw_aff_dim(__isl_keep isl_pw_aff *pwaff,
+	isl_size isl_pw_aff_dim(__isl_keep isl_pw_aff *pwaff,
 		enum isl_dim_type type);
-	unsigned isl_pw_multi_aff_dim(
+	isl_size isl_pw_multi_aff_dim(
 		__isl_keep isl_pw_multi_aff *pma,
 		enum isl_dim_type type);
-	unsigned isl_multi_pw_aff_dim(
+	isl_size isl_multi_pw_aff_dim(
 		__isl_keep isl_multi_pw_aff *mpa,
 		enum isl_dim_type type);
-	unsigned isl_union_pw_aff_dim(
+	isl_size isl_union_pw_aff_dim(
 		__isl_keep isl_union_pw_aff *upa,
 		enum isl_dim_type type);
-	unsigned isl_union_pw_multi_aff_dim(
+	isl_size isl_union_pw_multi_aff_dim(
 		__isl_keep isl_union_pw_multi_aff *upma,
 		enum isl_dim_type type);
-	unsigned isl_multi_union_pw_aff_dim(
+	isl_size isl_multi_union_pw_aff_dim(
 		__isl_keep isl_multi_union_pw_aff *mupa,
 		enum isl_dim_type type);
 
 	#include <isl/polynomial.h>
-	unsigned isl_union_pw_qpolynomial_dim(
+	isl_size isl_union_pw_qpolynomial_dim(
 		__isl_keep isl_union_pw_qpolynomial *upwqp,
 		enum isl_dim_type type);
-	unsigned isl_union_pw_qpolynomial_fold_dim(
+	isl_size isl_union_pw_qpolynomial_fold_dim(
 		__isl_keep isl_union_pw_qpolynomial_fold *upwf,
 		enum isl_dim_type type);
 
@@ -1212,6 +1264,13 @@ Additional parameters can be added to a space using the following function.
 If a parameter with the given identifier already appears in the space,
 then it is not added again.
 
+Conversely, all parameters can be removed from a space
+using the following function.
+
+	#include <isl/space.h>
+	__isl_give isl_space *isl_space_drop_all_params(
+		__isl_take isl_space *space);
+
 The identifiers or names of the individual dimensions of spaces
 may be set or read off using the following functions on spaces
 or objects that live in spaces.
@@ -1219,6 +1278,9 @@ These functions are mostly useful to obtain the identifiers, positions
 or names of the parameters.  Identifiers of individual dimensions are
 essentially only useful for printing.  They are ignored by all other
 operations and may not be preserved across those operations.
+To keep track of a space along with names/identifiers of
+the set dimensions, use an C<isl_multi_id> as described in
+L</"Functions">.
 
 	#include <isl/space.h>
 	__isl_give isl_space *isl_space_set_dim_id(
@@ -1386,6 +1448,7 @@ operations and may not be preserved across those operations.
 	isl_multi_union_pw_aff_set_dim_name(
 		__isl_take isl_multi_union_pw_aff *mupa,
 		enum isl_dim_type type, unsigned pos,
+		const char *s);
 	const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
 		enum isl_dim_type type, unsigned pos);
 	const char *isl_pw_aff_get_dim_name(
@@ -1481,7 +1544,7 @@ its position can be obtained from the following functions.
 		__isl_keep isl_multi_pw_aff *mpa,
 		enum isl_dim_type type, __isl_keep isl_id *id);
 	int isl_multi_union_pw_aff_find_dim_by_id(
-		__isl_keep isl_union_multi_pw_aff *mupa,
+		__isl_keep isl_multi_union_pw_aff *mupa,
 		enum isl_dim_type type, __isl_keep isl_id *id);
 	int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff,
 		enum isl_dim_type type, const char *name);
@@ -1736,6 +1799,10 @@ of all the corresponding identifiers, use the following function.
 	__isl_give isl_union_map *isl_union_map_reset_user(
 		__isl_take isl_union_map *umap);
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_reset_user(
+		__isl_take isl_multi_id *mi);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_reset_user(
 		__isl_take isl_multi_val *mv);
@@ -1861,13 +1928,24 @@ C<isl> has functions for creating some standard sets and relations.
 		__isl_take isl_space *space);
 	__isl_give isl_map *isl_map_empty(
 		__isl_take isl_space *space);
+	__isl_give isl_union_set *isl_union_set_empty_ctx(
+		isl_ctx *ctx);
+	__isl_give isl_union_set *isl_union_set_empty_space(
+		__isl_take isl_space *space);
 	__isl_give isl_union_set *isl_union_set_empty(
 		__isl_take isl_space *space);
+	__isl_give isl_union_map *isl_union_map_empty_ctx(
+		isl_ctx *ctx);
+	__isl_give isl_union_map *isl_union_map_empty_space(
+		__isl_take isl_space *space);
 	__isl_give isl_union_map *isl_union_map_empty(
 		__isl_take isl_space *space);
 
 For C<isl_union_set>s and C<isl_union_map>s, the space
 is only used to specify the parameters.
+C<isl_union_set_empty> is an alternative name for
+C<isl_union_set_empty_space>.
+Similarly for the other pair of functions.
 
 =item * Universe sets and relations
 
@@ -1965,8 +2043,15 @@ The inverse conversions below can only be used if the input
 union set or relation is known to contain elements in exactly one
 space.
 
+	#include <isl/union_set.h>
+	isl_bool isl_union_set_isa_set(
+		__isl_keep isl_union_set *uset);
 	__isl_give isl_set *isl_set_from_union_set(
 		__isl_take isl_union_set *uset);
+
+	#include <isl/union_map.h>
+	isl_bool isl_union_map_isa_map(
+		__isl_keep isl_union_map *umap);
 	__isl_give isl_map *isl_map_from_union_map(
 		__isl_take isl_union_map *umap);
 
@@ -2034,7 +2119,7 @@ using the following functions.
 		__isl_take isl_constraint *constraint);
 
 For example, to create a set containing the even integers
-between 10 and 42, you would use the following code.
+between 10 and 42, you could use the following code.
 
 	isl_space *space;
 	isl_local_space *ls;
@@ -2062,7 +2147,40 @@ between 10 and 42, you would use the following code.
 
 	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 1);
 
-Or, alternatively,
+However, this is considered to be a fairly low-level approach.
+It is more appropriate to construct a (basic) set by means
+of affine expressions (defined below in L</"Functions">).
+For example, the same set could be constructed as follows.
+
+	isl_val *v, *two;
+	isl_space *space;
+	isl_multi_aff *ma;
+	isl_aff *var, *cst;
+	isl_basic_set *bset;
+
+	space = isl_space_unit(ctx);
+	space = isl_space_add_unnamed_tuple_ui(space, 1);
+	ma = isl_multi_aff_identity_on_domain_space(
+		isl_space_copy(space));
+	var = isl_multi_aff_get_at(ma, 0);
+	v = isl_val_int_from_si(ctx, 10);
+	cst = isl_aff_val_on_domain_space(isl_space_copy(space), v);
+	bset = isl_aff_ge_basic_set(isl_aff_copy(var), cst);
+
+	v = isl_val_int_from_si(ctx, 42);
+	cst = isl_aff_val_on_domain_space(space, v);
+	bset = isl_basic_set_intersect(bset,
+		isl_aff_le_basic_set(var, cst));
+
+	two = isl_val_int_from_si(ctx, 2);
+	ma = isl_multi_aff_scale_val(ma, isl_val_copy(two));
+	bset = isl_basic_set_preimage_multi_aff(bset,
+		isl_multi_aff_copy(ma));
+	ma = isl_multi_aff_scale_down_val(ma, isl_val_copy(two));
+	ma = isl_multi_aff_scale_down_val(ma, two);
+	bset = isl_basic_set_preimage_multi_aff(bset, ma);
+
+Alternatively, the set can be parsed from a string representation.
 
 	isl_basic_set *bset;
 	bset = isl_basic_set_read_from_str(ctx,
@@ -2086,8 +2204,8 @@ describing the equalities and the inequalities.
 
 The C<isl_dim_type> arguments indicate the order in which
 
diff erent kinds of variables appear in the input matrices
-and should be a permutation of C<isl_dim_cst>, C<isl_dim_param>,
-C<isl_dim_set> and C<isl_dim_div> for sets and
+and should be a permutation of C<isl_dim_cst> (the constant term),
+C<isl_dim_param>, C<isl_dim_set> and C<isl_dim_div> for sets and
 of C<isl_dim_cst>, C<isl_dim_param>,
 C<isl_dim_in>, C<isl_dim_out> and C<isl_dim_div> for relations.
 
@@ -2229,6 +2347,11 @@ To iterate over all the sets or maps in a union set or map, use
 		__isl_keep isl_union_set *uset,
 		isl_stat (*fn)(__isl_take isl_set *set, void *user),
 		void *user);
+	isl_bool isl_union_set_every_set(
+		__isl_keep isl_union_set *uset,
+		isl_bool (*test)(__isl_keep isl_set *set,
+			void *user),
+		void *user);
 
 	#include <isl/union_map.h>
 	isl_stat isl_union_map_foreach_map(
@@ -2245,15 +2368,16 @@ These functions call the callback function once for each
 (pair of) space(s) for which there are elements in the input.
 The argument to the callback contains all elements in the input
 with that (pair of) space(s).
-The C<isl_union_map_every_map> variant check whether each
+The C<isl_union_set_every_set> and
+C<isl_union_map_every_map> variants check whether each
 call to the callback returns true and stops checking as soon as one
 of these calls returns false.
 
 The number of sets or maps in a union set or map can be obtained
 from
 
-	int isl_union_set_n_set(__isl_keep isl_union_set *uset);
-	int isl_union_map_n_map(__isl_keep isl_union_map *umap);
+	isl_size isl_union_set_n_set(__isl_keep isl_union_set *uset);
+	isl_size isl_union_map_n_map(__isl_keep isl_union_map *umap);
 
 To extract the set or map in a given space from a union, use
 
@@ -2294,10 +2418,10 @@ or the number of basic maps in a map can be obtained
 from
 
 	#include <isl/set.h>
-	int isl_set_n_basic_set(__isl_keep isl_set *set);
+	isl_size isl_set_n_basic_set(__isl_keep isl_set *set);
 
 	#include <isl/map.h>
-	int isl_map_n_basic_map(__isl_keep isl_map *map);
+	isl_size isl_map_n_basic_map(__isl_keep isl_map *map);
 
 It is also possible to obtain a list of (basic) sets from a set
 or union set, a list of basic maps from a map and a list of maps from a union
@@ -2328,14 +2452,14 @@ To iterate over the constraints of a basic set or map, use
 
 	#include <isl/constraint.h>
 
-	int isl_basic_set_n_constraint(
+	isl_size isl_basic_set_n_constraint(
 		__isl_keep isl_basic_set *bset);
 	isl_stat isl_basic_set_foreach_constraint(
 		__isl_keep isl_basic_set *bset,
 		isl_stat (*fn)(__isl_take isl_constraint *c,
 			void *user),
 		void *user);
-	int isl_basic_map_n_constraint(
+	isl_size isl_basic_map_n_constraint(
 		__isl_keep isl_basic_map *bmap);
 	isl_stat isl_basic_map_foreach_constraint(
 		__isl_keep isl_basic_map *bmap,
@@ -2424,7 +2548,8 @@ form, use the following functions.
 The C<isl_dim_type> arguments dictate the order in which
 
diff erent kinds of variables appear in the resulting matrix.
 For set inputs, they should be a permutation of
-C<isl_dim_cst>, C<isl_dim_param>, C<isl_dim_set> and C<isl_dim_div>.
+C<isl_dim_cst> (the constant term), C<isl_dim_param>, C<isl_dim_set> and
+C<isl_dim_div>.
 For map inputs, they should be a permutation of
 C<isl_dim_cst>, C<isl_dim_param>,
 C<isl_dim_in>, C<isl_dim_out> and C<isl_dim_div>.
@@ -2441,6 +2566,9 @@ The zero point (the origin) can be created using
 The coordinates of a point can be inspected, set and changed
 using
 
+	#include <isl/point.h>
+	__isl_give isl_multi_val *isl_point_get_multi_val(
+		__isl_keep isl_point *pnt);
 	__isl_give isl_val *isl_point_get_coordinate_val(
 		__isl_keep isl_point *pnt,
 		enum isl_dim_type type, int pos);
@@ -2524,6 +2652,9 @@ Besides sets and relation, C<isl> also supports various types of functions.
 Each of these types is derived from the value type (see L</"Values">)
 or from one of two primitive function types
 through the application of zero or more type constructors.
+As a special case, a multiple expression can also be derived
+from an identifier (see L</"Identifiers">) although the result
+is not really a function.
 We first describe the primitive type and then we describe
 the types derived from these primitive types.
 
@@ -2579,6 +2710,9 @@ a specified dimension on a given domain can be created using
 	#include <isl/aff.h>
 	__isl_give isl_aff *isl_aff_zero_on_domain(
 		__isl_take isl_local_space *ls);
+	__isl_give isl_aff *isl_aff_val_on_domain_space(
+		__isl_take isl_space *space,
+		__isl_take isl_val *val);
 	__isl_give isl_aff *isl_aff_val_on_domain(
 		__isl_take isl_local_space *ls,
 		__isl_take isl_val *val);
@@ -2735,15 +2869,16 @@ use
 The terms themselves can be inspected and freed using
 these functions
 
-	unsigned isl_term_dim(__isl_keep isl_term *term,
+	isl_size 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,
+	isl_size 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);
-	void isl_term_free(__isl_take isl_term *term);
+	__isl_null isl_term *isl_term_free(
+		__isl_take isl_term *term);
 
 Each term is a product of parameters, set variables and
 integer divisions.  The function C<isl_term_get_exp>
@@ -2771,9 +2906,24 @@ the following functions.
 	__isl_give isl_qpolynomial_fold *
 	isl_qpolynomial_fold_copy(
 		__isl_keep isl_qpolynomial_fold *fold);
-	void isl_qpolynomial_fold_free(
+	__isl_null isl_qpolynomial_fold *
+	isl_qpolynomial_fold_free(
 		__isl_take isl_qpolynomial_fold *fold);
 
+The type of a (union piecewise) reduction
+can be obtained using the following functions.
+
+	#include <isl/polynomial.h>
+	enum isl_fold isl_qpolynomial_fold_get_type(
+		__isl_keep isl_qpolynomial_fold *fold);
+	enum isl_fold isl_pw_qpolynomial_fold_get_type(
+		__isl_keep isl_pw_qpolynomial_fold *pwf);
+	enum isl_fold isl_union_pw_qpolynomial_fold_get_type(
+		__isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+The type may be either C<isl_fold_min> or C<isl_fold_max>
+(or C<isl_fold_error> in case of error).
+
 To iterate over all quasipolynomials in a reduction, use
 
 	isl_stat isl_qpolynomial_fold_foreach_qpolynomial(
@@ -2790,8 +2940,9 @@ as that of the base expressions, but the range space
 can be any space.  In case the base expressions have
 a set space, the corresponding multiple expression
 also has a set space.
-Objects of the value type do not have an associated space.
-The space of a multiple value is therefore always a set space.
+Objects of the value or identifier type do not have an associated space.
+The space of a multiple value or
+multiple identifier is therefore always a set space.
 Similarly, the space of a multiple union piecewise
 affine expression is always a set space.
 If the base expressions are not total, then
@@ -2800,7 +2951,7 @@ have an explicit domain that keeps track of the domain
 outside of any base expressions.
 
 The multiple expression types defined by C<isl>
-are C<isl_multi_val>, C<isl_multi_aff>, C<isl_multi_pw_aff>,
+are C<isl_multi_val>, C<isl_multi_id>, C<isl_multi_aff>, C<isl_multi_pw_aff>,
 C<isl_multi_union_pw_aff>.
 
 A multiple expression with the value zero for
@@ -2825,14 +2976,32 @@ value of type C<isl_union_pw_aff>, the space passed
 to C<isl_multi_union_pw_aff_zero> needs to be zero-dimensional.
 
 An identity function can be created using the following
-functions.  The space needs to be that of a relation
+functions.
+For the first group of functions, the space needs to be that of a set.
+For the second group,
+the space needs to be that of a relation
 with the same number of input and output dimensions.
+For the third group, the input function needs to live in a space
+with the same number of input and output dimensions and
+the identity function is created in that space.
 
 	#include <isl/aff.h>
+	__isl_give isl_multi_aff *
+	isl_multi_aff_identity_on_domain_space(
+		__isl_take isl_space *space);
+	__isl_give isl_multi_pw_aff *
+	isl_multi_pw_aff_identity_on_domain_space(
+		__isl_take isl_space *space);
 	__isl_give isl_multi_aff *isl_multi_aff_identity(
 		__isl_take isl_space *space);
 	__isl_give isl_multi_pw_aff *isl_multi_pw_aff_identity(
 		__isl_take isl_space *space);
+	__isl_give isl_multi_aff *
+	isl_multi_aff_identity_multi_aff(
+		__isl_take isl_multi_aff *ma);
+	__isl_give isl_multi_pw_aff *
+	isl_multi_pw_aff_identity_multi_pw_aff(
+		__isl_take isl_multi_pw_aff *mpa);
 
 A function that performs a projection on a universe
 relation or set can be created using the following functions.
@@ -2873,6 +3042,11 @@ as the domains of the base expressions in the list.
 If the base expressions have a set space (or no associated space),
 then this space also needs to be a set space.
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_from_id_list(
+		__isl_take isl_space *space,
+		__isl_take isl_id_list *list);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_from_val_list(
 		__isl_take isl_space *space,
@@ -2945,6 +3119,12 @@ using the following functions.
 Multiple expressions can be copied and freed using
 the following functions.
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_copy(
+		__isl_keep isl_multi_id *mi);
+	__isl_null isl_multi_id *isl_multi_id_free(
+		__isl_take isl_multi_id *mi);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_copy(
 		__isl_keep isl_multi_val *mv);
@@ -2967,38 +3147,108 @@ the following functions.
 	isl_multi_union_pw_aff_free(
 		__isl_take isl_multi_union_pw_aff *mupa);
 
+The number of base expressions in a multiple
+expression can be obtained using the following functions.
+
+	#include <isl/id.h>
+	int isl_multi_id_size(__isl_keep isl_multi_id *mi);
+
+	#include <isl/val.h>
+	isl_size isl_multi_val_size(__isl_keep isl_multi_val *mv);
+
+	#include <isl/aff.h>
+	isl_size isl_multi_aff_size(
+		__isl_keep isl_multi_aff *multi);
+	isl_size isl_multi_pw_aff_size(
+		__isl_keep isl_multi_pw_aff *mpa);
+	isl_size isl_multi_union_pw_aff_size(
+		__isl_keep isl_multi_union_pw_aff *mupa);
+
 The base expression at a given position of a multiple
 expression can be extracted using the following functions.
 
+	#include <isl/id.h>
+	__isl_give isl_id *isl_multi_id_get_at(
+		__isl_keep isl_multi_id *mi, int pos);
+	__isl_give isl_id *isl_multi_id_get_id(
+		__isl_keep isl_multi_id *mi, int pos);
+
 	#include <isl/val.h>
+	__isl_give isl_val *isl_multi_val_get_at(
+		__isl_keep isl_multi_val *mv, int pos);
 	__isl_give isl_val *isl_multi_val_get_val(
 		__isl_keep isl_multi_val *mv, int pos);
 
 	#include <isl/aff.h>
+	__isl_give isl_aff *isl_multi_aff_get_at(
+		__isl_keep isl_multi_aff *ma, int pos);
 	__isl_give isl_aff *isl_multi_aff_get_aff(
 		__isl_keep isl_multi_aff *multi, int pos);
+	__isl_give isl_pw_aff *isl_multi_pw_aff_get_at(
+		__isl_keep isl_multi_pw_aff *mpa, int pos);
 	__isl_give isl_pw_aff *isl_multi_pw_aff_get_pw_aff(
 		__isl_keep isl_multi_pw_aff *mpa, int pos);
 	__isl_give isl_union_pw_aff *
+	isl_multi_union_pw_aff_get_at(
+		__isl_keep isl_multi_union_pw_aff *mupa, int pos);
+	__isl_give isl_union_pw_aff *
 	isl_multi_union_pw_aff_get_union_pw_aff(
 		__isl_keep isl_multi_union_pw_aff *mupa, int pos);
 
-It can be replaced using the following functions.
+C<isl_multi_id_get_id> is an alternative name for C<isl_multi_id_get_at>.
+Similarly for the other pairs of functions.
+
+The base expression can be replaced using the following functions.
+
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_set_at(
+		__isl_take isl_multi_id *mi, int pos,
+		__isl_take isl_id *id);
+	__isl_give isl_multi_id *isl_multi_id_set_id(
+		__isl_take isl_multi_id *mi, int pos,
+		__isl_take isl_id *id);
 
 	#include <isl/val.h>
+	__isl_give isl_multi_val *isl_multi_val_set_at(
+		__isl_take isl_multi_val *mv, int pos,
+		__isl_take isl_val *val);
 	__isl_give isl_multi_val *isl_multi_val_set_val(
 		__isl_take isl_multi_val *mv, int pos,
 		__isl_take isl_val *val);
 
 	#include <isl/aff.h>
+	__isl_give isl_multi_aff *isl_multi_aff_set_at(
+		__isl_take isl_multi_aff *ma, int pos,
+		__isl_take isl_aff *aff);
 	__isl_give isl_multi_aff *isl_multi_aff_set_aff(
 		__isl_take isl_multi_aff *multi, int pos,
 		__isl_take isl_aff *aff);
+	__isl_give isl_multi_pw_aff *isl_multi_pw_aff_set_at(
+		__isl_take isl_multi_pw_aff *mpa, int pos,
+		__isl_take isl_pw_aff *pa);
+	__isl_give isl_multi_pw_aff *isl_multi_pw_aff_set_pw_aff(
+		__isl_take isl_multi_pw_aff *mpa, int pos,
+		__isl_take isl_pw_aff *pa);
+	__isl_give isl_multi_union_pw_aff *
+	isl_multi_union_pw_aff_set_at(
+		__isl_take isl_multi_union_pw_aff *mupa, int pos,
+		__isl_take isl_union_pw_aff *upa);
 	__isl_give isl_multi_union_pw_aff *
 	isl_multi_union_pw_aff_set_union_pw_aff(
 		__isl_take isl_multi_union_pw_aff *mupa, int pos,
 		__isl_take isl_union_pw_aff *upa);
 
+C<isl_multi_id_set_id> is an alternative name for C<isl_multi_id_set_at>.
+Similarly for the other pairs of functions.
+
+The constant terms of the base expressions can be obtained using
+the following function.
+
+	#include <isl/aff.h>
+	__isl_give isl_multi_val *
+	isl_multi_aff_get_constant_multi_val(
+		__isl_keep isl_multi_aff *ma);
+
 As a convenience, a sequence of base expressions that have
 their domains in a given space can be extracted from a sequence
 of union expressions using the following function.
@@ -3089,6 +3339,33 @@ created using the following functions.
 	__isl_give isl_pw_qpolynomial *
 	isl_pw_qpolynomial_from_qpolynomial(
 		__isl_take isl_qpolynomial *qp);
+	__isl_give isl_pw_qpolynomial_fold *
+	isl_pw_qpolynomial_fold_from_qpolynomial_fold(
+		__isl_take isl_qpolynomial_fold *fold);
+
+The inverse conversions below can only be used if the input
+expression is known to be defined over a single universe domain.
+
+	#include <isl/aff.h>
+	isl_bool isl_pw_aff_isa_aff(__isl_keep isl_pw_aff *pa);
+	__isl_give isl_aff *isl_pw_aff_as_aff(
+		__isl_take isl_pw_aff *pa);
+	isl_bool isl_pw_multi_aff_isa_multi_aff(
+		__isl_keep isl_pw_multi_aff *pma);
+	__isl_give isl_multi_aff *isl_pw_multi_aff_as_multi_aff(
+		__isl_take isl_pw_multi_aff *pma);
+
+	#include <isl/polynomial.h>
+	isl_bool isl_pw_qpolynomial_isa_qpolynomial(
+		__isl_keep isl_pw_qpolynomial *pwqp);
+	__isl_give isl_qpolynomial *
+	isl_pw_qpolynomial_as_qpolynomial(
+		__isl_take isl_pw_qpolynomial *pwqp);
+	isl_bool isl_pw_qpolynomial_fold_isa_qpolynomial_fold(
+		__isl_keep isl_pw_qpolynomial_fold *pwf);
+	__isl_give isl_qpolynomial_fold *
+	isl_pw_qpolynomial_fold_as_qpolynomial_fold(
+		__isl_take isl_pw_qpolynomial_fold *pwf);
 
 A piecewise expression with a single specified cell can be
 created using the following functions.
@@ -3143,6 +3420,9 @@ then create a piecewise expression over a given domain.
 	isl_pw_multi_aff_multi_val_on_domain(
 		__isl_take isl_set *domain,
 		__isl_take isl_multi_val *mv);
+	__isl_give isl_pw_aff *isl_pw_aff_param_on_domain_id(
+		__isl_take isl_set *domain,
+		__isl_take isl_id *id);
 
 As a convenience, a piecewise multiple expression can
 also be created from a piecewise expression.
@@ -3191,13 +3471,13 @@ use the following functions.
 
 	#include <isl/aff.h>
 	isl_bool isl_pw_aff_is_empty(__isl_keep isl_pw_aff *pwaff);
-	int isl_pw_aff_n_piece(__isl_keep isl_pw_aff *pwaff);
+	isl_size isl_pw_aff_n_piece(__isl_keep isl_pw_aff *pwaff);
 	isl_stat isl_pw_aff_foreach_piece(
 		__isl_keep isl_pw_aff *pwaff,
 		isl_stat (*fn)(__isl_take isl_set *set,
 			  __isl_take isl_aff *aff,
 			  void *user), void *user);
-	int isl_pw_multi_aff_n_piece(
+	isl_size isl_pw_multi_aff_n_piece(
 		__isl_keep isl_pw_multi_aff *pma);
 	isl_stat isl_pw_multi_aff_foreach_piece(
 		__isl_keep isl_pw_multi_aff *pma,
@@ -3206,7 +3486,7 @@ use the following functions.
 			    void *user), void *user);
 
 	#include <isl/polynomial.h>
-	int isl_pw_qpolynomial_n_piece(
+	isl_size isl_pw_qpolynomial_n_piece(
 		__isl_keep isl_pw_qpolynomial *pwqp);
 	isl_stat isl_pw_qpolynomial_foreach_piece(
 		__isl_keep isl_pw_qpolynomial *pwqp,
@@ -3218,7 +3498,7 @@ use the following functions.
 		isl_stat (*fn)(__isl_take isl_set *set,
 			  __isl_take isl_qpolynomial *qp,
 			  void *user), void *user);
-	int isl_pw_qpolynomial_fold_n_piece(
+	isl_size isl_pw_qpolynomial_fold_n_piece(
 		__isl_keep isl_pw_qpolynomial_fold *pwf);
 	isl_stat isl_pw_qpolynomial_fold_foreach_piece(
 		__isl_keep isl_pw_qpolynomial_fold *pwf,
@@ -3302,17 +3582,39 @@ but the domains of these expressions need to be disjoint.
 An empty union expression can be created using the following functions.
 
 	#include <isl/aff.h>
+	__isl_give isl_union_pw_aff *
+	isl_union_pw_aff_empty_ctx(
+		isl_ctx *ctx);
+	__isl_give isl_union_pw_aff *
+	isl_union_pw_aff_empty_space(
+		__isl_take isl_space *space);
 	__isl_give isl_union_pw_aff *isl_union_pw_aff_empty(
 		__isl_take isl_space *space);
 	__isl_give isl_union_pw_multi_aff *
+	isl_union_pw_multi_aff_empty_ctx(
+		isl_ctx *ctx);
+	__isl_give isl_union_pw_multi_aff *
+	isl_union_pw_multi_aff_empty_space(
+		__isl_take isl_space *space);
+	__isl_give isl_union_pw_multi_aff *
 	isl_union_pw_multi_aff_empty(
 		__isl_take isl_space *space);
 
 	#include <isl/polynomial.h>
 	__isl_give isl_union_pw_qpolynomial *
+	isl_union_pw_qpolynomial_zero_ctx(
+		isl_ctx *ctx);
+	__isl_give isl_union_pw_qpolynomial *
+	isl_union_pw_qpolynomial_zero_space(
+		__isl_take isl_space *space);
+	__isl_give isl_union_pw_qpolynomial *
 	isl_union_pw_qpolynomial_zero(
 		__isl_take isl_space *space);
 
+C<isl_union_pw_aff_empty> is an alternative name for
+C<isl_union_pw_aff_empty_space>.
+Similarly for the other pairs of functions.
+
 A union expression containing a single base expression
 can be created using the following functions.
 
@@ -3332,6 +3634,16 @@ can be created using the following functions.
 	isl_union_pw_qpolynomial_from_pw_qpolynomial(
 		__isl_take isl_pw_qpolynomial *pwqp);
 
+The inverse conversions below can only be used if the input
+expression is known to live in exactly one space.
+
+	#include <isl/aff.h>
+	isl_bool isl_union_pw_multi_aff_isa_pw_multi_aff(
+		__isl_keep isl_union_pw_multi_aff *upma);
+	__isl_give isl_pw_multi_aff *
+	isl_union_pw_multi_aff_as_pw_multi_aff(
+		__isl_take isl_union_pw_multi_aff *upma);
+
 The following functions create a base expression on each
 of the sets in the union set and collect the results.
 
@@ -3426,13 +3738,13 @@ To iterate over the base expressions in a union expression,
 use the following functions.
 
 	#include <isl/aff.h>
-	int isl_union_pw_aff_n_pw_aff(
+	isl_size isl_union_pw_aff_n_pw_aff(
 		__isl_keep isl_union_pw_aff *upa);
 	isl_stat isl_union_pw_aff_foreach_pw_aff(
 		__isl_keep isl_union_pw_aff *upa,
 		isl_stat (*fn)(__isl_take isl_pw_aff *pa,
 			void *user), void *user);
-	int isl_union_pw_multi_aff_n_pw_multi_aff(
+	isl_size isl_union_pw_multi_aff_n_pw_multi_aff(
 		__isl_keep isl_union_pw_multi_aff *upma);
 	isl_stat isl_union_pw_multi_aff_foreach_pw_multi_aff(
 		__isl_keep isl_union_pw_multi_aff *upma,
@@ -3440,13 +3752,13 @@ use the following functions.
 			    void *user), void *user);
 
 	#include <isl/polynomial.h>
-	int isl_union_pw_qpolynomial_n_pw_qpolynomial(
+	isl_size isl_union_pw_qpolynomial_n_pw_qpolynomial(
 		__isl_keep isl_union_pw_qpolynomial *upwqp);
 	isl_stat isl_union_pw_qpolynomial_foreach_pw_qpolynomial(
 		__isl_keep isl_union_pw_qpolynomial *upwqp,
 		isl_stat (*fn)(__isl_take isl_pw_qpolynomial *pwqp,
 			    void *user), void *user);
-	int isl_union_pw_qpolynomial_fold_n_pw_qpolynomial_fold(
+	isl_size isl_union_pw_qpolynomial_fold_n_pw_qpolynomial_fold(
 		__isl_keep isl_union_pw_qpolynomial_fold *upwf);
 	isl_stat isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
 		__isl_keep isl_union_pw_qpolynomial_fold *upwf,
@@ -3556,6 +3868,12 @@ dimensions is zero.
 
 Objects can be read from input using the following functions.
 
+	#include <isl/id.h>
+	__isl_give isl_id *isl_id_read_from_str(isl_ctx *ctx,
+		const char *str);
+	__isl_give isl_multi_id *isl_multi_id_read_from_str(
+		isl_ctx *ctx, const char *str);
+
 	#include <isl/val.h>
 	__isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx,
 		const char *str);
@@ -3725,6 +4043,11 @@ To actually print something, use
 		__isl_take isl_printer *p,
 		__isl_keep isl_multi_val *mv);
 
+	#include <isl/id.h>
+	__isl_give isl_printer *isl_printer_print_multi_id(
+		__isl_take isl_printer *p,
+		__isl_keep isl_multi_id *mi);
+
 	#include <isl/aff.h>
 	__isl_give isl_printer *isl_printer_print_aff(
 		__isl_take isl_printer *p, __isl_keep isl_aff *aff);
@@ -3842,6 +4165,8 @@ in isl format.
 	#include <isl/id.h>
 	__isl_give char *isl_id_to_str(
 		__isl_keep isl_id *id);
+	__isl_give char *isl_multi_id_to_str(
+		__isl_keep isl_multi_id *mi);
 
 	#include <isl/space.h>
 	__isl_give char *isl_space_to_str(
@@ -4011,6 +4336,9 @@ only maps elements to themselves.
 	__isl_give isl_val *isl_set_plain_get_val_if_fixed(
 		__isl_keep isl_set *set,
 		enum isl_dim_type type, unsigned pos);
+	__isl_give isl_multi_val *
+	isl_set_get_plain_multi_val_if_fixed(
+		__isl_keep isl_set *set);
 	__isl_give isl_val *isl_map_plain_get_val_if_fixed(
 		__isl_keep isl_map *map,
 		enum isl_dim_type type, unsigned pos);
@@ -4018,6 +4346,8 @@ only maps elements to themselves.
 If the set or relation obviously lies on a hyperplane where the given dimension
 has a fixed value, then return that value.
 Otherwise return NaN.
+C<isl_set_get_plain_multi_val_if_fixed> collects the results over
+all set dimensions.
 
 =item * Stride
 
@@ -4076,8 +4406,18 @@ functions.
 
 =item * Dependence
 
+To check whether a function involves any local variables,
+i.e., integer divisions,
+the following functions can be used.
+
+	#include <isl/aff.h>
+	isl_bool isl_aff_involves_locals(
+		__isl_keep isl_aff *aff);
+	isl_bool isl_multi_aff_involves_locals(
+		__isl_keep isl_multi_aff *ma);
+
 To check whether the description of a set, relation or function depends
-on one or more given dimensions,
+on a parameter or one or more given dimensions,
 the following functions can be used.
 
 	#include <isl/constraint.h>
@@ -4107,23 +4447,41 @@ the following functions can be used.
 	#include <isl/aff.h>
 	isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff,
 		enum isl_dim_type type, unsigned first, unsigned n);
+	isl_bool isl_pw_aff_involves_param_id(
+		__isl_keep isl_pw_aff *pa,
+		__isl_keep isl_id *id);
 	isl_bool isl_pw_aff_involves_dims(
 		__isl_keep isl_pw_aff *pwaff,
 		enum isl_dim_type type, unsigned first, unsigned n);
 	isl_bool isl_multi_aff_involves_dims(
 		__isl_keep isl_multi_aff *ma,
 		enum isl_dim_type type, unsigned first, unsigned n);
+	isl_bool isl_pw_multi_aff_involves_param_id(
+		__isl_keep isl_pw_multi_aff *pma,
+		__isl_keep isl_id *id);
 	isl_bool isl_pw_multi_aff_involves_dims(
 		__isl_keep isl_pw_multi_aff *pma,
 		enum isl_dim_type type, unsigned first, unsigned n);
 	isl_bool isl_multi_pw_aff_involves_dims(
 		__isl_keep isl_multi_pw_aff *mpa,
 		enum isl_dim_type type, unsigned first, unsigned n);
+	isl_bool isl_multi_pw_aff_involves_param_id(
+		__isl_keep isl_multi_pw_aff *mpa,
+		__isl_keep isl_id *id);
+	isl_bool isl_multi_pw_aff_involves_param_id_list(
+		__isl_keep isl_multi_pw_aff *mpa,
+		__isl_keep isl_id_list *list);
 
 	#include <isl/polynomial.h>
 	isl_bool isl_qpolynomial_involves_dims(
 		__isl_keep isl_qpolynomial *qp,
 		enum isl_dim_type type, unsigned first, unsigned n);
+	isl_bool isl_pw_qpolynomial_involves_param_id(
+		__isl_keep isl_pw_qpolynomial *pwqp,
+		__isl_keep isl_id *id);
+	isl_bool isl_pw_qpolynomial_fold_involves_param_id(
+		__isl_keep isl_pw_qpolynomial_fold *pwf,
+		__isl_keep isl_id *id);
 
 Similarly, the following functions can be used to check whether
 a given dimension is involved in any lower or upper bound.
@@ -4184,6 +4542,10 @@ The following functions check whether the space of the given
 		__isl_keep isl_map *map);
 	isl_bool isl_map_is_product(__isl_keep isl_map *map);
 
+	#include <isl/id.h>
+	isl_bool isl_multi_id_range_is_wrapping(
+		__isl_keep isl_multi_id *mi);
+
 	#include <isl/val.h>
 	isl_bool isl_multi_val_range_is_wrapping(
 		__isl_keep isl_multi_val *mv);
@@ -4297,6 +4659,12 @@ Check whether the given expression is a constant.
 
 Check whether the given expression is equal to or involves NaN.
 
+	#include <isl/val.h>
+	isl_bool isl_multi_val_is_zero(
+		__isl_keep isl_multi_val *mv);
+
+Check whether the multiple value is zero.
+
 	#include <isl/aff.h>
 	isl_bool isl_aff_plain_is_zero(
 		__isl_keep isl_aff *aff);
@@ -4351,6 +4719,11 @@ return true if the objects are not the same.
 		__isl_keep isl_union_map *umap1,
 		__isl_keep isl_union_map *umap2);
 
+	#include <isl/id.h>
+	isl_bool isl_multi_id_plain_is_equal(
+		__isl_keep isl_multi_id *mi1,
+		__isl_keep isl_multi_id *mi2);
+
 	#include <isl/val.h>
 	isl_bool isl_multi_val_plain_is_equal(
 		__isl_keep isl_multi_val *mv1,
@@ -4536,16 +4909,117 @@ earlier dimensions before those that involve later dimensions.
 	#include <isl/space.h>
 	__isl_give isl_space *isl_space_reverse(
 		__isl_take isl_space *space);
+	__isl_give isl_space *isl_space_range_reverse(
+		__isl_take isl_space *space);
 
 	#include <isl/map.h>
 	__isl_give isl_basic_map *isl_basic_map_reverse(
 		__isl_take isl_basic_map *bmap);
 	__isl_give isl_map *isl_map_reverse(
 		__isl_take isl_map *map);
+	__isl_give isl_map *isl_map_range_reverse(
+		__isl_take isl_map *map);
 
 	#include <isl/union_map.h>
 	__isl_give isl_union_map *isl_union_map_reverse(
 		__isl_take isl_union_map *umap);
+	__isl_give isl_union_map *isl_union_map_range_reverse(
+		__isl_take isl_union_map *umap);
+
+The function C<isl_space_range_reverse> reverses the relation
+that is embedded in the range of the input map space.
+The identifier of the range, if any, is only preserved
+if this embedded relation has identical input and output tuples.
+
+=item * Tuple binding
+
+The following function binds
+a tuple to a sequence of parameter identifiers, equating
+the tuple dimensions to the parameters with those identifiers and
+subsequently projecting out the tuple.
+If the original object did not reference any such parameters,
+then this means that the tuple dimensions are reinterpreted
+as parameters.
+The space of C<tuple> needs to match that of the bound tuple.
+
+	#include <isl/set.h>
+	__isl_give isl_set *isl_set_bind(
+		__isl_take isl_set *set,
+		__isl_take isl_multi_id *tuple);
+
+	#include <isl/map.h>
+	__isl_give isl_set *isl_map_bind_domain(
+		__isl_take isl_map *map,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_set *isl_map_bind_range(
+		__isl_take isl_map *map,
+		__isl_take isl_multi_id *tuple);
+
+	#include <isl/union_map.h>
+	__isl_give isl_union_set *isl_union_map_bind_range(
+		__isl_take isl_union_map *umap,
+		__isl_take isl_multi_id *tuple);
+
+	#include <isl/aff.h>
+	__isl_give isl_pw_aff *isl_pw_aff_bind_domain(
+		__isl_take isl_pw_aff *pa,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_multi_aff *isl_multi_aff_bind_domain(
+		__isl_take isl_multi_aff *ma,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_bind_domain(
+		__isl_take isl_pw_multi_aff *pma,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_multi_pw_aff *
+	isl_multi_pw_aff_bind_domain(
+		__isl_take isl_multi_pw_aff *mpa,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_pw_aff *
+	isl_pw_aff_bind_domain_wrapped_domain(
+		__isl_take isl_pw_aff *pa,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_multi_aff *
+	isl_multi_aff_bind_domain_wrapped_domain(
+		__isl_take isl_multi_aff *ma,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_bind_domain_wrapped_domain(
+		__isl_take isl_pw_multi_aff *pma,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_multi_pw_aff *
+	isl_multi_pw_aff_bind_domain_wrapped_domain(
+		__isl_take isl_multi_pw_aff *mpa,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_basic_set *isl_aff_bind_id(
+		__isl_take isl_aff *aff,
+		__isl_take isl_id *id);
+	__isl_give isl_set *isl_pw_aff_bind_id(
+		__isl_take isl_pw_aff *pa,
+		__isl_take isl_id *id);
+	__isl_give isl_basic_set *isl_multi_aff_bind(
+		__isl_take isl_multi_aff *ma,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_set *isl_multi_pw_aff_bind(
+		__isl_take isl_multi_pw_aff *mpa,
+		__isl_take isl_multi_id *tuple);
+	__isl_give isl_union_set *isl_union_pw_aff_bind_id(
+		__isl_take isl_union_pw_aff *upa,
+		__isl_take isl_id *id);
+	__isl_give isl_union_set *
+	isl_multi_union_pw_aff_bind(
+		__isl_take isl_multi_union_pw_aff *mupa,
+		__isl_take isl_multi_id *tuple);
+
+Projecting out the domain of the wrapped relation in the domain
+of a function leaves the range of that wrapped relation
+in the domain of the resulting function.
+In the case of C<isl_aff_bind_id>, C<isl_pw_aff_bind_id>,
+C<isl_multi_aff_bind>, C<isl_multi_pw_aff_bind>,
+C<isl_union_pw_aff_bind_id> and
+C<isl_multi_union_pw_aff_bind>, the parameters
+are bound to the function values and the result lives
+in the domain of the input function.
 
 =item * Projection
 
@@ -4567,8 +5041,17 @@ earlier dimensions before those that involve later dimensions.
 	__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_param_id(
+		__isl_take isl_set *set,
+		__isl_take isl_id *id);
+	__isl_give isl_set *
+	isl_set_project_out_param_id_list(
+		__isl_take isl_set *set,
+		__isl_take isl_id_list *list);
 	__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_set *isl_set_project_out_all_params(
+		__isl_take isl_set *set);
 	__isl_give isl_map *isl_set_project_onto_map(
 		__isl_take isl_set *set,
 		enum isl_dim_type type, unsigned first,
@@ -4586,6 +5069,8 @@ that projects the input set onto the given set dimensions.
 		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_map *isl_map_project_out_all_params(
+		__isl_take isl_map *map);
 	__isl_give isl_basic_set *isl_basic_map_domain(
 		__isl_take isl_basic_map *bmap);
 	__isl_give isl_basic_set *isl_basic_map_range(
@@ -4601,6 +5086,9 @@ that projects the input set onto the given set dimensions.
 		__isl_take isl_union_set *uset,
 		enum isl_dim_type type,
 		unsigned first, unsigned n);
+	__isl_give isl_union_set *
+	isl_union_set_project_out_all_params(
+		__isl_take isl_union_set *uset);
 	__isl_give isl_set *isl_union_set_params(
 		__isl_take isl_union_set *uset);
 
@@ -4731,6 +5219,28 @@ without removing the dimensions.
 
 =item * Constructing a set from a parameter domain
 
+A set space of a given dimension and with an optional name
+can be created from a parameter space using the following functions.
+
+	#include <isl/space.h>
+	__isl_give isl_space *isl_space_add_unnamed_tuple_ui(
+		__isl_take isl_space *space, unsigned dim);
+	__isl_give isl_space *
+	isl_space_add_named_tuple_id_ui(
+		__isl_take isl_space *space,
+		__isl_take isl_id *tuple_id, unsigned dim);
+
+A set with a given tuple can be created from a parameter domain
+using the following function.
+
+	#include <isl/set.h>
+	__isl_give isl_set *isl_set_unbind_params(
+		__isl_take isl_set *set,
+		__isl_take isl_multi_id *tuple);
+
+Any parameters with identifiers in C<tuple> are reinterpreted
+as the corresponding set dimensions.
+
 A zero-dimensional (local) space or (basic) set can be constructed
 on a given parameter domain using the following functions.
 
@@ -4751,10 +5261,44 @@ on a given parameter domain using the following functions.
 
 =item * Constructing a relation from one or two sets
 
+A map space with a range of a given dimension and with an optional name
+can be created from a domain space using the functions
+C<isl_space_add_unnamed_tuple_ui> and C<isl_space_add_named_tuple_id_ui>
+described above.
+
+A relation with a given domain tuple can be created from a set
+that will become the range of the relation
+using the following function.
+
+	#include <isl/set.h>
+	__isl_give isl_map *
+	isl_set_unbind_params_insert_domain(
+		__isl_take isl_set *set,
+		__isl_take isl_multi_id *domain);
+
+Any parameters with identifiers in C<domain> are reinterpreted
+as the corresponding input dimensions.
+
+Similarly, a function defined over a parameter domain can
+be converted into one defined over a set domain
+using the following function.
+
+	#include <isl/aff.h>
+	__isl_give isl_aff *
+	isl_aff_unbind_params_insert_domain(
+		__isl_take isl_aff *aff,
+		__isl_take isl_multi_id *domain);
+
+Again,
+any parameters with identifiers in C<domain> are reinterpreted
+as the corresponding input dimensions.
+
 Create a relation with the given set(s) as domain and/or range.
 If only the domain or the range is specified, then
 the range or domain of the created relation is a zero-dimensional
 flat anonymous space.
+If the case of C<isl_space_map_from_set>, the input space
+specifies both the domain and the range of the result.
 
 	#include <isl/space.h>
 	__isl_give isl_space *isl_space_from_domain(
@@ -4787,6 +5331,10 @@ flat anonymous space.
 		__isl_take isl_union_set *domain,
 		__isl_take isl_union_set *range);
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_from_range(
+		__isl_take isl_multi_id *mi);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_from_range(
 		__isl_take isl_multi_val *mv);
@@ -4894,6 +5442,18 @@ dimension has the fixed given value.
 		__isl_take isl_set *set,
 		enum isl_dim_type type, unsigned pos,
 		__isl_take isl_val *value);
+	__isl_give isl_set *isl_set_lower_bound_multi_val(
+		__isl_take isl_set *set,
+		__isl_take isl_multi_val *lower);
+	__isl_give isl_set *isl_set_upper_bound_multi_val(
+		__isl_take isl_set *set,
+		__isl_take isl_multi_val *upper);
+	__isl_give isl_set *isl_set_lower_bound_multi_pw_aff(
+		__isl_take isl_set *set,
+		__isl_take isl_multi_pw_aff *lower);
+	__isl_give isl_set *isl_set_upper_bound_multi_pw_aff(
+		__isl_take isl_set *set,
+		__isl_take isl_multi_pw_aff *upper);
 
 	#include <isl/map.h>
 	__isl_give isl_basic_map *isl_basic_map_lower_bound_si(
@@ -4908,9 +5468,33 @@ dimension has the fixed given 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_give isl_map *isl_map_lower_bound_val(
+		__isl_take isl_map *map,
+		enum isl_dim_type type, unsigned pos,
+		__isl_take isl_val *value);
+	__isl_give isl_map *isl_map_upper_bound_val(
+		__isl_take isl_map *map,
+		enum isl_dim_type type, unsigned pos,
+		__isl_take isl_val *value);
+	__isl_give isl_map *isl_map_lower_bound_multi_val(
+		__isl_take isl_map *map,
+		__isl_take isl_multi_val *lower);
+	__isl_give isl_map *isl_map_upper_bound_multi_val(
+		__isl_take isl_map *map,
+		__isl_take isl_multi_val *upper);
+	__isl_give isl_map *isl_map_lower_bound_multi_pw_aff(
+		__isl_take isl_map *map,
+		__isl_take isl_multi_pw_aff *lower);
+	__isl_give isl_map *isl_map_upper_bound_multi_pw_aff(
+		__isl_take isl_map *map,
+		__isl_take isl_multi_pw_aff *upper);
 
 Intersect the set or relation with the half-space where the given
-dimension has a value bounded by the fixed given integer value.
+dimension has a value bounded by the given fixed integer value or
+symbolic constant expression.
+For functions taking a multi expression,
+this applies to all set dimensions.
+Those that bound a map, bound the range of that map.
 
 	__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
 		enum isl_dim_type type1, int pos1,
@@ -5094,7 +5678,7 @@ basic set or relation.
 
 	#include <isl/aff.h>
 	__isl_give isl_pw_aff *isl_pw_aff_coalesce(
-		__isl_take isl_pw_aff *pwqp);
+		__isl_take isl_pw_aff *pa);
 	__isl_give isl_pw_multi_aff *isl_pw_multi_aff_coalesce(
 		__isl_take isl_pw_multi_aff *pma);
 	__isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
@@ -5106,7 +5690,7 @@ basic set or relation.
 		__isl_take isl_union_pw_multi_aff *upma);
 	__isl_give isl_multi_union_pw_aff *
 	isl_multi_union_pw_aff_coalesce(
-		__isl_take isl_multi_union_pw_aff *aff);
+		__isl_take isl_multi_union_pw_aff *mupa);
 
 	#include <isl/polynomial.h>
 	__isl_give isl_pw_qpolynomial_fold *
@@ -5284,18 +5868,26 @@ per space.
 
 =item * Box hull
 
+	#include <isl/set.h>
+	__isl_give isl_fixed_box *
+	isl_set_get_simple_fixed_box_hull(
+		__isl_keep isl_set *set)
+
 	#include <isl/map.h>
 	__isl_give isl_fixed_box *
 	isl_map_get_range_simple_fixed_box_hull(
 		__isl_keep isl_map *map);
 
-This function tries to approximate the range of the map by a box of fixed size.
+These functions try to approximate the set or
+the range of the map by a box of fixed size.
 The box is described in terms of an offset living in the same space as
-the input map and a size living in the range space.  For any element
+the input and a size living in the set or range space.  For any element
 in the input map, the range value is greater than or equal to
 the offset applied to the domain value and the 
diff erence with
 this offset is strictly smaller than the size.
-If no fixed-size approximation of the range can be found,
+The same holds for the elements of the input set, where
+the offset is a parametric constant value.
+If no fixed-size approximation can be found,
 an I<invalid> box is returned, i.e., one for which
 C<isl_fixed_box_is_valid> below returns false.
 
@@ -5318,6 +5910,18 @@ The box can be copied and freed using the following functions.
 	__isl_null isl_fixed_box *isl_fixed_box_free(
 		__isl_take isl_fixed_box *box);
 
+A representation of the information contained in an object
+of type C<isl_fixed_box> can be obtained using
+
+	#include <isl/fixed_box.h>
+	__isl_give isl_printer *isl_printer_print_fixed_box(
+		__isl_take isl_printer *p,
+		__isl_keep isl_fixed_box *box);
+	__isl_give char *isl_fixed_box_to_str(
+		__isl_keep isl_fixed_box *box);
+
+C<isl_fixed_box_to_str> prints the information in flow format.
+
 =item * Other approximations
 
 	#include <isl/set.h>
@@ -5505,9 +6109,9 @@ If the exponent C<exp> is negative, then the -C<exp> th power of the inverse
 of C<map> is computed.
 
 	__isl_give isl_map *isl_map_power(__isl_take isl_map *map,
-		int *exact);
+		isl_bool *exact);
 	__isl_give isl_union_map *isl_union_map_power(
-		__isl_take isl_union_map *umap, int *exact);
+		__isl_take isl_union_map *umap, isl_bool *exact);
 
 Compute a parametric representation for all positive powers I<k> of C<map>.
 The result maps I<k> to a nested relation corresponding to the
@@ -5518,9 +6122,9 @@ then C<*exact> is set to C<1>.
 =item * Transitive closure
 
 	__isl_give isl_map *isl_map_transitive_closure(
-		__isl_take isl_map *map, int *exact);
+		__isl_take isl_map *map, isl_bool *exact);
 	__isl_give isl_union_map *isl_union_map_transitive_closure(
-		__isl_take isl_union_map *umap, int *exact);
+		__isl_take isl_union_map *umap, isl_bool *exact);
 
 Compute the transitive closure of C<map>.
 The result may be an overapproximation.  If the result is known to be exact,
@@ -5529,7 +6133,7 @@ then C<*exact> is set to C<1>.
 =item * Reaching path lengths
 
 	__isl_give isl_map *isl_map_reaching_path_lengths(
-		__isl_take isl_map *map, int *exact);
+		__isl_take isl_map *map, isl_bool *exact);
 
 Compute a relation that maps each element in the range of C<map>
 to the lengths of all paths composed of edges in C<map> that
@@ -5623,6 +6227,10 @@ then the name of the space is also removed.
 	__isl_give isl_map *isl_map_flatten(
 		__isl_take isl_map *map);
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_flatten_range(
+		__isl_take isl_multi_id *mi);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_flatten_range(
 		__isl_take isl_multi_val *mv);
@@ -5774,6 +6382,11 @@ All parameters need to be named.
 		__isl_take isl_map *map,
 		__isl_take isl_space *model);
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_align_params(
+		__isl_take isl_multi_id *mi,
+		__isl_take isl_space *model);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_align_params(
 		__isl_take isl_multi_val *mv,
@@ -6167,6 +6780,12 @@ the same (number of) parameters.
 	__isl_give isl_set *isl_set_intersect(
 		__isl_take isl_set *set1,
 		__isl_take isl_set *set2);
+	__isl_give isl_set *isl_set_intersect_factor_domain(
+		__isl_take isl_set *set,
+		__isl_take isl_set *domain);
+	__isl_give isl_set *isl_set_intersect_factor_range(
+		__isl_take isl_set *set,
+		__isl_take isl_set *range);
 
 	#include <isl/map.h>
 	__isl_give isl_basic_map *isl_basic_map_intersect_domain(
@@ -6197,6 +6816,10 @@ the same (number of) parameters.
 		__isl_take isl_map *map,
 		__isl_take isl_map *factor);
 	__isl_give isl_map *
+	isl_map_intersect_range_factor_domain(
+		__isl_take isl_map *map,
+		__isl_take isl_map *factor);
+	__isl_give isl_map *
 	isl_map_intersect_range_factor_range(
 		__isl_take isl_map *map,
 		__isl_take isl_map *factor);
@@ -6223,6 +6846,14 @@ the same (number of) parameters.
 		__isl_take isl_union_map *umap1,
 		__isl_take isl_union_map *umap2);
 	__isl_give isl_union_map *
+	isl_union_map_intersect_domain_factor_range(
+		__isl_take isl_union_map *umap,
+		__isl_take isl_union_map *factor);
+	__isl_give isl_union_map *
+	isl_union_map_intersect_range_factor_domain(
+		__isl_take isl_union_map *umap,
+		__isl_take isl_union_map *factor);
+	__isl_give isl_union_map *
 	isl_union_map_intersect_range_factor_range(
 		__isl_take isl_union_map *umap,
 		__isl_take isl_union_map *factor);
@@ -6249,6 +6880,38 @@ the same (number of) parameters.
 	isl_multi_union_pw_aff_intersect_domain(
 		__isl_take isl_multi_union_pw_aff *mupa,
 		__isl_take isl_union_set *uset);
+	__isl_give isl_pw_aff *
+	isl_pw_aff_intersect_domain_wrapped_domain(
+		__isl_take isl_pw_aff *pa,
+		__isl_take isl_set *set);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_intersect_domain_wrapped_domain(
+		__isl_take isl_pw_multi_aff *pma,
+		__isl_take isl_set *set);
+	__isl_give isl_union_pw_aff *
+	isl_union_pw_aff_intersect_domain_wrapped_domain(
+		__isl_take isl_union_pw_aff *upa,
+		__isl_take isl_union_set *uset);
+	__isl_give isl_union_pw_multi_aff *
+	isl_union_pw_multi_aff_intersect_domain_wrapped_domain(
+		__isl_take isl_union_pw_multi_aff *upma,
+		__isl_take isl_union_set *uset);
+	__isl_give isl_pw_aff *
+	isl_pw_aff_intersect_domain_wrapped_range(
+		__isl_take isl_pw_aff *pa,
+		__isl_take isl_set *set);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_intersect_domain_wrapped_range(
+		__isl_take isl_pw_multi_aff *pma,
+		__isl_take isl_set *set);
+	__isl_give isl_union_pw_multi_aff *
+	isl_union_pw_multi_aff_intersect_domain_wrapped_range(
+		__isl_take isl_union_pw_multi_aff *upma,
+		__isl_take isl_union_set *uset);
+	__isl_give isl_union_pw_aff *
+	isl_union_pw_aff_intersect_domain_wrapped_range(
+		__isl_take isl_union_pw_aff *upa,
+		__isl_take isl_union_set *uset);
 	__isl_give isl_pw_aff *isl_pw_aff_intersect_params(
 		__isl_take isl_pw_aff *pa,
 		__isl_take isl_set *set);
@@ -6262,6 +6925,7 @@ the same (number of) parameters.
 	__isl_give isl_union_pw_aff *
 	isl_union_pw_aff_intersect_params(
 		__isl_take isl_union_pw_aff *upa,
+		__isl_take isl_set *set);
 	__isl_give isl_union_pw_multi_aff *
 	isl_union_pw_multi_aff_intersect_params(
 		__isl_take isl_union_pw_multi_aff *upma,
@@ -6270,6 +6934,7 @@ the same (number of) parameters.
 	isl_multi_union_pw_aff_intersect_params(
 		__isl_take isl_multi_union_pw_aff *mupa,
 		__isl_take isl_set *params);
+	__isl_give isl_multi_union_pw_aff *
 	isl_multi_union_pw_aff_intersect_range(
 		__isl_take isl_multi_union_pw_aff *mupa,
 		__isl_take isl_set *set);
@@ -6288,6 +6953,38 @@ the same (number of) parameters.
 		__isl_take isl_union_pw_qpolynomial_fold *upwf,
 		__isl_take isl_union_set *uset);
 	__isl_give isl_pw_qpolynomial *
+	isl_pw_qpolynomial_intersect_domain_wrapped_domain(
+		__isl_take isl_pw_qpolynomial *pwpq,
+		__isl_take isl_set *set);
+	__isl_give isl_pw_qpolynomial_fold *
+	isl_pw_qpolynomial_fold_intersect_domain_wrapped_domain(
+		__isl_take isl_pw_qpolynomial_fold *pwf,
+		__isl_take isl_set *set);
+	__isl_give isl_union_pw_qpolynomial *
+	isl_union_pw_qpolynomial_intersect_domain_wrapped_domain(
+		__isl_take isl_union_pw_qpolynomial *upwpq,
+		__isl_take isl_union_set *uset);
+	__isl_give isl_union_pw_qpolynomial_fold *
+	isl_union_pw_qpolynomial_fold_intersect_domain_wrapped_domain(
+		__isl_take isl_union_pw_qpolynomial_fold *upwf,
+		__isl_take isl_union_set *uset);
+	__isl_give isl_pw_qpolynomial *
+	isl_pw_qpolynomial_intersect_domain_wrapped_range(
+		__isl_take isl_pw_qpolynomial *pwpq,
+		__isl_take isl_set *set);
+	__isl_give isl_pw_qpolynomial_fold *
+	isl_pw_qpolynomial_fold_intersect_domain_wrapped_range(
+		__isl_take isl_pw_qpolynomial_fold *pwf,
+		__isl_take isl_set *set);
+	__isl_give isl_union_pw_qpolynomial *
+	isl_union_pw_qpolynomial_intersect_domain_wrapped_range(
+		__isl_take isl_union_pw_qpolynomial *upwpq,
+		__isl_take isl_union_set *uset);
+	__isl_give isl_union_pw_qpolynomial_fold *
+	isl_union_pw_qpolynomial_fold_intersect_domain_wrapped_range(
+		__isl_take isl_union_pw_qpolynomial_fold *upwf,
+		__isl_take isl_union_set *uset);
+	__isl_give isl_pw_qpolynomial *
 	isl_pw_qpolynomial_intersect_params(
 		__isl_take isl_pw_qpolynomial *pwpq,
 		__isl_take isl_set *set);
@@ -6398,7 +7095,7 @@ at least one element and all elements need to live in the same space.
 	__isl_give isl_union_pw_multi_aff *
 	isl_union_pw_multi_aff_subtract_domain(
 		__isl_take isl_union_pw_multi_aff *upma,
-		__isl_take isl_set *set);
+		__isl_take isl_union_set *uset);
 
 	#include <isl/polynomial.h>
 	__isl_give isl_pw_qpolynomial *
@@ -6425,16 +7122,20 @@ at least one element and all elements need to live in the same space.
 		__isl_take isl_space *left,
 		__isl_take isl_space *right);
 
-	#include <isl/map.h>
+	#include <isl/set.h>
 	__isl_give isl_basic_set *isl_basic_set_apply(
 		__isl_take isl_basic_set *bset,
 		__isl_take isl_basic_map *bmap);
 	__isl_give isl_set *isl_set_apply(
 		__isl_take isl_set *set,
 		__isl_take isl_map *map);
+
+	#include <isl/union_set.h>
 	__isl_give isl_union_set *isl_union_set_apply(
 		__isl_take isl_union_set *uset,
 		__isl_take isl_union_map *umap);
+
+	#include <isl/map.h>
 	__isl_give isl_basic_map *isl_basic_map_apply_domain(
 		__isl_take isl_basic_map *bmap1,
 		__isl_take isl_basic_map *bmap2);
@@ -6488,22 +7189,22 @@ Similarly for C<isl_multi_union_pw_aff_apply_pw_multi_aff>.
 	isl_set_apply_pw_qpolynomial_fold(
 		__isl_take isl_set *set,
 		__isl_take isl_pw_qpolynomial_fold *pwf,
-		int *tight);
+		isl_bool *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_bool *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_bool *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_bool *tight);
 
 The functions taking a map
 compose the given map with the given piecewise quasipolynomial reduction.
@@ -6767,9 +7468,15 @@ C<isl_pw_aff> function to each pair of elements in the two lists.
 	__isl_give isl_map *isl_pw_aff_eq_map(
 		__isl_take isl_pw_aff *pa1,
 		__isl_take isl_pw_aff *pa2);
+	__isl_give isl_map *isl_pw_aff_le_map(
+		__isl_take isl_pw_aff *pa1,
+		__isl_take isl_pw_aff *pa2);
 	__isl_give isl_map *isl_pw_aff_lt_map(
 		__isl_take isl_pw_aff *pa1,
 		__isl_take isl_pw_aff *pa2);
+	__isl_give isl_map *isl_pw_aff_ge_map(
+		__isl_take isl_pw_aff *pa1,
+		__isl_take isl_pw_aff *pa2);
 	__isl_give isl_map *isl_pw_aff_gt_map(
 		__isl_take isl_pw_aff *pa1,
 		__isl_take isl_pw_aff *pa2);
@@ -6870,6 +7577,11 @@ two input spaces.
 		__isl_take isl_union_map *umap1,
 		__isl_take isl_union_map *umap2);
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_range_product(
+		__isl_take isl_multi_id *mi1,
+		__isl_take isl_multi_id *mi2);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_range_product(
 		__isl_take isl_multi_val *mv1,
@@ -6945,6 +7657,12 @@ instead.
 		__isl_take isl_union_map *umap1,
 		__isl_take isl_union_map *umap2);
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *
+	isl_multi_id_flat_range_product(
+		__isl_take isl_multi_id *mi1,
+		__isl_take isl_multi_id *mi2);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_flat_range_product(
 		__isl_take isl_multi_val *mv1,
@@ -7024,6 +7742,16 @@ from the result using the following functions.
 	isl_union_map_range_factor_range(
 		__isl_take isl_union_map *umap);
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_factor_range(
+		__isl_take isl_multi_id *mi);
+	__isl_give isl_multi_id *
+	isl_multi_id_range_factor_domain(
+		__isl_take isl_multi_id *mi);
+	__isl_give isl_multi_id *
+	isl_multi_id_range_factor_range(
+		__isl_take isl_multi_id *mi);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_factor_range(
 		__isl_take isl_multi_val *mv);
@@ -7052,6 +7780,18 @@ from the result using the following functions.
 	__isl_give isl_multi_pw_aff *
 	isl_multi_pw_aff_range_factor_range(
 		__isl_take isl_multi_pw_aff *mpa);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_range_factor_domain(
+		__isl_take isl_pw_multi_aff *pma);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_range_factor_range(
+		__isl_take isl_pw_multi_aff *pma);
+	__isl_give isl_union_pw_multi_aff *
+	isl_union_pw_multi_aff_range_factor_domain(
+		__isl_take isl_union_pw_multi_aff *upma);
+	__isl_give isl_union_pw_multi_aff *
+	isl_union_pw_multi_aff_range_factor_range(
+		__isl_take isl_union_pw_multi_aff *upma);
 	__isl_give isl_multi_union_pw_aff *
 	isl_multi_union_pw_aff_factor_range(
 		__isl_take isl_multi_union_pw_aff *mupa);
@@ -7071,6 +7811,11 @@ C<isl_multi_pw_aff_factor_range> and
 C<isl_multi_union_pw_aff_factor_range>
 take functions that live in a set space.
 
+	#include <isl/id.h>
+	__isl_give isl_multi_id *isl_multi_id_range_splice(
+		__isl_take isl_multi_id *mi1, unsigned pos,
+		__isl_take isl_multi_id *mi2);
+
 	#include <isl/val.h>
 	__isl_give isl_multi_val *isl_multi_val_range_splice(
 		__isl_take isl_multi_val *mv1, unsigned pos,
@@ -7212,11 +7957,11 @@ to simplify the expression associated to each cell.
 		__isl_take isl_union_set *context);
 	__isl_give isl_multi_union_pw_aff *
 	isl_multi_union_pw_aff_gist_params(
-		__isl_take isl_multi_union_pw_aff *aff,
+		__isl_take isl_multi_union_pw_aff *mupa,
 		__isl_take isl_set *context);
 	__isl_give isl_multi_union_pw_aff *
 	isl_multi_union_pw_aff_gist(
-		__isl_take isl_multi_union_pw_aff *aff,
+		__isl_take isl_multi_union_pw_aff *mupa,
 		__isl_take isl_union_set *context);
 
 	#include <isl/polynomial.h>
@@ -7316,6 +8061,33 @@ in the two arguments.
 	isl_multi_union_pw_aff_add(
 		__isl_take isl_multi_union_pw_aff *mupa1,
 		__isl_take isl_multi_union_pw_aff *mupa2);
+	__isl_give isl_pw_aff *isl_pw_aff_add_constant_val(
+		__isl_take isl_pw_aff *pa,
+		__isl_take isl_val *v);
+	__isl_give isl_multi_aff *
+	isl_multi_aff_add_constant_val(
+		__isl_take isl_multi_aff *pa,
+		__isl_take isl_val *v);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_add_constant_val(
+		__isl_take isl_pw_multi_aff *pma,
+		__isl_take isl_val *v);
+	__isl_give isl_pw_multi_aff *
+	isl_pw_multi_aff_add_constant_multi_val(
+		__isl_take isl_pw_multi_aff *pma,
+		__isl_take isl_multi_val *mv);
+	__isl_give isl_multi_pw_aff *
+	isl_multi_pw_aff_add_constant_val(
+		__isl_take isl_multi_pw_aff *mpa,
+		__isl_take isl_val *v);
+	__isl_give isl_multi_aff *
+	isl_multi_aff_add_constant_multi_val(
+		__isl_take isl_multi_aff *pa,
+		__isl_take isl_multi_val *mv);
+	__isl_give isl_multi_pw_aff *
+	isl_multi_pw_aff_add_constant_multi_val(
+		__isl_take isl_multi_pw_aff *mpa,
+		__isl_take isl_multi_val *mv);
 	__isl_give isl_pw_aff *isl_pw_aff_min(
 		__isl_take isl_pw_aff *pwaff1,
 		__isl_take isl_pw_aff *pwaff2);
@@ -7453,10 +8225,10 @@ only defined on the shared definition domain of the arguments.
 	__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_union_pw_multi_aff *
 	__isl_give isl_union_pw_aff *isl_union_pw_aff_scale_val(
 		__isl_take isl_union_pw_aff *upa,
 		__isl_take isl_val *f);
+	__isl_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);
@@ -7857,6 +8629,8 @@ Lists can be created, copied, modified and freed using the following functions.
 	__isl_give isl_set_list *isl_set_list_drop(
 		__isl_take isl_set_list *list,
 		unsigned first, unsigned n);
+	__isl_give isl_set_list *isl_set_list_clear(
+		__isl_take isl_set_list *list);
 	__isl_give isl_set_list *isl_set_list_swap(
 		__isl_take isl_set_list *list,
 		unsigned pos1, unsigned pos2);
@@ -7885,14 +8659,15 @@ C<isl_set_list_alloc> creates an empty list with an initial capacity
 for C<n> elements.  C<isl_set_list_insert> and C<isl_set_list_add>
 add elements to a list, increasing its capacity as needed.
 C<isl_set_list_from_set> creates a list with a single element.
+C<isl_set_list_clear> removes all elements from a list.
 C<isl_set_list_swap> swaps the elements at the specified locations.
 C<isl_set_list_reverse> reverses the elements in the list.
 
 Lists can be inspected using the following functions.
 
 	#include <isl/set.h>
-	int isl_set_list_size(__isl_keep isl_set_list *list);
-	int isl_set_list_n_set(__isl_keep isl_set_list *list);
+	isl_size isl_set_list_size(__isl_keep isl_set_list *list);
+	isl_size isl_set_list_n_set(__isl_keep isl_set_list *list);
 	__isl_give isl_set *isl_set_list_get_at(
 		__isl_keep isl_set_list *list, int index);
 	__isl_give isl_set *isl_set_list_get_set(
@@ -7924,6 +8699,14 @@ Lists can be printed using
 		__isl_take isl_printer *p,
 		__isl_keep isl_set_list *list);
 
+Alternatively, a string representation can be obtained
+directly using the following function, which always prints
+in isl format.
+
+	#include <isl/set.h>
+	__isl_give char *isl_set_list_to_str(
+		__isl_keep isl_set_list *list);
+
 =head2 Associative arrays
 
 Associative arrays map isl objects of a specific type to isl objects
@@ -8015,7 +8798,7 @@ may have arbitrary values.
 A vector created by C<isl_vec_zero> has elements with value zero.
 The elements can be changed and inspected using the following functions.
 
-	int isl_vec_size(__isl_keep isl_vec *vec);
+	isl_size 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(
@@ -8051,8 +8834,8 @@ Matrices can be created, copied and freed using the following functions.
 Note that the elements of a newly created matrix may have arbitrary values.
 The elements can be changed and inspected using the following functions.
 
-	int isl_mat_rows(__isl_keep isl_mat *mat);
-	int isl_mat_cols(__isl_keep isl_mat *mat);
+	isl_size isl_mat_rows(__isl_keep isl_mat *mat);
+	isl_size 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,
@@ -8065,7 +8848,7 @@ The following function computes the rank of a matrix.
 The return value may be -1 if some error occurred.
 
 	#include <isl/mat.h>
-	int isl_mat_rank(__isl_keep isl_mat *mat);
+	isl_size isl_mat_rank(__isl_keep isl_mat *mat);
 
 The following function can be used to compute the (right) inverse
 of a matrix, i.e., a matrix such that the product of the original
@@ -8111,12 +8894,12 @@ an upper or lower bound on a quasipolynomial over its domain.
 	__isl_give isl_pw_qpolynomial_fold *
 	isl_pw_qpolynomial_bound(
 		__isl_take isl_pw_qpolynomial *pwqp,
-		enum isl_fold type, int *tight);
+		enum isl_fold type, isl_bool *tight);
 
 	__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);
+		enum isl_fold type, isl_bool *tight);
 
 The C<type> argument may be either C<isl_fold_min> or C<isl_fold_max>.
 If C<tight> is not C<NULL>, then C<*tight> is set to C<1>
@@ -8162,19 +8945,20 @@ and then iterating over all vertices that are active on the chamber.
 Other operations that can be performed on an C<isl_vertices> object are
 the following.
 
-	int isl_vertices_get_n_vertices(
+	isl_size isl_vertices_get_n_vertices(
 		__isl_keep isl_vertices *vertices);
 	__isl_null isl_vertices *isl_vertices_free(
 		__isl_take isl_vertices *vertices);
 
 Vertices can be inspected and destroyed using the following functions.
 
-	int isl_vertex_get_id(__isl_keep isl_vertex *vertex);
+	isl_size 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_null isl_vertex *isl_vertex_free(
+		__isl_take isl_vertex *vertex);
 
 C<isl_vertex_get_expr> returns a multiple quasi-affine expression
 describing the vertex in terms of the parameters,
@@ -8185,7 +8969,8 @@ Chambers can be inspected and destroyed using the following functions.
 
 	__isl_give isl_basic_set *isl_cell_get_domain(
 		__isl_keep isl_cell *cell);
-	void isl_cell_free(__isl_take isl_cell *cell);
+	__isl_null isl_cell *isl_cell_free(
+		__isl_take isl_cell *cell);
 
 =head1 Polyhedral Compilation Library
 
@@ -8567,7 +9352,7 @@ exists.
 	__isl_give isl_schedule_node *isl_schedule_node_ancestor(
 		__isl_take isl_schedule_node *node,
 		int generation);
-	int isl_schedule_node_n_children(
+	isl_size isl_schedule_node_n_children(
 		__isl_keep isl_schedule_node *node);
 	__isl_give isl_schedule_node *isl_schedule_node_child(
 		__isl_take isl_schedule_node *node, int pos);
@@ -8600,11 +9385,11 @@ shared ancestor can be obtained using
 C<isl_schedule_node_get_shared_ancestor>.
 
 	#include <isl/schedule_node.h>
-	int isl_schedule_node_get_tree_depth(
+	isl_size isl_schedule_node_get_tree_depth(
 		__isl_keep isl_schedule_node *node);
-	int isl_schedule_node_get_child_position(
+	isl_size isl_schedule_node_get_child_position(
 		__isl_keep isl_schedule_node *node);
-	int isl_schedule_node_get_ancestor_child_position(
+	isl_size isl_schedule_node_get_ancestor_child_position(
 		__isl_keep isl_schedule_node *node,
 		__isl_keep isl_schedule_node *ancestor);
 	__isl_give isl_schedule_node *isl_schedule_node_get_child(
@@ -8746,7 +9531,7 @@ Several node types have their own functions for querying
 	__isl_give isl_union_map *
 	isl_schedule_node_band_get_partial_schedule_union_map(
 		__isl_keep isl_schedule_node *node);
-	unsigned isl_schedule_node_band_n_member(
+	isl_size isl_schedule_node_band_n_member(
 		__isl_keep isl_schedule_node *node);
 	isl_bool isl_schedule_node_band_member_get_coincident(
 		__isl_keep isl_schedule_node *node, int pos);
@@ -8766,7 +9551,6 @@ Several node types have their own functions for querying
 	isl_schedule_node_band_member_set_ast_loop_type(
 		__isl_take isl_schedule_node *node, int pos,
 		enum isl_ast_loop_type type);
-	__isl_give isl_union_set *
 	enum isl_ast_loop_type
 	isl_schedule_node_band_member_get_isolate_ast_loop_type(
 		__isl_keep isl_schedule_node *node, int pos);
@@ -8774,6 +9558,7 @@ Several node types have their own functions for querying
 	isl_schedule_node_band_member_set_isolate_ast_loop_type(
 		__isl_take isl_schedule_node *node, int pos,
 		enum isl_ast_loop_type type);
+	__isl_give isl_union_set *
 	isl_schedule_node_band_get_ast_build_options(
 		__isl_keep isl_schedule_node *node);
 	__isl_give isl_schedule_node *
@@ -8913,7 +9698,7 @@ of C<isl_schedule_node_get_prefix_schedule_union_map> can be obtained
 using the following function.
 
 	#include <isl/schedule_node.h>
-	int isl_schedule_node_get_schedule_depth(
+	isl_size isl_schedule_node_get_schedule_depth(
 		__isl_keep isl_schedule_node *node);
 
 The following functions return the elements that reach the given node
@@ -9383,7 +10168,8 @@ A lower-level interface is provided by the following functions.
 		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_null isl_flow *isl_flow_free(
+		__isl_take isl_flow *deps);
 
 The function C<isl_access_info_compute_flow> performs the actual
 dependence analysis.  The other functions are used to construct
@@ -9969,13 +10755,27 @@ exactly once.
 	#include <isl/ast.h>
 	__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_node(
+		__isl_keep isl_ast_node *node);
 	__isl_give isl_ast_node *isl_ast_node_if_get_then(
 		__isl_keep isl_ast_node *node);
+	isl_bool isl_ast_node_if_has_else_node(
+		__isl_keep isl_ast_node *node);
 	isl_bool isl_ast_node_if_has_else(
 		__isl_keep isl_ast_node *node);
+	__isl_give isl_ast_node *isl_ast_node_if_get_else_node(
+		__isl_keep isl_ast_node *node);
 	__isl_give isl_ast_node *isl_ast_node_if_get_else(
 		__isl_keep isl_ast_node *node);
 
+C<isl_ast_node_if_get_then>,
+C<isl_ast_node_if_has_else> and
+C<isl_ast_node_if_get_else>
+are alternative names for
+C<isl_ast_node_if_get_then_node>,
+C<isl_ast_node_if_has_else_node> and
+C<isl_ast_node_if_get_else_node>, respectively.
+
 	__isl_give isl_ast_node_list *
 	isl_ast_node_block_get_children(
 		__isl_keep isl_ast_node *node);
@@ -10025,102 +10825,127 @@ An C<isl_ast_expr_int> represents an integer value.
 Each type of expression has its own additional properties.
 
 	#include <isl/ast.h>
-	enum isl_ast_op_type isl_ast_expr_get_op_type(
+	enum isl_ast_expr_op_type isl_ast_expr_op_get_type(
 		__isl_keep isl_ast_expr *expr);
-	int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+	enum isl_ast_expr_op_type isl_ast_expr_get_op_type(
+		__isl_keep isl_ast_expr *expr);
+	isl_size isl_ast_expr_op_get_n_arg(__isl_keep isl_ast_expr *expr);
+	isl_size isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+	__isl_give isl_ast_expr *isl_ast_expr_op_get_arg(
+		__isl_keep isl_ast_expr *expr, int pos);
 	__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(
 		__isl_keep isl_ast_expr *expr, int pos);
+	isl_stat isl_ast_expr_foreach_ast_expr_op_type(
+		__isl_keep isl_ast_expr *expr,
+		isl_stat (*fn)(enum isl_ast_expr_op_type type,
+			void *user), void *user);
 	isl_stat isl_ast_expr_foreach_ast_op_type(
 		__isl_keep isl_ast_expr *expr,
-		isl_stat (*fn)(enum isl_ast_op_type type,
+		isl_stat (*fn)(enum isl_ast_expr_op_type type,
+			void *user), void *user);
+	isl_stat isl_ast_node_foreach_ast_expr_op_type(
+		__isl_keep isl_ast_node *node,
+		isl_stat (*fn)(enum isl_ast_expr_op_type type,
 			void *user), void *user);
 	isl_stat isl_ast_node_foreach_ast_op_type(
 		__isl_keep isl_ast_node *node,
-		isl_stat (*fn)(enum isl_ast_op_type type,
+		isl_stat (*fn)(enum isl_ast_expr_op_type type,
 			void *user), void *user);
 
-C<isl_ast_expr_get_op_type> returns the type of the operation
-performed.  C<isl_ast_expr_get_op_n_arg> returns the number of
+C<isl_ast_expr_op_get_type> returns the type of the operation
+performed.  C<isl_ast_expr_op_get_n_arg> returns the number of
 arguments.  C<isl_ast_expr_get_op_arg> returns the specified
 argument.
-C<isl_ast_expr_foreach_ast_op_type> calls C<fn> for each distinct
-C<isl_ast_op_type> that appears in C<expr>.
-C<isl_ast_node_foreach_ast_op_type> does the same for each distinct
-C<isl_ast_op_type> that appears in C<node>.
+C<isl_ast_expr_get_op_type> is an alternative name for
+C<isl_ast_expr_op_get_type>.
+Similarly,
+C<isl_ast_expr_get_op_n_arg> is an alternative name for
+C<isl_ast_expr_op_get_n_arg> and
+C<isl_ast_expr_get_op_arg> is an alternative name for
+C<isl_ast_expr_op_get_arg>.
+
+C<isl_ast_expr_foreach_ast_expr_op_type> calls C<fn> for each distinct
+C<isl_ast_expr_op_type> that appears in C<expr>.
+C<isl_ast_expr_foreach_ast_op_type> is an alternative name for
+C<isl_ast_expr_foreach_ast_expr_op_type>.
+C<isl_ast_node_foreach_ast_expr_op_type> does the same for each distinct
+C<isl_ast_expr_op_type> that appears in C<node>.
+C<isl_ast_node_foreach_ast_op_type> is an alternative name for
+C<isl_ast_node_foreach_ast_expr_op_type>.
 The operation type is one of the following.
 
 =over
 
-=item C<isl_ast_op_and>
+=item C<isl_ast_expr_op_and>
 
 Logical I<and> of two arguments.
 Both arguments can be evaluated.
 
-=item C<isl_ast_op_and_then>
+=item C<isl_ast_expr_op_and_then>
 
 Logical I<and> of two arguments.
 The second argument can only be evaluated if the first evaluates to true.
 
-=item C<isl_ast_op_or>
+=item C<isl_ast_expr_op_or>
 
 Logical I<or> of two arguments.
 Both arguments can be evaluated.
 
-=item C<isl_ast_op_or_else>
+=item C<isl_ast_expr_op_or_else>
 
 Logical I<or> of two arguments.
 The second argument can only be evaluated if the first evaluates to false.
 
-=item C<isl_ast_op_max>
+=item C<isl_ast_expr_op_max>
 
 Maximum of two or more arguments.
 
-=item C<isl_ast_op_min>
+=item C<isl_ast_expr_op_min>
 
 Minimum of two or more arguments.
 
-=item C<isl_ast_op_minus>
+=item C<isl_ast_expr_op_minus>
 
 Change sign.
 
-=item C<isl_ast_op_add>
+=item C<isl_ast_expr_op_add>
 
 Sum of two arguments.
 
-=item C<isl_ast_op_sub>
+=item C<isl_ast_expr_op_sub>
 
 Difference of two arguments.
 
-=item C<isl_ast_op_mul>
+=item C<isl_ast_expr_op_mul>
 
 Product of two arguments.
 
-=item C<isl_ast_op_div>
+=item C<isl_ast_expr_op_div>
 
 Exact division.  That is, the result is known to be an integer.
 
-=item C<isl_ast_op_fdiv_q>
+=item C<isl_ast_expr_op_fdiv_q>
 
 Result of integer division, rounded towards negative
 infinity.
 The divisor is known to be positive.
 
-=item C<isl_ast_op_pdiv_q>
+=item C<isl_ast_expr_op_pdiv_q>
 
 Result of integer division, where dividend is known to be non-negative.
 The divisor is known to be positive.
 
-=item C<isl_ast_op_pdiv_r>
+=item C<isl_ast_expr_op_pdiv_r>
 
 Remainder of integer division, where dividend is known to be non-negative.
 The divisor is known to be positive.
 
-=item C<isl_ast_op_zdiv_r>
+=item C<isl_ast_expr_op_zdiv_r>
 
 Equal to zero iff the remainder on integer division is zero.
 The divisor is known to be positive.
 
-=item C<isl_ast_op_cond>
+=item C<isl_ast_expr_op_cond>
 
 Conditional operator defined on three arguments.
 If the first argument evaluates to true, then the result
@@ -10130,7 +10955,7 @@ The second and third argument may only be evaluated if
 the first argument evaluates to true and false, respectively.
 Corresponds to C<a ? b : c> in C.
 
-=item C<isl_ast_op_select>
+=item C<isl_ast_expr_op_select>
 
 Conditional operator defined on three arguments.
 If the first argument evaluates to true, then the result
@@ -10140,41 +10965,41 @@ The second and third argument may be evaluated independently
 of the value of the first argument.
 Corresponds to C<a * b + (1 - a) * c> in C.
 
-=item C<isl_ast_op_eq>
+=item C<isl_ast_expr_op_eq>
 
 Equality relation.
 
-=item C<isl_ast_op_le>
+=item C<isl_ast_expr_op_le>
 
 Less than or equal relation.
 
-=item C<isl_ast_op_lt>
+=item C<isl_ast_expr_op_lt>
 
 Less than relation.
 
-=item C<isl_ast_op_ge>
+=item C<isl_ast_expr_op_ge>
 
 Greater than or equal relation.
 
-=item C<isl_ast_op_gt>
+=item C<isl_ast_expr_op_gt>
 
 Greater than relation.
 
-=item C<isl_ast_op_call>
+=item C<isl_ast_expr_op_call>
 
 A function call.
 The number of arguments of the C<isl_ast_expr> is one more than
 the number of arguments in the function call, the first argument
 representing the function being called.
 
-=item C<isl_ast_op_access>
+=item C<isl_ast_expr_op_access>
 
 An array access.
 The number of arguments of the C<isl_ast_expr> is one more than
 the number of index expressions in the array access, the first argument
 representing the array being accessed.
 
-=item C<isl_ast_op_member>
+=item C<isl_ast_expr_op_member>
 
 A member access.
 This operation has two arguments, a structure and the name of
@@ -10183,16 +11008,24 @@ the member of the structure being accessed.
 =back
 
 	#include <isl/ast.h>
+	__isl_give isl_id *isl_ast_expr_id_get_id(
+		__isl_keep isl_ast_expr *expr);
 	__isl_give isl_id *isl_ast_expr_get_id(
 		__isl_keep isl_ast_expr *expr);
 
 Return the identifier represented by the AST expression.
+C<isl_ast_expr_get_id> is an alternative name for
+C<isl_ast_expr_id_get_id>.
 
 	#include <isl/ast.h>
+	__isl_give isl_val *isl_ast_expr_int_get_val(
+		__isl_keep isl_ast_expr *expr);
 	__isl_give isl_val *isl_ast_expr_get_val(
 		__isl_keep isl_ast_expr *expr);
 
 Return the integer represented by the AST expression.
+C<isl_ast_expr_get_val> is an alternative name for
+C<isl_ast_expr_int_get_val>.
 
 =head3 Properties of ASTs
 
@@ -10286,7 +11119,7 @@ the context of an C<isl_ast_build>.
 		__isl_take isl_ast_expr_list *arguments);
 
 The function C<isl_ast_expr_address_of> can be applied to an
-C<isl_ast_expr> of type C<isl_ast_op_access> only. It is meant
+C<isl_ast_expr> of type C<isl_ast_expr_op_access> only. It is meant
 to represent the address of the C<isl_ast_expr_access>.
 The second argument of the functions C<isl_ast_expr_pdiv_q> and
 C<isl_ast_expr_pdiv_r> should always evaluate to a positive number.
@@ -10382,15 +11215,23 @@ that return a string representation of the input in C format.
 More advanced printing can be performed using the following functions.
 
 	#include <isl/ast.h>
+	__isl_give isl_printer *
+	isl_ast_expr_op_type_set_print_name(
+		__isl_take isl_printer *p,
+		enum isl_ast_expr_op_type type,
+		__isl_keep const char *name);
 	__isl_give isl_printer *isl_ast_op_type_set_print_name(
 		__isl_take isl_printer *p,
-		enum isl_ast_op_type type,
+		enum isl_ast_expr_op_type type,
 		__isl_keep const char *name);
 	isl_stat isl_options_set_ast_print_macro_once(
 		isl_ctx *ctx, int val);
 	int isl_options_get_ast_print_macro_once(isl_ctx *ctx);
+	__isl_give isl_printer *isl_ast_expr_op_type_print_macro(
+		enum isl_ast_expr_op_type type,
+		__isl_take isl_printer *p);
 	__isl_give isl_printer *isl_ast_op_type_print_macro(
-		enum isl_ast_op_type type,
+		enum isl_ast_expr_op_type type,
 		__isl_take isl_printer *p);
 	__isl_give isl_printer *isl_ast_expr_print_macros(
 		__isl_keep isl_ast_expr *expr,
@@ -10415,17 +11256,22 @@ While printing an C<isl_ast_node> in C<ISL_FORMAT_C>,
 C<isl> may print out an AST that makes use of macros such
 as C<floord>, C<min> and C<max>.
 The names of these macros may be modified by a call
-to C<isl_ast_op_type_set_print_name>.  The user-specified
+to C<isl_ast_expr_op_type_set_print_name>.  The user-specified
 names are associated to the printer object.
-C<isl_ast_op_type_print_macro> prints out the macro
-corresponding to a specific C<isl_ast_op_type>.
+C<isl_ast_op_type_set_print_name> is an alternative name for
+C<isl_ast_expr_op_type_set_print_name>.
+C<isl_ast_expr_op_type_print_macro> prints out the macro
+corresponding to a specific C<isl_ast_expr_op_type>.
 If the print-macro-once option is set, then a given macro definition
 is only printed once to any given printer object.
+C<isl_ast_op_type_print_macro> is an alternative name for
+C<isl_ast_expr_op_type_print_macro>.
 C<isl_ast_expr_print_macros> scans the C<isl_ast_expr>
 for subexpressions where these macros would be used and prints
 out the required macro definitions.
 Essentially, C<isl_ast_expr_print_macros> calls
-C<isl_ast_expr_foreach_ast_op_type> with C<isl_ast_op_type_print_macro>
+C<isl_ast_expr_foreach_ast_expr_op_type> with
+C<isl_ast_expr_op_type_print_macro>
 as function argument.
 C<isl_ast_node_print_macros> does the same
 for expressions in its C<isl_ast_node> argument.
@@ -10556,12 +11402,12 @@ When the option is turned on, the following AST is generated
 =item * ast_build_prefer_pdiv
 
 If this option is turned off, then the AST generation will
-produce ASTs that may only contain C<isl_ast_op_fdiv_q>
-operators, but no C<isl_ast_op_pdiv_q> or
-C<isl_ast_op_pdiv_r> operators.
+produce ASTs that may only contain C<isl_ast_expr_op_fdiv_q>
+operators, but no C<isl_ast_expr_op_pdiv_q> or
+C<isl_ast_expr_op_pdiv_r> operators.
 If this option is turned on, then C<isl> will try to convert
-some of the C<isl_ast_op_fdiv_q> operators to (expressions containing)
-C<isl_ast_op_pdiv_q> or C<isl_ast_op_pdiv_r> operators.
+some of the C<isl_ast_expr_op_fdiv_q> operators to (expressions containing)
+C<isl_ast_expr_op_pdiv_q> or C<isl_ast_expr_op_pdiv_r> operators.
 
 =item * ast_build_detect_min_max
 

diff  --git a/polly/lib/External/isl/has_single_reference_templ.c b/polly/lib/External/isl/has_single_reference_templ.c
new file mode 100644
index 000000000000..332f6b22e245
--- /dev/null
+++ b/polly/lib/External/isl/has_single_reference_templ.c
@@ -0,0 +1,12 @@
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Does "obj" have a single reference?
+ * That is, can "obj" be changed inplace?
+ */
+isl_bool FN(TYPE,has_single_reference)(__isl_keep TYPE *obj)
+{
+	if (!obj)
+		return isl_bool_error;
+	return obj->ref == 1;
+}

diff  --git a/polly/lib/External/isl/include/isl/aff.h b/polly/lib/External/isl/include/isl/aff.h
index 9b4116171186..cd2b74b1b63d 100644
--- a/polly/lib/External/isl/include/isl/aff.h
+++ b/polly/lib/External/isl/include/isl/aff.h
@@ -4,6 +4,7 @@
 #include <isl/stdint.h>
 #include <isl/local_space.h>
 #include <isl/printer.h>
+#include <isl/id_type.h>
 #include <isl/set_type.h>
 #include <isl/aff_type.h>
 #include <isl/list.h>
@@ -17,6 +18,8 @@ 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_space(__isl_take isl_space *space,
+	__isl_take isl_val *val);
 __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,
@@ -31,7 +34,9 @@ __isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff);
 isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff);
 uint32_t isl_aff_get_hash(__isl_keep isl_aff *aff);
 
-int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type);
+isl_bool isl_aff_involves_locals(__isl_keep isl_aff *aff);
+
+isl_size isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type);
 isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff,
 	enum isl_dim_type type, unsigned first, unsigned n);
 
@@ -57,6 +62,7 @@ __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
 __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_overload
 __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);
@@ -127,15 +133,20 @@ __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
 __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_export
+__isl_give isl_aff *isl_aff_unbind_params_insert_domain(
+	__isl_take isl_aff *aff, __isl_take isl_multi_id *domain);
 
 __isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
 	__isl_take isl_space *model);
 
+__isl_export
 __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_export
 __isl_give isl_val *isl_aff_eval(__isl_take isl_aff *aff,
 	__isl_take isl_point *pnt);
 
@@ -177,6 +188,10 @@ __isl_export
 __isl_give isl_set *isl_aff_gt_set(__isl_take isl_aff *aff1,
 	__isl_take isl_aff *aff2);
 
+__isl_overload
+__isl_give isl_basic_set *isl_aff_bind_id(__isl_take isl_aff *aff,
+	__isl_take isl_id *id);
+
 __isl_constructor
 __isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str);
 __isl_give char *isl_aff_to_str(__isl_keep isl_aff *aff);
@@ -191,7 +206,7 @@ __isl_give isl_space *isl_pw_aff_get_space(__isl_keep isl_pw_aff *pwaff);
 
 __isl_constructor
 __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_empty(__isl_take isl_space *space);
 __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(
@@ -201,7 +216,11 @@ __isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls,
 __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_overload
+__isl_give isl_pw_aff *isl_pw_aff_param_on_domain_id(
+	__isl_take isl_set *domain, __isl_take isl_id *id);
 
+__isl_export
 __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,
@@ -236,7 +255,9 @@ __isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
 __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);
+isl_size isl_pw_aff_dim(__isl_keep isl_pw_aff *pwaff, enum isl_dim_type type);
+isl_bool isl_pw_aff_involves_param_id(__isl_keep isl_pw_aff *pa,
+	__isl_keep isl_id *id);
 isl_bool isl_pw_aff_involves_dims(__isl_keep isl_pw_aff *pwaff,
 	enum isl_dim_type type, unsigned first, unsigned n);
 
@@ -261,6 +282,7 @@ __isl_give isl_pw_aff *isl_pw_aff_reset_tuple_id(__isl_take isl_pw_aff *pa,
 __isl_give isl_pw_aff *isl_pw_aff_reset_user(__isl_take isl_pw_aff *pa);
 
 __isl_give isl_set *isl_pw_aff_params(__isl_take isl_pw_aff *pwa);
+__isl_export
 __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);
 
@@ -298,10 +320,17 @@ __isl_export
 __isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2);
 
+__isl_export
 __isl_give isl_pw_aff *isl_pw_aff_intersect_params(__isl_take isl_pw_aff *pa,
 	__isl_take isl_set *set);
+__isl_export
 __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_intersect_domain_wrapped_domain(
+	__isl_take isl_pw_aff *pa, __isl_take isl_set *set);
+__isl_give isl_pw_aff *isl_pw_aff_intersect_domain_wrapped_range(
+	__isl_take isl_pw_aff *pa, __isl_take isl_set *set);
+__isl_export
 __isl_give isl_pw_aff *isl_pw_aff_subtract_domain(__isl_take isl_pw_aff *pa,
 	__isl_take isl_set *set);
 
@@ -310,6 +339,9 @@ __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_overload
+__isl_give isl_pw_aff *isl_pw_aff_add_constant_val(__isl_take isl_pw_aff *pa,
+	__isl_take isl_val *v);
+__isl_overload
 __isl_give isl_pw_aff *isl_pw_aff_scale_val(__isl_take isl_pw_aff *pa,
 	__isl_take isl_val *v);
 __isl_overload
@@ -326,12 +358,15 @@ __isl_give isl_pw_aff *isl_pw_aff_move_dims(__isl_take isl_pw_aff *pa,
 __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_export
+__isl_give isl_pw_aff *isl_pw_aff_coalesce(__isl_take isl_pw_aff *pa);
+__isl_export
 __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_export
 __isl_give isl_val *isl_pw_aff_eval(__isl_take isl_pw_aff *pa,
 	__isl_take isl_point *pnt);
 
@@ -345,10 +380,14 @@ __isl_overload
 __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);
+isl_size isl_pw_aff_n_piece(__isl_keep isl_pw_aff *pwaff);
 isl_stat isl_pw_aff_foreach_piece(__isl_keep isl_pw_aff *pwaff,
 	isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_aff *aff,
 		    void *user), void *user);
+__isl_export
+isl_bool isl_pw_aff_isa_aff(__isl_keep isl_pw_aff *pa);
+__isl_export
+__isl_give isl_aff *isl_pw_aff_as_aff(__isl_take isl_pw_aff *pa);
 
 __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);
@@ -379,11 +418,25 @@ __isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
 
 __isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2);
+__isl_give isl_map *isl_pw_aff_le_map(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2);
 __isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2);
+__isl_give isl_map *isl_pw_aff_ge_map(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2);
 __isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2);
 
+__isl_export
+__isl_give isl_pw_aff *isl_pw_aff_bind_domain(__isl_take isl_pw_aff *pa,
+	__isl_take isl_multi_id *tuple);
+__isl_export
+__isl_give isl_pw_aff *isl_pw_aff_bind_domain_wrapped_domain(
+	__isl_take isl_pw_aff *pa, __isl_take isl_multi_id *tuple);
+__isl_overload
+__isl_give isl_set *isl_pw_aff_bind_id(__isl_take isl_pw_aff *pa,
+	__isl_take isl_id *id);
+
 __isl_constructor
 __isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str);
 __isl_give char *isl_pw_aff_to_str(__isl_keep isl_pw_aff *pa);
@@ -408,15 +461,24 @@ __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_DECLARE_MULTI_IDENTITY(aff)
 ISL_DECLARE_MULTI_CMP(aff)
-ISL_DECLARE_MULTI_NEG(aff)
+ISL_DECLARE_MULTI_ARITH(aff)
+ISL_DECLARE_MULTI_ADD_CONSTANT(aff)
+ISL_DECLARE_MULTI_ZERO(aff)
+ISL_DECLARE_MULTI_NAN(aff)
 ISL_DECLARE_MULTI_DIMS(aff)
+ISL_DECLARE_MULTI_LOCALS(aff)
+ISL_DECLARE_MULTI_DIM_ID(aff)
+ISL_DECLARE_MULTI_TUPLE_ID(aff)
 ISL_DECLARE_MULTI_WITH_DOMAIN(aff)
+ISL_DECLARE_MULTI_BIND_DOMAIN(aff)
 
 __isl_constructor
 __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_export
 __isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space);
+__isl_export
 __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,
@@ -425,10 +487,16 @@ __isl_give isl_multi_aff *isl_multi_aff_project_out_map(
 __isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
 	__isl_take isl_space *space, __isl_take isl_multi_val *mv);
 
+__isl_export
+__isl_give isl_multi_val *isl_multi_aff_get_constant_multi_val(
+	__isl_keep isl_multi_aff *ma);
+
+__isl_export
 __isl_give isl_multi_aff *isl_multi_aff_floor(__isl_take isl_multi_aff *ma);
 
 __isl_give isl_multi_aff *isl_multi_aff_gist_params(
 	__isl_take isl_multi_aff *maff, __isl_take isl_set *context);
+__isl_export
 __isl_give isl_multi_aff *isl_multi_aff_gist(__isl_take isl_multi_aff *maff,
 	__isl_take isl_set *context);
 
@@ -452,6 +520,10 @@ __isl_give isl_set *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1,
 __isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
 	__isl_take isl_multi_aff *ma2);
 
+__isl_export
+__isl_give isl_basic_set *isl_multi_aff_bind(__isl_take isl_multi_aff *ma,
+	__isl_take isl_multi_id *tuple);
+
 __isl_give char *isl_multi_aff_to_str(__isl_keep isl_multi_aff *ma);
 __isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,
 	__isl_keep isl_multi_aff *maff);
@@ -462,10 +534,19 @@ __isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
 void isl_multi_aff_dump(__isl_keep isl_multi_aff *maff);
 
 ISL_DECLARE_MULTI(pw_aff)
-ISL_DECLARE_MULTI_NEG(pw_aff)
+ISL_DECLARE_MULTI_IDENTITY(pw_aff)
+ISL_DECLARE_MULTI_ARITH(pw_aff)
+ISL_DECLARE_MULTI_ADD_CONSTANT(pw_aff)
+ISL_DECLARE_MULTI_ZERO(pw_aff)
+ISL_DECLARE_MULTI_NAN(pw_aff)
 ISL_DECLARE_MULTI_DIMS(pw_aff)
+ISL_DECLARE_MULTI_DIM_ID(pw_aff)
+ISL_DECLARE_MULTI_TUPLE_ID(pw_aff)
 ISL_DECLARE_MULTI_WITH_DOMAIN(pw_aff)
+ISL_DECLARE_MULTI_BIND_DOMAIN(pw_aff)
+ISL_DECLARE_MULTI_PARAM(pw_aff)
 
+__isl_export
 __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);
@@ -487,8 +568,10 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_copy(
 __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,
+isl_size isl_pw_multi_aff_dim(__isl_keep isl_pw_multi_aff *pma,
 	enum isl_dim_type type);
+isl_bool isl_pw_multi_aff_involves_param_id(__isl_keep isl_pw_multi_aff *pma,
+	__isl_keep isl_id *id);
 isl_bool isl_pw_multi_aff_involves_dims(__isl_keep isl_pw_multi_aff *pma,
 	enum isl_dim_type type, unsigned first, unsigned n);
 __isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
@@ -500,6 +583,7 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
 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_export
 __isl_give isl_space *isl_pw_multi_aff_get_space(
 	__isl_keep isl_pw_multi_aff *pma);
 isl_bool isl_pw_multi_aff_has_tuple_name(__isl_keep isl_pw_multi_aff *pma,
@@ -525,6 +609,7 @@ __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_export
 __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);
@@ -563,11 +648,20 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_neg(
 __isl_export
 __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_export
 __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_overload
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add_constant_val(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_val *v);
+__isl_overload
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add_constant_multi_val(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv);
+__isl_overload
 __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_overload
 __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(
@@ -592,11 +686,24 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
 __isl_export
 __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_export
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_domain(
+	__isl_take isl_pw_multi_aff *pma);
+__isl_export
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_range(
+	__isl_take isl_pw_multi_aff *pma);
 
+__isl_export
 __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_export
 __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_intersect_domain_wrapped_domain(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_domain_wrapped_range(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+__isl_export
 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_subtract_domain(
 	__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
 
@@ -608,10 +715,12 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_align_params(
 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_drop_unused_params(
 	__isl_take isl_pw_multi_aff *pma);
 
+__isl_export
 __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_export
 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist(
 	__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
 
@@ -622,10 +731,17 @@ __isl_overload
 __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_n_piece(__isl_keep isl_pw_multi_aff *pma);
+__isl_export
+isl_size isl_pw_multi_aff_n_piece(__isl_keep isl_pw_multi_aff *pma);
+__isl_export
 isl_stat isl_pw_multi_aff_foreach_piece(__isl_keep isl_pw_multi_aff *pma,
 	isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_multi_aff *maff,
 		    void *user), void *user);
+__isl_export
+isl_bool isl_pw_multi_aff_isa_multi_aff(__isl_keep isl_pw_multi_aff *pma);
+__isl_export
+__isl_give isl_multi_aff *isl_pw_multi_aff_as_multi_aff(
+	__isl_take isl_pw_multi_aff *pma);
 
 __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);
@@ -637,12 +753,24 @@ __isl_give isl_printer *isl_printer_print_pw_multi_aff(__isl_take isl_printer *p
 __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_export
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_bind_domain(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_id *tuple);
+__isl_export
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_bind_domain_wrapped_domain(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_id *tuple);
+
 __isl_constructor
 __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_overload
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_empty_ctx(
+	isl_ctx *ctx);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_empty_space(
+	__isl_take isl_space *space);
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_empty(
 	__isl_take isl_space *space);
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff(
@@ -673,12 +801,13 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_add_pw_multi_aff(
 
 isl_ctx *isl_union_pw_multi_aff_get_ctx(
 	__isl_keep isl_union_pw_multi_aff *upma);
+__isl_export
 __isl_give isl_space *isl_union_pw_multi_aff_get_space(
 	__isl_keep isl_union_pw_multi_aff *upma);
 __isl_give isl_pw_multi_aff_list *isl_union_pw_multi_aff_get_pw_multi_aff_list(
 	__isl_keep isl_union_pw_multi_aff *upma);
 
-unsigned isl_union_pw_multi_aff_dim(__isl_keep isl_union_pw_multi_aff *upma,
+isl_size isl_union_pw_multi_aff_dim(__isl_keep isl_union_pw_multi_aff *upma,
 	enum isl_dim_type type);
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_set_dim_name(
 	__isl_take isl_union_pw_multi_aff *upma,
@@ -694,10 +823,12 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_drop_dims(
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_reset_user(
 	__isl_take isl_union_pw_multi_aff *upma);
 
+__isl_export
 __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_export
 __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);
@@ -711,15 +842,22 @@ isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_align_params(
 	__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *model);
 
-int isl_union_pw_multi_aff_n_pw_multi_aff(
+isl_size isl_union_pw_multi_aff_n_pw_multi_aff(
 	__isl_keep isl_union_pw_multi_aff *upma);
 
 isl_stat isl_union_pw_multi_aff_foreach_pw_multi_aff(
 	__isl_keep isl_union_pw_multi_aff *upma,
 	isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user),
 	void *user);
+__isl_export
 __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);
+__isl_export
+isl_bool isl_union_pw_multi_aff_isa_pw_multi_aff(
+	__isl_keep isl_union_pw_multi_aff *upma);
+__isl_export
+__isl_give isl_pw_multi_aff *isl_union_pw_multi_aff_as_pw_multi_aff(
+	__isl_take isl_union_pw_multi_aff *upma);
 
 isl_bool isl_union_pw_multi_aff_involves_nan(
 	__isl_keep isl_union_pw_multi_aff *upma);
@@ -727,6 +865,7 @@ isl_bool 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_export
 __isl_give isl_union_set *isl_union_pw_multi_aff_domain(
 	__isl_take isl_union_pw_multi_aff *upma);
 
@@ -741,6 +880,7 @@ __isl_export
 __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_export
 __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);
@@ -756,12 +896,31 @@ __isl_export
 __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_export
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_range_factor_domain(
+	__isl_take isl_union_pw_multi_aff *upma);
+__isl_export
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_range_factor_range(
+	__isl_take isl_union_pw_multi_aff *upma);
 
+__isl_export
 __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_export
 __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_export
+__isl_give isl_union_pw_multi_aff *
+isl_union_pw_multi_aff_intersect_domain_wrapped_domain(
+	__isl_take isl_union_pw_multi_aff *upma,
+	__isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_pw_multi_aff *
+isl_union_pw_multi_aff_intersect_domain_wrapped_range(
+	__isl_take isl_union_pw_multi_aff *upma,
+	__isl_take isl_union_set *uset);
+__isl_export
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_subtract_domain(
 	__isl_take isl_union_pw_multi_aff *upma,
 	__isl_take isl_union_set *uset);
@@ -787,22 +946,25 @@ __isl_give char *isl_union_pw_multi_aff_to_str(
 
 uint32_t isl_multi_pw_aff_get_hash(__isl_keep isl_multi_pw_aff *mpa);
 
-__isl_give isl_multi_pw_aff *isl_multi_pw_aff_identity(
-	__isl_take isl_space *space);
 __isl_constructor
 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
 	__isl_take isl_multi_aff *ma);
 __isl_constructor
 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_aff(
 	__isl_take isl_pw_aff *pa);
+__isl_export
 __isl_give isl_set *isl_multi_pw_aff_domain(__isl_take isl_multi_pw_aff *mpa);
+__isl_export
 __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_export
 __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_export
 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
 	__isl_take isl_multi_pw_aff *mpa);
+__isl_export
 __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(
@@ -842,6 +1004,10 @@ __isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
 __isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
 	__isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2);
 
+__isl_export
+__isl_give isl_set *isl_multi_pw_aff_bind(__isl_take isl_multi_pw_aff *mpa,
+	__isl_take isl_multi_id *tuple);
+
 __isl_constructor
 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
 	const char *str);
@@ -856,12 +1022,13 @@ __isl_null isl_union_pw_aff *isl_union_pw_aff_free(
 	__isl_take isl_union_pw_aff *upa);
 
 isl_ctx *isl_union_pw_aff_get_ctx(__isl_keep isl_union_pw_aff *upa);
+__isl_export
 __isl_give isl_space *isl_union_pw_aff_get_space(
 	__isl_keep isl_union_pw_aff *upa);
 __isl_give isl_pw_aff_list *isl_union_pw_aff_get_pw_aff_list(
 	__isl_keep isl_union_pw_aff *upa);
 
-unsigned isl_union_pw_aff_dim(__isl_keep isl_union_pw_aff *upa,
+isl_size isl_union_pw_aff_dim(__isl_keep isl_union_pw_aff *upa,
 	enum isl_dim_type type);
 __isl_give isl_union_pw_aff *isl_union_pw_aff_set_dim_name(
 	__isl_take isl_union_pw_aff *upa, enum isl_dim_type type,
@@ -876,6 +1043,9 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_drop_dims(
 __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_user(
 	__isl_take isl_union_pw_aff *upa);
 
+__isl_give isl_union_pw_aff *isl_union_pw_aff_empty_ctx(isl_ctx *ctx);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_empty_space(
+	__isl_take isl_space *space);
 __isl_give isl_union_pw_aff *isl_union_pw_aff_empty(
 	__isl_take isl_space *space);
 __isl_constructor
@@ -894,7 +1064,7 @@ __isl_constructor
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff(
 	__isl_take isl_union_pw_aff *upa);
 
-int isl_union_pw_aff_n_pw_aff(__isl_keep isl_union_pw_aff *upa);
+isl_size isl_union_pw_aff_n_pw_aff(__isl_keep isl_union_pw_aff *upa);
 
 isl_stat isl_union_pw_aff_foreach_pw_aff(__isl_keep isl_union_pw_aff *upa,
 	isl_stat (*fn)(__isl_take isl_pw_aff *pa, void *user), void *user);
@@ -905,6 +1075,7 @@ isl_bool isl_union_pw_aff_involves_nan(__isl_keep isl_union_pw_aff *upa);
 isl_bool isl_union_pw_aff_plain_is_equal(__isl_keep isl_union_pw_aff *upa1,
 	__isl_keep isl_union_pw_aff *upa2);
 
+__isl_export
 __isl_give isl_union_set *isl_union_pw_aff_domain(
 	__isl_take isl_union_pw_aff *upa);
 
@@ -917,11 +1088,14 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_add(
 __isl_export
 __isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
 	__isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2);
+__isl_export
 __isl_give isl_union_pw_aff *isl_union_pw_aff_sub(
 	__isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2);
 
+__isl_export
 __isl_give isl_union_pw_aff *isl_union_pw_aff_coalesce(
 	__isl_take isl_union_pw_aff *upa);
+__isl_export
 __isl_give isl_union_pw_aff *isl_union_pw_aff_gist(
 	__isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *context);
 __isl_give isl_union_pw_aff *isl_union_pw_aff_gist_params(
@@ -945,10 +1119,19 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val(
 __isl_give isl_union_pw_aff *isl_union_pw_aff_align_params(
 	__isl_take isl_union_pw_aff *upa, __isl_take isl_space *model);
 
+__isl_export
 __isl_give isl_union_pw_aff *isl_union_pw_aff_intersect_params(
 	__isl_take isl_union_pw_aff *upa, __isl_take isl_set *set);
+__isl_export
 __isl_give isl_union_pw_aff *isl_union_pw_aff_intersect_domain(
 	__isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_pw_aff *isl_union_pw_aff_intersect_domain_wrapped_domain(
+	__isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_pw_aff *isl_union_pw_aff_intersect_domain_wrapped_range(
+	__isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *uset);
+__isl_export
 __isl_give isl_union_pw_aff *isl_union_pw_aff_subtract_domain(
 	__isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *uset);
 
@@ -962,6 +1145,10 @@ __isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
 __isl_give isl_union_map *isl_union_map_from_union_pw_aff(
 	__isl_take isl_union_pw_aff *upa);
 
+__isl_overload
+__isl_give isl_union_set *isl_union_pw_aff_bind_id(
+	__isl_take isl_union_pw_aff *upa, __isl_take isl_id *id);
+
 __isl_constructor
 __isl_give isl_union_pw_aff *isl_union_pw_aff_read_from_str(isl_ctx *ctx,
 	const char *str);
@@ -971,7 +1158,12 @@ __isl_give isl_printer *isl_printer_print_union_pw_aff(
 void isl_union_pw_aff_dump(__isl_keep isl_union_pw_aff *upa);
 
 ISL_DECLARE_MULTI(union_pw_aff)
-ISL_DECLARE_MULTI_NEG(union_pw_aff)
+ISL_DECLARE_MULTI_ARITH(union_pw_aff)
+ISL_DECLARE_MULTI_ZERO(union_pw_aff)
+ISL_DECLARE_MULTI_NAN(union_pw_aff)
+ISL_DECLARE_MULTI_DROP_DIMS(union_pw_aff)
+ISL_DECLARE_MULTI_DIM_ID(union_pw_aff)
+ISL_DECLARE_MULTI_TUPLE_ID(union_pw_aff)
 
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
 	__isl_take isl_multi_aff *ma);
@@ -992,24 +1184,29 @@ isl_multi_union_pw_aff_pw_multi_aff_on_domain(__isl_take isl_union_set *domain,
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_floor(
 	__isl_take isl_multi_union_pw_aff *mupa);
 
+__isl_export
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_domain(
 	__isl_take isl_multi_union_pw_aff *mupa,
 	__isl_take isl_union_set *uset);
+__isl_export
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_params(
 	__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *params);
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
 	__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *set);
 
+__isl_export
 __isl_give isl_union_set *isl_multi_union_pw_aff_domain(
 	__isl_take isl_multi_union_pw_aff *mupa);
 
+__isl_export
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_coalesce(
-	__isl_take isl_multi_union_pw_aff *aff);
+	__isl_take isl_multi_union_pw_aff *mupa);
+__isl_export
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_gist(
-	__isl_take isl_multi_union_pw_aff *aff,
+	__isl_take isl_multi_union_pw_aff *mupa,
 	__isl_take isl_union_set *context);
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_gist_params(
-	__isl_take isl_multi_union_pw_aff *aff, __isl_take isl_set *context);
+	__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *context);
 
 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
 	__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff);
@@ -1048,6 +1245,10 @@ __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
 
 __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
 	__isl_take isl_multi_union_pw_aff *mupa);
+__isl_export
+__isl_give isl_union_set *isl_multi_union_pw_aff_bind(
+	__isl_take isl_multi_union_pw_aff *mupa,
+	__isl_take isl_multi_id *tuple);
 
 __isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
 	__isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space);
@@ -1061,8 +1262,10 @@ __isl_give isl_printer *isl_printer_print_multi_union_pw_aff(
 	__isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa);
 void isl_multi_union_pw_aff_dump(__isl_keep isl_multi_union_pw_aff *mupa);
 
-ISL_DECLARE_LIST_FN(pw_multi_aff)
-ISL_DECLARE_LIST_FN(union_pw_aff)
+ISL_DECLARE_EXPORTED_LIST_FN(aff)
+ISL_DECLARE_EXPORTED_LIST_FN(pw_aff)
+ISL_DECLARE_EXPORTED_LIST_FN(pw_multi_aff)
+ISL_DECLARE_EXPORTED_LIST_FN(union_pw_aff)
 ISL_DECLARE_LIST_FN(union_pw_multi_aff)
 
 #if defined(__cplusplus)

diff  --git a/polly/lib/External/isl/include/isl/aff_type.h b/polly/lib/External/isl/include/isl/aff_type.h
index 7a4fd9ad4e30..271f978b8ce2 100644
--- a/polly/lib/External/isl/include/isl/aff_type.h
+++ b/polly/lib/External/isl/include/isl/aff_type.h
@@ -10,19 +10,19 @@ extern "C" {
 struct __isl_subclass(isl_multi_aff) __isl_subclass(isl_pw_aff) isl_aff;
 typedef struct isl_aff isl_aff;
 
-ISL_DECLARE_LIST(aff)
+ISL_DECLARE_EXPORTED_LIST_TYPE(aff)
 
 struct __isl_subclass(isl_multi_pw_aff) __isl_subclass(isl_pw_multi_aff)
 	__isl_subclass(isl_union_pw_aff) isl_pw_aff;
 typedef struct isl_pw_aff isl_pw_aff;
 
-ISL_DECLARE_LIST(pw_aff)
+ISL_DECLARE_EXPORTED_LIST_TYPE(pw_aff)
 
 struct __isl_subclass(isl_multi_union_pw_aff)
 	__isl_subclass(isl_union_pw_multi_aff) isl_union_pw_aff;
 typedef struct isl_union_pw_aff isl_union_pw_aff;
 
-ISL_DECLARE_LIST_TYPE(union_pw_aff)
+ISL_DECLARE_EXPORTED_LIST_TYPE(union_pw_aff)
 
 struct __isl_subclass(isl_multi_pw_aff) __isl_subclass(isl_pw_multi_aff)
 	isl_multi_aff;
@@ -32,7 +32,7 @@ struct __isl_subclass(isl_multi_pw_aff) __isl_subclass(isl_union_pw_multi_aff)
 	isl_pw_multi_aff;
 typedef struct isl_pw_multi_aff isl_pw_multi_aff;
 
-ISL_DECLARE_LIST_TYPE(pw_multi_aff)
+ISL_DECLARE_EXPORTED_LIST_TYPE(pw_multi_aff)
 
 struct __isl_export isl_union_pw_multi_aff;
 typedef struct isl_union_pw_multi_aff isl_union_pw_multi_aff;

diff  --git a/polly/lib/External/isl/include/isl/arg.h b/polly/lib/External/isl/include/isl/arg.h
index 66c560ca1f61..edbd81e12dd0 100644
--- a/polly/lib/External/isl/include/isl/arg.h
+++ b/polly/lib/External/isl/include/isl/arg.h
@@ -53,6 +53,7 @@ struct isl_arg {
 	char			 short_name;
 	const char		*long_name;
 	const char		*argument_name;
+#define ISL_ARG_OFFSET_NONE	((size_t) -1)
 	size_t			 offset;
 	const char		*help_msg;
 #define ISL_ARG_SINGLE_DASH	(1 << 0)
@@ -152,7 +153,7 @@ struct isl_args {
 	.type = isl_arg_choice,						\
 	.short_name = s,						\
 	.long_name = l,							\
-	.offset = -1,							\
+	.offset = ISL_ARG_OFFSET_NONE,					\
 	.help_msg = h,							\
 	.flags = fl,							\
 	.u = { .choice = { .choice = c, .default_value = d,		\
@@ -181,7 +182,7 @@ struct isl_args {
 #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)
+	_ISL_ARG_BOOL_F(ISL_ARG_OFFSET_NONE,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)	{			\
@@ -263,7 +264,7 @@ struct isl_args {
 #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)
+	_ISL_ARG_CHILD(ISL_ARG_OFFSET_NONE,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)	{				\

diff  --git a/polly/lib/External/isl/include/isl/ast.h b/polly/lib/External/isl/include/isl/ast.h
index 96511ff82673..56b8e3297658 100644
--- a/polly/lib/External/isl/include/isl/ast.h
+++ b/polly/lib/External/isl/include/isl/ast.h
@@ -62,12 +62,26 @@ __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);
+__isl_subclass(isl_ast_expr)
 enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr);
+__isl_export
+__isl_give isl_val *isl_ast_expr_int_get_val(__isl_keep isl_ast_expr *expr);
 __isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr);
+__isl_export
+__isl_give isl_id *isl_ast_expr_id_get_id(__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_subclass(isl_ast_expr_op)
+enum isl_ast_expr_op_type isl_ast_expr_op_get_type(
+	__isl_keep isl_ast_expr *expr);
+enum isl_ast_expr_op_type isl_ast_expr_get_op_type(
+	__isl_keep isl_ast_expr *expr);
+__isl_export
+isl_size isl_ast_expr_op_get_n_arg(__isl_keep isl_ast_expr *expr);
+isl_size isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+__isl_export
+__isl_give isl_ast_expr *isl_ast_expr_op_get_arg(__isl_keep isl_ast_expr *expr,
+	int pos);
 __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,
@@ -91,39 +105,59 @@ __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);
+__isl_subclass(isl_ast_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_export
 __isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
 	__isl_keep isl_ast_node *node);
+__isl_export
 __isl_give isl_ast_expr *isl_ast_node_for_get_init(
 	__isl_keep isl_ast_node *node);
+__isl_export
 __isl_give isl_ast_expr *isl_ast_node_for_get_cond(
 	__isl_keep isl_ast_node *node);
+__isl_export
 __isl_give isl_ast_expr *isl_ast_node_for_get_inc(
 	__isl_keep isl_ast_node *node);
+__isl_export
 __isl_give isl_ast_node *isl_ast_node_for_get_body(
 	__isl_keep isl_ast_node *node);
+__isl_export
 isl_bool isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node);
 
+__isl_export
 __isl_give isl_ast_expr *isl_ast_node_if_get_cond(
 	__isl_keep isl_ast_node *node);
+__isl_export
+__isl_give isl_ast_node *isl_ast_node_if_get_then_node(
+	__isl_keep isl_ast_node *node);
 __isl_give isl_ast_node *isl_ast_node_if_get_then(
 	__isl_keep isl_ast_node *node);
+__isl_export
+isl_bool isl_ast_node_if_has_else_node(__isl_keep isl_ast_node *node);
 isl_bool isl_ast_node_if_has_else(__isl_keep isl_ast_node *node);
+__isl_export
+__isl_give isl_ast_node *isl_ast_node_if_get_else_node(
+	__isl_keep isl_ast_node *node);
 __isl_give isl_ast_node *isl_ast_node_if_get_else(
 	__isl_keep isl_ast_node *node);
 
+__isl_export
 __isl_give isl_ast_node_list *isl_ast_node_block_get_children(
 	__isl_keep isl_ast_node *node);
 
+__isl_export
 __isl_give isl_id *isl_ast_node_mark_get_id(__isl_keep isl_ast_node *node);
+__isl_export
 __isl_give isl_ast_node *isl_ast_node_mark_get_node(
 	__isl_keep isl_ast_node *node);
 
+__isl_export
 __isl_give isl_ast_expr *isl_ast_node_user_get_expr(
 	__isl_keep isl_ast_node *node);
 
@@ -160,15 +194,24 @@ __isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
 isl_stat isl_options_set_ast_print_macro_once(isl_ctx *ctx, int val);
 int isl_options_get_ast_print_macro_once(isl_ctx *ctx);
 
+isl_stat isl_ast_expr_foreach_ast_expr_op_type(__isl_keep isl_ast_expr *expr,
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user);
 isl_stat isl_ast_expr_foreach_ast_op_type(__isl_keep isl_ast_expr *expr,
-	isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user);
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user);
+isl_stat isl_ast_node_foreach_ast_expr_op_type(__isl_keep isl_ast_node *node,
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user);
 isl_stat isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
-	isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user);
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user);
+__isl_give isl_printer *isl_ast_expr_op_type_set_print_name(
+	__isl_take isl_printer *p, enum isl_ast_expr_op_type type,
+	__isl_keep const char *name);
 __isl_give isl_printer *isl_ast_op_type_set_print_name(
-	__isl_take isl_printer *p, enum isl_ast_op_type type,
+	__isl_take isl_printer *p, enum isl_ast_expr_op_type type,
 	__isl_keep const char *name);
+__isl_give isl_printer *isl_ast_expr_op_type_print_macro(
+	enum isl_ast_expr_op_type type, __isl_take isl_printer *p);
 __isl_give isl_printer *isl_ast_op_type_print_macro(
-	enum isl_ast_op_type type, __isl_take isl_printer *p);
+	enum isl_ast_expr_op_type type, __isl_take isl_printer *p);
 __isl_give isl_printer *isl_ast_expr_print_macros(
 	__isl_keep isl_ast_expr *expr, __isl_take isl_printer *p);
 __isl_give isl_printer *isl_ast_node_print_macros(
@@ -186,6 +229,9 @@ __isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
 __isl_export
 __isl_give char *isl_ast_node_to_C_str(__isl_keep isl_ast_node *node);
 
+ISL_DECLARE_LIST_FN(ast_expr)
+ISL_DECLARE_EXPORTED_LIST_FN(ast_node)
+
 #if defined(__cplusplus)
 }
 #endif

diff  --git a/polly/lib/External/isl/include/isl/ast_build.h b/polly/lib/External/isl/include/isl/ast_build.h
index bf08e03cbe0f..0029cd5bec7b 100644
--- a/polly/lib/External/isl/include/isl/ast_build.h
+++ b/polly/lib/External/isl/include/isl/ast_build.h
@@ -1,5 +1,5 @@
-#ifndef ISL_AST_CONTEXT_H
-#define ISL_AST_CONTEXT_H
+#ifndef ISL_AST_BUILD_H
+#define ISL_AST_BUILD_H
 
 #include <isl/ctx.h>
 #include <isl/set.h>
@@ -52,6 +52,7 @@ __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_export
 __isl_give isl_union_map *isl_ast_build_get_schedule(
 	__isl_keep isl_ast_build *build);
 
@@ -69,6 +70,7 @@ __isl_give isl_ast_build *isl_ast_build_set_options(
 __isl_give isl_ast_build *isl_ast_build_set_iterators(
 	__isl_take isl_ast_build *build,
 	__isl_take isl_id_list *iterators);
+__isl_export
 __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,
@@ -113,6 +115,7 @@ __isl_overload
 __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_overload
 __isl_give isl_ast_node *isl_ast_build_node_from_schedule(
 	__isl_keep isl_ast_build *build, __isl_take isl_schedule *schedule);
 __isl_export

diff  --git a/polly/lib/External/isl/include/isl/ast_type.h b/polly/lib/External/isl/include/isl/ast_type.h
index 1e09b3b5536e..2877b8f85510 100644
--- a/polly/lib/External/isl/include/isl/ast_type.h
+++ b/polly/lib/External/isl/include/isl/ast_type.h
@@ -13,36 +13,65 @@ typedef struct isl_ast_expr isl_ast_expr;
 struct __isl_export 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_op_type {
+	isl_ast_expr_op_error = -1,
+	isl_ast_expr_op_and,
+	isl_ast_expr_op_and_then,
+	isl_ast_expr_op_or,
+	isl_ast_expr_op_or_else,
+	isl_ast_expr_op_max,
+	isl_ast_expr_op_min,
+	isl_ast_expr_op_minus,
+	isl_ast_expr_op_add,
+	isl_ast_expr_op_sub,
+	isl_ast_expr_op_mul,
+	isl_ast_expr_op_div,
+	isl_ast_expr_op_fdiv_q,	/* Round towards -infty */
+	isl_ast_expr_op_pdiv_q,	/* Dividend is non-negative */
+	isl_ast_expr_op_pdiv_r,	/* Dividend is non-negative */
+	isl_ast_expr_op_zdiv_r,	/* Result only compared against zero */
+	isl_ast_expr_op_cond,
+	isl_ast_expr_op_select,
+	isl_ast_expr_op_eq,
+	isl_ast_expr_op_le,
+	isl_ast_expr_op_lt,
+	isl_ast_expr_op_ge,
+	isl_ast_expr_op_gt,
+	isl_ast_expr_op_call,
+	isl_ast_expr_op_access,
+	isl_ast_expr_op_member,
+	isl_ast_expr_op_address_of
 };
 
+#define isl_ast_op_type		isl_ast_expr_op_type
+#define isl_ast_op_error	isl_ast_expr_op_error
+#define isl_ast_op_and		isl_ast_expr_op_and
+#define isl_ast_op_and_then	isl_ast_expr_op_and_then
+#define isl_ast_op_or		isl_ast_expr_op_or
+#define isl_ast_op_or_else	isl_ast_expr_op_or_else
+#define isl_ast_op_max		isl_ast_expr_op_max
+#define isl_ast_op_min		isl_ast_expr_op_min
+#define isl_ast_op_minus	isl_ast_expr_op_minus
+#define isl_ast_op_add		isl_ast_expr_op_add
+#define isl_ast_op_sub		isl_ast_expr_op_sub
+#define isl_ast_op_mul		isl_ast_expr_op_mul
+#define isl_ast_op_div		isl_ast_expr_op_div
+#define isl_ast_op_fdiv_q	isl_ast_expr_op_fdiv_q
+#define isl_ast_op_pdiv_q	isl_ast_expr_op_pdiv_q
+#define isl_ast_op_pdiv_r	isl_ast_expr_op_pdiv_r
+#define isl_ast_op_zdiv_r	isl_ast_expr_op_zdiv_r
+#define isl_ast_op_cond		isl_ast_expr_op_cond
+#define isl_ast_op_select	isl_ast_expr_op_select
+#define isl_ast_op_eq		isl_ast_expr_op_eq
+#define isl_ast_op_le		isl_ast_expr_op_le
+#define isl_ast_op_lt		isl_ast_expr_op_lt
+#define isl_ast_op_ge		isl_ast_expr_op_ge
+#define isl_ast_op_gt		isl_ast_expr_op_gt
+#define isl_ast_op_call		isl_ast_expr_op_call
+#define isl_ast_op_access	isl_ast_expr_op_access
+#define isl_ast_op_member	isl_ast_expr_op_member
+#define isl_ast_op_address_of	isl_ast_expr_op_address_of
+
 enum isl_ast_expr_type {
 	isl_ast_expr_error = -1,
 	isl_ast_expr_op,
@@ -70,8 +99,8 @@ enum isl_ast_loop_type {
 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)
+ISL_DECLARE_LIST_TYPE(ast_expr)
+ISL_DECLARE_EXPORTED_LIST_TYPE(ast_node)
 
 #if defined(__cplusplus)
 }

diff  --git a/polly/lib/External/isl/include/isl/constraint.h b/polly/lib/External/isl/include/isl/constraint.h
index adb0d863b914..672824502ad8 100644
--- a/polly/lib/External/isl/include/isl/constraint.h
+++ b/polly/lib/External/isl/include/isl/constraint.h
@@ -39,8 +39,8 @@ __isl_give isl_constraint *isl_inequality_alloc(__isl_take isl_local_space *ls);
 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);
+isl_size isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap);
+isl_size isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset);
 isl_stat isl_basic_map_foreach_constraint(__isl_keep isl_basic_map *bmap,
 	isl_stat (*fn)(__isl_take isl_constraint *c, void *user), void *user);
 isl_stat isl_basic_set_foreach_constraint(__isl_keep isl_basic_set *bset,
@@ -82,7 +82,7 @@ __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,
+isl_size isl_constraint_dim(__isl_keep isl_constraint *constraint,
 	enum isl_dim_type type);
 
 isl_bool isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
@@ -111,7 +111,8 @@ __isl_give isl_aff *isl_constraint_get_div(__isl_keep isl_constraint *constraint
 struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint);
 
 isl_bool isl_constraint_is_equality(__isl_keep isl_constraint *constraint);
-int isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint);
+isl_bool isl_constraint_is_div_constraint(
+	__isl_keep isl_constraint *constraint);
 
 isl_bool isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint,
 	enum isl_dim_type type, unsigned pos);

diff  --git a/polly/lib/External/isl/include/isl/cpp-checked-conversion.h b/polly/lib/External/isl/include/isl/cpp-checked-conversion.h
index 848d52d3c07b..20e422ea8084 100644
--- a/polly/lib/External/isl/include/isl/cpp-checked-conversion.h
+++ b/polly/lib/External/isl/include/isl/cpp-checked-conversion.h
@@ -22,6 +22,14 @@ aff uncheck(checked::aff obj) {
 	return manage(obj.copy());
 }
 
+checked::aff_list check(aff_list obj) {
+	return checked::manage(obj.copy());
+}
+
+aff_list uncheck(checked::aff_list obj) {
+	return manage(obj.copy());
+}
+
 checked::ast_build check(ast_build obj) {
 	return checked::manage(obj.copy());
 }
@@ -38,6 +46,238 @@ ast_expr uncheck(checked::ast_expr obj) {
 	return manage(obj.copy());
 }
 
+checked::ast_expr_id check(ast_expr_id obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_id>();
+}
+
+ast_expr_id uncheck(checked::ast_expr_id obj) {
+	return manage(obj.copy()).as<ast_expr_id>();
+}
+
+checked::ast_expr_int check(ast_expr_int obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_int>();
+}
+
+ast_expr_int uncheck(checked::ast_expr_int obj) {
+	return manage(obj.copy()).as<ast_expr_int>();
+}
+
+checked::ast_expr_op check(ast_expr_op obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>();
+}
+
+ast_expr_op uncheck(checked::ast_expr_op obj) {
+	return manage(obj.copy()).as<ast_expr_op>();
+}
+
+checked::ast_expr_op_access check(ast_expr_op_access obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_access>();
+}
+
+ast_expr_op_access uncheck(checked::ast_expr_op_access obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_access>();
+}
+
+checked::ast_expr_op_add check(ast_expr_op_add obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_add>();
+}
+
+ast_expr_op_add uncheck(checked::ast_expr_op_add obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_add>();
+}
+
+checked::ast_expr_op_address_of check(ast_expr_op_address_of obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_address_of>();
+}
+
+ast_expr_op_address_of uncheck(checked::ast_expr_op_address_of obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_address_of>();
+}
+
+checked::ast_expr_op_and check(ast_expr_op_and obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_and>();
+}
+
+ast_expr_op_and uncheck(checked::ast_expr_op_and obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_and>();
+}
+
+checked::ast_expr_op_and_then check(ast_expr_op_and_then obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_and_then>();
+}
+
+ast_expr_op_and_then uncheck(checked::ast_expr_op_and_then obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_and_then>();
+}
+
+checked::ast_expr_op_call check(ast_expr_op_call obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_call>();
+}
+
+ast_expr_op_call uncheck(checked::ast_expr_op_call obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_call>();
+}
+
+checked::ast_expr_op_cond check(ast_expr_op_cond obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_cond>();
+}
+
+ast_expr_op_cond uncheck(checked::ast_expr_op_cond obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_cond>();
+}
+
+checked::ast_expr_op_div check(ast_expr_op_div obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_div>();
+}
+
+ast_expr_op_div uncheck(checked::ast_expr_op_div obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_div>();
+}
+
+checked::ast_expr_op_eq check(ast_expr_op_eq obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_eq>();
+}
+
+ast_expr_op_eq uncheck(checked::ast_expr_op_eq obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_eq>();
+}
+
+checked::ast_expr_op_fdiv_q check(ast_expr_op_fdiv_q obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_fdiv_q>();
+}
+
+ast_expr_op_fdiv_q uncheck(checked::ast_expr_op_fdiv_q obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_fdiv_q>();
+}
+
+checked::ast_expr_op_ge check(ast_expr_op_ge obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_ge>();
+}
+
+ast_expr_op_ge uncheck(checked::ast_expr_op_ge obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_ge>();
+}
+
+checked::ast_expr_op_gt check(ast_expr_op_gt obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_gt>();
+}
+
+ast_expr_op_gt uncheck(checked::ast_expr_op_gt obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_gt>();
+}
+
+checked::ast_expr_op_le check(ast_expr_op_le obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_le>();
+}
+
+ast_expr_op_le uncheck(checked::ast_expr_op_le obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_le>();
+}
+
+checked::ast_expr_op_lt check(ast_expr_op_lt obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_lt>();
+}
+
+ast_expr_op_lt uncheck(checked::ast_expr_op_lt obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_lt>();
+}
+
+checked::ast_expr_op_max check(ast_expr_op_max obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_max>();
+}
+
+ast_expr_op_max uncheck(checked::ast_expr_op_max obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_max>();
+}
+
+checked::ast_expr_op_member check(ast_expr_op_member obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_member>();
+}
+
+ast_expr_op_member uncheck(checked::ast_expr_op_member obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_member>();
+}
+
+checked::ast_expr_op_min check(ast_expr_op_min obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_min>();
+}
+
+ast_expr_op_min uncheck(checked::ast_expr_op_min obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_min>();
+}
+
+checked::ast_expr_op_minus check(ast_expr_op_minus obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_minus>();
+}
+
+ast_expr_op_minus uncheck(checked::ast_expr_op_minus obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_minus>();
+}
+
+checked::ast_expr_op_mul check(ast_expr_op_mul obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_mul>();
+}
+
+ast_expr_op_mul uncheck(checked::ast_expr_op_mul obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_mul>();
+}
+
+checked::ast_expr_op_or check(ast_expr_op_or obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_or>();
+}
+
+ast_expr_op_or uncheck(checked::ast_expr_op_or obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_or>();
+}
+
+checked::ast_expr_op_or_else check(ast_expr_op_or_else obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_or_else>();
+}
+
+ast_expr_op_or_else uncheck(checked::ast_expr_op_or_else obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_or_else>();
+}
+
+checked::ast_expr_op_pdiv_q check(ast_expr_op_pdiv_q obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_pdiv_q>();
+}
+
+ast_expr_op_pdiv_q uncheck(checked::ast_expr_op_pdiv_q obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_pdiv_q>();
+}
+
+checked::ast_expr_op_pdiv_r check(ast_expr_op_pdiv_r obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_pdiv_r>();
+}
+
+ast_expr_op_pdiv_r uncheck(checked::ast_expr_op_pdiv_r obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_pdiv_r>();
+}
+
+checked::ast_expr_op_select check(ast_expr_op_select obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_select>();
+}
+
+ast_expr_op_select uncheck(checked::ast_expr_op_select obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_select>();
+}
+
+checked::ast_expr_op_sub check(ast_expr_op_sub obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_sub>();
+}
+
+ast_expr_op_sub uncheck(checked::ast_expr_op_sub obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_sub>();
+}
+
+checked::ast_expr_op_zdiv_r check(ast_expr_op_zdiv_r obj) {
+	return checked::manage(obj.copy()).as<checked::ast_expr_op>().as<checked::ast_expr_op_zdiv_r>();
+}
+
+ast_expr_op_zdiv_r uncheck(checked::ast_expr_op_zdiv_r obj) {
+	return manage(obj.copy()).as<ast_expr_op>().as<ast_expr_op_zdiv_r>();
+}
+
 checked::ast_node check(ast_node obj) {
 	return checked::manage(obj.copy());
 }
@@ -46,6 +286,54 @@ ast_node uncheck(checked::ast_node obj) {
 	return manage(obj.copy());
 }
 
+checked::ast_node_block check(ast_node_block obj) {
+	return checked::manage(obj.copy()).as<checked::ast_node_block>();
+}
+
+ast_node_block uncheck(checked::ast_node_block obj) {
+	return manage(obj.copy()).as<ast_node_block>();
+}
+
+checked::ast_node_for check(ast_node_for obj) {
+	return checked::manage(obj.copy()).as<checked::ast_node_for>();
+}
+
+ast_node_for uncheck(checked::ast_node_for obj) {
+	return manage(obj.copy()).as<ast_node_for>();
+}
+
+checked::ast_node_if check(ast_node_if obj) {
+	return checked::manage(obj.copy()).as<checked::ast_node_if>();
+}
+
+ast_node_if uncheck(checked::ast_node_if obj) {
+	return manage(obj.copy()).as<ast_node_if>();
+}
+
+checked::ast_node_list check(ast_node_list obj) {
+	return checked::manage(obj.copy());
+}
+
+ast_node_list uncheck(checked::ast_node_list obj) {
+	return manage(obj.copy());
+}
+
+checked::ast_node_mark check(ast_node_mark obj) {
+	return checked::manage(obj.copy()).as<checked::ast_node_mark>();
+}
+
+ast_node_mark uncheck(checked::ast_node_mark obj) {
+	return manage(obj.copy()).as<ast_node_mark>();
+}
+
+checked::ast_node_user check(ast_node_user obj) {
+	return checked::manage(obj.copy()).as<checked::ast_node_user>();
+}
+
+ast_node_user uncheck(checked::ast_node_user obj) {
+	return manage(obj.copy()).as<ast_node_user>();
+}
+
 checked::basic_map check(basic_map obj) {
 	return checked::manage(obj.copy());
 }
@@ -62,6 +350,30 @@ basic_set uncheck(checked::basic_set obj) {
 	return manage(obj.copy());
 }
 
+checked::fixed_box check(fixed_box obj) {
+	return checked::manage(obj.copy());
+}
+
+fixed_box uncheck(checked::fixed_box obj) {
+	return manage(obj.copy());
+}
+
+checked::id check(id obj) {
+	return checked::manage(obj.copy());
+}
+
+id uncheck(checked::id obj) {
+	return manage(obj.copy());
+}
+
+checked::id_list check(id_list obj) {
+	return checked::manage(obj.copy());
+}
+
+id_list uncheck(checked::id_list obj) {
+	return manage(obj.copy());
+}
+
 checked::map check(map obj) {
 	return checked::manage(obj.copy());
 }
@@ -78,6 +390,14 @@ multi_aff uncheck(checked::multi_aff obj) {
 	return manage(obj.copy());
 }
 
+checked::multi_id check(multi_id obj) {
+	return checked::manage(obj.copy());
+}
+
+multi_id uncheck(checked::multi_id obj) {
+	return manage(obj.copy());
+}
+
 checked::multi_pw_aff check(multi_pw_aff obj) {
 	return checked::manage(obj.copy());
 }
@@ -118,6 +438,14 @@ pw_aff uncheck(checked::pw_aff obj) {
 	return manage(obj.copy());
 }
 
+checked::pw_aff_list check(pw_aff_list obj) {
+	return checked::manage(obj.copy());
+}
+
+pw_aff_list uncheck(checked::pw_aff_list obj) {
+	return manage(obj.copy());
+}
+
 checked::pw_multi_aff check(pw_multi_aff obj) {
 	return checked::manage(obj.copy());
 }
@@ -126,6 +454,14 @@ pw_multi_aff uncheck(checked::pw_multi_aff obj) {
 	return manage(obj.copy());
 }
 
+checked::pw_multi_aff_list check(pw_multi_aff_list obj) {
+	return checked::manage(obj.copy());
+}
+
+pw_multi_aff_list uncheck(checked::pw_multi_aff_list obj) {
+	return manage(obj.copy());
+}
+
 checked::schedule check(schedule obj) {
 	return checked::manage(obj.copy());
 }
@@ -150,6 +486,94 @@ schedule_node uncheck(checked::schedule_node obj) {
 	return manage(obj.copy());
 }
 
+checked::schedule_node_band check(schedule_node_band obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_band>();
+}
+
+schedule_node_band uncheck(checked::schedule_node_band obj) {
+	return manage(obj.copy()).as<schedule_node_band>();
+}
+
+checked::schedule_node_context check(schedule_node_context obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_context>();
+}
+
+schedule_node_context uncheck(checked::schedule_node_context obj) {
+	return manage(obj.copy()).as<schedule_node_context>();
+}
+
+checked::schedule_node_domain check(schedule_node_domain obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_domain>();
+}
+
+schedule_node_domain uncheck(checked::schedule_node_domain obj) {
+	return manage(obj.copy()).as<schedule_node_domain>();
+}
+
+checked::schedule_node_expansion check(schedule_node_expansion obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_expansion>();
+}
+
+schedule_node_expansion uncheck(checked::schedule_node_expansion obj) {
+	return manage(obj.copy()).as<schedule_node_expansion>();
+}
+
+checked::schedule_node_extension check(schedule_node_extension obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_extension>();
+}
+
+schedule_node_extension uncheck(checked::schedule_node_extension obj) {
+	return manage(obj.copy()).as<schedule_node_extension>();
+}
+
+checked::schedule_node_filter check(schedule_node_filter obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_filter>();
+}
+
+schedule_node_filter uncheck(checked::schedule_node_filter obj) {
+	return manage(obj.copy()).as<schedule_node_filter>();
+}
+
+checked::schedule_node_guard check(schedule_node_guard obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_guard>();
+}
+
+schedule_node_guard uncheck(checked::schedule_node_guard obj) {
+	return manage(obj.copy()).as<schedule_node_guard>();
+}
+
+checked::schedule_node_leaf check(schedule_node_leaf obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_leaf>();
+}
+
+schedule_node_leaf uncheck(checked::schedule_node_leaf obj) {
+	return manage(obj.copy()).as<schedule_node_leaf>();
+}
+
+checked::schedule_node_mark check(schedule_node_mark obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_mark>();
+}
+
+schedule_node_mark uncheck(checked::schedule_node_mark obj) {
+	return manage(obj.copy()).as<schedule_node_mark>();
+}
+
+checked::schedule_node_sequence check(schedule_node_sequence obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_sequence>();
+}
+
+schedule_node_sequence uncheck(checked::schedule_node_sequence obj) {
+	return manage(obj.copy()).as<schedule_node_sequence>();
+}
+
+checked::schedule_node_set check(schedule_node_set obj) {
+	return checked::manage(obj.copy()).as<checked::schedule_node_set>();
+}
+
+schedule_node_set uncheck(checked::schedule_node_set obj) {
+	return manage(obj.copy()).as<schedule_node_set>();
+}
+
 checked::set check(set obj) {
 	return checked::manage(obj.copy());
 }
@@ -158,6 +582,14 @@ set uncheck(checked::set obj) {
 	return manage(obj.copy());
 }
 
+checked::space check(space obj) {
+	return checked::manage(obj.copy());
+}
+
+space uncheck(checked::space obj) {
+	return manage(obj.copy());
+}
+
 checked::union_access_info check(union_access_info obj) {
 	return checked::manage(obj.copy());
 }
@@ -190,6 +622,14 @@ union_pw_aff uncheck(checked::union_pw_aff obj) {
 	return manage(obj.copy());
 }
 
+checked::union_pw_aff_list check(union_pw_aff_list obj) {
+	return checked::manage(obj.copy());
+}
+
+union_pw_aff_list uncheck(checked::union_pw_aff_list obj) {
+	return manage(obj.copy());
+}
+
 checked::union_pw_multi_aff check(union_pw_multi_aff obj) {
 	return checked::manage(obj.copy());
 }
@@ -206,6 +646,14 @@ union_set uncheck(checked::union_set obj) {
 	return manage(obj.copy());
 }
 
+checked::union_set_list check(union_set_list obj) {
+	return checked::manage(obj.copy());
+}
+
+union_set_list uncheck(checked::union_set_list obj) {
+	return manage(obj.copy());
+}
+
 checked::val check(val obj) {
 	return checked::manage(obj.copy());
 }
@@ -214,6 +662,14 @@ val uncheck(checked::val obj) {
 	return manage(obj.copy());
 }
 
+checked::val_list check(val_list obj) {
+	return checked::manage(obj.copy());
+}
+
+val_list uncheck(checked::val_list obj) {
+	return manage(obj.copy());
+}
+
 } // namespace isl
 
 #endif /* ISL_CPP_CHECKED_CONVERSION */

diff  --git a/polly/lib/External/isl/include/isl/cpp-checked.h b/polly/lib/External/isl/include/isl/cpp-checked.h
index 1cd0506052b4..bd2aabbfd5da 100644
--- a/polly/lib/External/isl/include/isl/cpp-checked.h
+++ b/polly/lib/External/isl/include/isl/cpp-checked.h
@@ -8,6 +8,8 @@
 #ifndef ISL_CPP_CHECKED
 #define ISL_CPP_CHECKED
 
+#include <isl/id.h>
+#include <isl/space.h>
 #include <isl/val.h>
 #include <isl/aff.h>
 #include <isl/set.h>
@@ -19,12 +21,16 @@
 #include <isl/schedule.h>
 #include <isl/schedule_node.h>
 #include <isl/ast_build.h>
+#include <isl/fixed_box.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <functional>
+#include <memory>
+#include <ostream>
 #include <string>
+#include <type_traits>
 
 namespace isl {
 namespace checked {
@@ -42,37 +48,60 @@ namespace checked {
     abort();                                                 \
   } while (0)
 
+/* Class used to check that isl::checked::boolean,
+ * isl::checked::stat and isl::checked::size values are checked for errors.
+ */
+struct checker {
+	bool checked = false;
+	~checker() {
+		ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
+	}
+};
+
 class boolean {
 private:
-  mutable bool checked = false;
+  mutable std::shared_ptr<checker> check = std::make_shared<checker>();
   isl_bool val;
 
   friend boolean manage(isl_bool val);
   boolean(isl_bool val): val(val) {}
 public:
+  static boolean error() {
+    return boolean(isl_bool_error);
+  }
   boolean()
       : val(isl_bool_error) {}
-  ~boolean() {
-    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
-  }
 
   /* implicit */ boolean(bool val)
       : val(val ? isl_bool_true : isl_bool_false) {}
 
-  bool is_error() const { checked = true; return val == isl_bool_error; }
-  bool is_false() const { checked = true; return val == isl_bool_false; }
-  bool is_true() const { checked = true; return val == isl_bool_true; }
+  isl_bool release() {
+    auto tmp = val;
+    val = isl_bool_error;
+    check->checked = true;
+    return tmp;
+  }
+
+  bool is_error() const { check->checked = true; return val == isl_bool_error; }
+  bool is_false() const { check->checked = true; return val == isl_bool_false; }
+  bool is_true() const { check->checked = true; return val == isl_bool_true; }
 
   explicit operator bool() const {
-    ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked error state");
+    ISLPP_ASSERT(check->checked, "IMPLEMENTATION ERROR: Unchecked error state");
     ISLPP_ASSERT(!is_error(), "IMPLEMENTATION ERROR: Unhandled error state");
     return is_true();
   }
 
+  boolean negate() {
+    if (val == isl_bool_true)
+      val = isl_bool_false;
+    else if (val == isl_bool_false)
+      val = isl_bool_true;
+    return *this;
+  }
+
   boolean operator!() const {
-    if (is_error())
-      return *this;
-    return !is_true();
+    return boolean(*this).negate();
   }
 };
 
@@ -99,11 +128,11 @@ class ctx {
  */
 class stat {
 private:
-	mutable bool checked = false;
+	mutable std::shared_ptr<checker> check = std::make_shared<checker>();
 	isl_stat val;
 
 	friend stat manage(isl_stat val);
-	constexpr stat(isl_stat val) : val(val) {}
+	stat(isl_stat val) : val(val) {}
 public:
 	static stat ok() {
 		return stat(isl_stat_ok);
@@ -112,21 +141,18 @@ class stat {
 		return stat(isl_stat_error);
 	}
 	stat() : val(isl_stat_error) {}
-	~stat() {
-		ISLPP_ASSERT(checked, "IMPLEMENTATION ERROR: Unchecked state");
-	}
 
 	isl_stat release() {
-		checked = true;
+		check->checked = true;
 		return val;
 	}
 
 	bool is_error() const {
-		checked = true;
+		check->checked = true;
 		return val == isl_stat_error;
 	}
 	bool is_ok() const {
-		checked = true;
+		check->checked = true;
 		return val == isl_stat_ok;
 	}
 };
@@ -136,6 +162,44 @@ inline stat manage(isl_stat val)
 	return stat(val);
 }
 
+/* Class encapsulating an isl_size value.
+ */
+class size {
+private:
+	mutable std::shared_ptr<checker> check = std::make_shared<checker>();
+	isl_size val;
+
+	friend size manage(isl_size val);
+	size(isl_size val) : val(val) {}
+public:
+	size() : val(isl_size_error) {}
+
+	isl_size release() {
+		auto tmp = val;
+		val = isl_size_error;
+		check->checked = true;
+		return tmp;
+	}
+
+	bool is_error() const {
+		check->checked = true;
+		return val == isl_size_error;
+	}
+
+	explicit operator unsigned() const {
+		ISLPP_ASSERT(check->checked,
+			    "IMPLEMENTATION ERROR: Unchecked error state");
+		ISLPP_ASSERT(!is_error(),
+			    "IMPLEMENTATION ERROR: Unhandled error state");
+		return val;
+	}
+};
+
+inline size manage(isl_size val)
+{
+	return size(val);
+}
+
 }
 } // namespace isl
 
@@ -145,30 +209,87 @@ namespace checked {
 
 // forward declarations
 class aff;
+class aff_list;
 class ast_build;
 class ast_expr;
+class ast_expr_id;
+class ast_expr_int;
+class ast_expr_op;
+class ast_expr_op_access;
+class ast_expr_op_add;
+class ast_expr_op_address_of;
+class ast_expr_op_and;
+class ast_expr_op_and_then;
+class ast_expr_op_call;
+class ast_expr_op_cond;
+class ast_expr_op_div;
+class ast_expr_op_eq;
+class ast_expr_op_fdiv_q;
+class ast_expr_op_ge;
+class ast_expr_op_gt;
+class ast_expr_op_le;
+class ast_expr_op_lt;
+class ast_expr_op_max;
+class ast_expr_op_member;
+class ast_expr_op_min;
+class ast_expr_op_minus;
+class ast_expr_op_mul;
+class ast_expr_op_or;
+class ast_expr_op_or_else;
+class ast_expr_op_pdiv_q;
+class ast_expr_op_pdiv_r;
+class ast_expr_op_select;
+class ast_expr_op_sub;
+class ast_expr_op_zdiv_r;
 class ast_node;
+class ast_node_block;
+class ast_node_for;
+class ast_node_if;
+class ast_node_list;
+class ast_node_mark;
+class ast_node_user;
 class basic_map;
 class basic_set;
+class fixed_box;
+class id;
+class id_list;
 class map;
 class multi_aff;
+class multi_id;
 class multi_pw_aff;
 class multi_union_pw_aff;
 class multi_val;
 class point;
 class pw_aff;
+class pw_aff_list;
 class pw_multi_aff;
+class pw_multi_aff_list;
 class schedule;
 class schedule_constraints;
 class schedule_node;
+class schedule_node_band;
+class schedule_node_context;
+class schedule_node_domain;
+class schedule_node_expansion;
+class schedule_node_extension;
+class schedule_node_filter;
+class schedule_node_guard;
+class schedule_node_leaf;
+class schedule_node_mark;
+class schedule_node_sequence;
+class schedule_node_set;
 class set;
+class space;
 class union_access_info;
 class union_flow;
 class union_map;
 class union_pw_aff;
+class union_pw_aff_list;
 class union_pw_multi_aff;
 class union_set;
+class union_set_list;
 class val;
+class val_list;
 
 // declarations for isl::aff
 inline aff manage(__isl_take isl_aff *ptr);
@@ -178,6 +299,7 @@ class aff {
   friend inline aff manage(__isl_take isl_aff *ptr);
   friend inline aff manage_copy(__isl_keep isl_aff *ptr);
 
+protected:
   isl_aff *ptr = nullptr;
 
   inline explicit aff(__isl_take isl_aff *ptr);
@@ -185,7 +307,7 @@ class aff {
 public:
   inline /* implicit */ aff();
   inline /* implicit */ aff(const aff &obj);
-  inline explicit aff(ctx ctx, const std::string &str);
+  inline explicit aff(isl::checked::ctx ctx, const std::string &str);
   inline aff &operator=(aff obj);
   inline ~aff();
   inline __isl_give isl_aff *copy() const &;
@@ -193,25 +315,71 @@ class aff {
   inline __isl_keep isl_aff *get() const;
   inline __isl_give isl_aff *release();
   inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline aff add(aff aff2) const;
-  inline aff ceil() const;
-  inline aff div(aff aff2) const;
-  inline set eq_set(aff aff2) const;
-  inline aff floor() const;
-  inline set ge_set(aff aff2) const;
-  inline set gt_set(aff aff2) const;
-  inline set le_set(aff aff2) const;
-  inline set lt_set(aff aff2) const;
-  inline aff mod(val mod) const;
-  inline aff mul(aff aff2) const;
-  inline set ne_set(aff aff2) const;
-  inline aff neg() const;
-  inline aff pullback(multi_aff ma) const;
-  inline aff scale(val v) const;
-  inline aff scale_down(val v) const;
-  inline aff sub(aff aff2) const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::aff add(isl::checked::aff aff2) const;
+  inline isl::checked::aff add_constant(isl::checked::val v) const;
+  inline isl::checked::aff add_constant(long v) const;
+  inline isl::checked::basic_set bind(isl::checked::id id) const;
+  inline isl::checked::basic_set bind(const std::string &id) const;
+  inline isl::checked::aff ceil() const;
+  inline isl::checked::aff div(isl::checked::aff aff2) const;
+  inline isl::checked::set eq_set(isl::checked::aff aff2) const;
+  inline isl::checked::val eval(isl::checked::point pnt) const;
+  inline isl::checked::aff floor() const;
+  inline isl::checked::set ge_set(isl::checked::aff aff2) const;
+  inline isl::checked::aff gist(isl::checked::set context) const;
+  inline isl::checked::set gt_set(isl::checked::aff aff2) const;
+  inline isl::checked::set le_set(isl::checked::aff aff2) const;
+  inline isl::checked::set lt_set(isl::checked::aff aff2) const;
+  inline isl::checked::aff mod(isl::checked::val mod) const;
+  inline isl::checked::aff mod(long mod) const;
+  inline isl::checked::aff mul(isl::checked::aff aff2) const;
+  inline isl::checked::set ne_set(isl::checked::aff aff2) const;
+  inline isl::checked::aff neg() const;
+  inline isl::checked::aff pullback(isl::checked::multi_aff ma) const;
+  inline isl::checked::aff scale(isl::checked::val v) const;
+  inline isl::checked::aff scale(long v) const;
+  inline isl::checked::aff scale_down(isl::checked::val v) const;
+  inline isl::checked::aff scale_down(long v) const;
+  inline isl::checked::aff sub(isl::checked::aff aff2) const;
+  inline isl::checked::aff unbind_params_insert_domain(isl::checked::multi_id domain) const;
+};
+
+// declarations for isl::aff_list
+inline aff_list manage(__isl_take isl_aff_list *ptr);
+inline aff_list manage_copy(__isl_keep isl_aff_list *ptr);
+
+class aff_list {
+  friend inline aff_list manage(__isl_take isl_aff_list *ptr);
+  friend inline aff_list manage_copy(__isl_keep isl_aff_list *ptr);
+
+protected:
+  isl_aff_list *ptr = nullptr;
+
+  inline explicit aff_list(__isl_take isl_aff_list *ptr);
+
+public:
+  inline /* implicit */ aff_list();
+  inline /* implicit */ aff_list(const aff_list &obj);
+  inline explicit aff_list(isl::checked::ctx ctx, int n);
+  inline explicit aff_list(isl::checked::aff el);
+  inline aff_list &operator=(aff_list obj);
+  inline ~aff_list();
+  inline __isl_give isl_aff_list *copy() const &;
+  inline __isl_give isl_aff_list *copy() && = delete;
+  inline __isl_keep isl_aff_list *get() const;
+  inline __isl_give isl_aff_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::aff_list add(isl::checked::aff el) const;
+  inline isl::checked::aff_list clear() const;
+  inline isl::checked::aff_list concat(isl::checked::aff_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::aff)> &fn) const;
+  inline isl::checked::aff at(int index) const;
+  inline isl::checked::aff get_at(int index) const;
+  inline class size size() const;
 };
 
 // declarations for isl::ast_build
@@ -222,6 +390,7 @@ class ast_build {
   friend inline ast_build manage(__isl_take isl_ast_build *ptr);
   friend inline ast_build manage_copy(__isl_keep isl_ast_build *ptr);
 
+protected:
   isl_ast_build *ptr = nullptr;
 
   inline explicit ast_build(__isl_take isl_ast_build *ptr);
@@ -229,7 +398,7 @@ class ast_build {
 public:
   inline /* implicit */ ast_build();
   inline /* implicit */ ast_build(const ast_build &obj);
-  inline explicit ast_build(ctx ctx);
+  inline explicit ast_build(isl::checked::ctx ctx);
   inline ast_build &operator=(ast_build obj);
   inline ~ast_build();
   inline __isl_give isl_ast_build *copy() const &;
@@ -237,16 +406,29 @@ class ast_build {
   inline __isl_keep isl_ast_build *get() const;
   inline __isl_give isl_ast_build *release();
   inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline ast_expr access_from(pw_multi_aff pma) const;
-  inline ast_expr access_from(multi_pw_aff mpa) const;
-  inline ast_expr call_from(pw_multi_aff pma) const;
-  inline ast_expr call_from(multi_pw_aff mpa) const;
-  inline ast_expr expr_from(set set) const;
-  inline ast_expr expr_from(pw_aff pa) const;
-  static inline ast_build from_context(set set);
-  inline ast_node node_from_schedule_map(union_map schedule) const;
+  inline isl::checked::ctx ctx() const;
+
+private:
+  inline ast_build &copy_callbacks(const ast_build &obj);
+  struct at_each_domain_data {
+    std::function<isl::checked::ast_node(isl::checked::ast_node, isl::checked::ast_build)> func;
+  };
+  std::shared_ptr<at_each_domain_data> at_each_domain_data;
+  static inline isl_ast_node *at_each_domain(isl_ast_node *arg_0, isl_ast_build *arg_1, void *arg_2);
+  inline void set_at_each_domain_data(const std::function<isl::checked::ast_node(isl::checked::ast_node, isl::checked::ast_build)> &fn);
+public:
+  inline isl::checked::ast_build set_at_each_domain(const std::function<isl::checked::ast_node(isl::checked::ast_node, isl::checked::ast_build)> &fn) const;
+  inline isl::checked::ast_expr access_from(isl::checked::multi_pw_aff mpa) const;
+  inline isl::checked::ast_expr access_from(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::ast_expr call_from(isl::checked::multi_pw_aff mpa) const;
+  inline isl::checked::ast_expr call_from(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::ast_expr expr_from(isl::checked::pw_aff pa) const;
+  inline isl::checked::ast_expr expr_from(isl::checked::set set) const;
+  static inline isl::checked::ast_build from_context(isl::checked::set set);
+  inline isl::checked::union_map schedule() const;
+  inline isl::checked::union_map get_schedule() const;
+  inline isl::checked::ast_node node_from(isl::checked::schedule schedule) const;
+  inline isl::checked::ast_node node_from_schedule_map(isl::checked::union_map schedule) const;
 };
 
 // declarations for isl::ast_expr
@@ -257,6 +439,7 @@ class ast_expr {
   friend inline ast_expr manage(__isl_take isl_ast_expr *ptr);
   friend inline ast_expr manage_copy(__isl_keep isl_ast_expr *ptr);
 
+protected:
   isl_ast_expr *ptr = nullptr;
 
   inline explicit ast_expr(__isl_take isl_ast_expr *ptr);
@@ -271,3281 +454,10021 @@ class ast_expr {
   inline __isl_keep isl_ast_expr *get() const;
   inline __isl_give isl_ast_expr *release();
   inline bool is_null() const;
-  inline ctx get_ctx() const;
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_ast_expr_get_type(NULL)),
+                  const T>::value>::type>
+  inline boolean isa_type(T subtype) const;
+public:
+  template <class T> inline boolean isa() const;
+  template <class T> inline T as() const;
+  inline isl::checked::ctx ctx() const;
 
   inline std::string to_C_str() const;
 };
 
-// declarations for isl::ast_node
-inline ast_node manage(__isl_take isl_ast_node *ptr);
-inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
-
-class ast_node {
-  friend inline ast_node manage(__isl_take isl_ast_node *ptr);
-  friend inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+// declarations for isl::ast_expr_id
 
-  isl_ast_node *ptr = nullptr;
+class ast_expr_id : public ast_expr {
+  template <class T>
+  friend boolean ast_expr::isa() const;
+  friend ast_expr_id ast_expr::as<ast_expr_id>() const;
+  static const auto type = isl_ast_expr_id;
 
-  inline explicit ast_node(__isl_take isl_ast_node *ptr);
+protected:
+  inline explicit ast_expr_id(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ ast_node();
-  inline /* implicit */ ast_node(const ast_node &obj);
-  inline ast_node &operator=(ast_node obj);
-  inline ~ast_node();
-  inline __isl_give isl_ast_node *copy() const &;
-  inline __isl_give isl_ast_node *copy() && = delete;
-  inline __isl_keep isl_ast_node *get() const;
-  inline __isl_give isl_ast_node *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_id();
+  inline /* implicit */ ast_expr_id(const ast_expr_id &obj);
+  inline ast_expr_id &operator=(ast_expr_id obj);
+  inline isl::checked::ctx ctx() const;
 
-  inline std::string to_C_str() const;
+  inline isl::checked::id id() const;
+  inline isl::checked::id get_id() const;
 };
 
-// declarations for isl::basic_map
-inline basic_map manage(__isl_take isl_basic_map *ptr);
-inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
-
-class basic_map {
-  friend inline basic_map manage(__isl_take isl_basic_map *ptr);
-  friend inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+// declarations for isl::ast_expr_int
 
-  isl_basic_map *ptr = nullptr;
+class ast_expr_int : public ast_expr {
+  template <class T>
+  friend boolean ast_expr::isa() const;
+  friend ast_expr_int ast_expr::as<ast_expr_int>() const;
+  static const auto type = isl_ast_expr_int;
 
-  inline explicit basic_map(__isl_take isl_basic_map *ptr);
+protected:
+  inline explicit ast_expr_int(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ basic_map();
-  inline /* implicit */ basic_map(const basic_map &obj);
-  inline explicit basic_map(ctx ctx, const std::string &str);
-  inline basic_map &operator=(basic_map obj);
-  inline ~basic_map();
-  inline __isl_give isl_basic_map *copy() const &;
-  inline __isl_give isl_basic_map *copy() && = delete;
-  inline __isl_keep isl_basic_map *get() const;
-  inline __isl_give isl_basic_map *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_map affine_hull() const;
-  inline basic_map apply_domain(basic_map bmap2) const;
-  inline basic_map apply_range(basic_map bmap2) const;
-  inline basic_set deltas() const;
-  inline basic_map detect_equalities() const;
-  inline basic_map flatten() const;
-  inline basic_map flatten_domain() const;
-  inline basic_map flatten_range() const;
-  inline basic_map gist(basic_map context) const;
-  inline basic_map intersect(basic_map bmap2) const;
-  inline basic_map intersect_domain(basic_set bset) const;
-  inline basic_map intersect_range(basic_set bset) const;
-  inline boolean is_empty() const;
-  inline boolean is_equal(const basic_map &bmap2) const;
-  inline boolean is_subset(const basic_map &bmap2) const;
-  inline map lexmax() const;
-  inline map lexmin() const;
-  inline basic_map reverse() const;
-  inline basic_map sample() const;
-  inline map unite(basic_map bmap2) const;
-};
+  inline /* implicit */ ast_expr_int();
+  inline /* implicit */ ast_expr_int(const ast_expr_int &obj);
+  inline ast_expr_int &operator=(ast_expr_int obj);
+  inline isl::checked::ctx ctx() const;
 
-// declarations for isl::basic_set
-inline basic_set manage(__isl_take isl_basic_set *ptr);
-inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+  inline isl::checked::val val() const;
+  inline isl::checked::val get_val() const;
+};
 
-class basic_set {
-  friend inline basic_set manage(__isl_take isl_basic_set *ptr);
-  friend inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+// declarations for isl::ast_expr_op
 
-  isl_basic_set *ptr = nullptr;
+class ast_expr_op : public ast_expr {
+  template <class T>
+  friend boolean ast_expr::isa() const;
+  friend ast_expr_op ast_expr::as<ast_expr_op>() const;
+  static const auto type = isl_ast_expr_op;
 
-  inline explicit basic_set(__isl_take isl_basic_set *ptr);
+protected:
+  inline explicit ast_expr_op(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ basic_set();
-  inline /* implicit */ basic_set(const basic_set &obj);
-  inline explicit basic_set(ctx ctx, const std::string &str);
-  inline /* implicit */ basic_set(point pnt);
-  inline basic_set &operator=(basic_set obj);
-  inline ~basic_set();
-  inline __isl_give isl_basic_set *copy() const &;
-  inline __isl_give isl_basic_set *copy() && = delete;
-  inline __isl_keep isl_basic_set *get() const;
-  inline __isl_give isl_basic_set *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_set affine_hull() const;
-  inline basic_set apply(basic_map bmap) const;
-  inline basic_set detect_equalities() const;
-  inline val dim_max_val(int pos) const;
-  inline basic_set flatten() const;
-  inline basic_set gist(basic_set context) const;
-  inline basic_set intersect(basic_set bset2) const;
-  inline basic_set intersect_params(basic_set bset2) const;
-  inline boolean is_empty() const;
-  inline boolean is_equal(const basic_set &bset2) const;
-  inline boolean is_subset(const basic_set &bset2) const;
-  inline boolean is_wrapping() const;
-  inline set lexmax() const;
-  inline set lexmin() const;
-  inline basic_set sample() const;
-  inline point sample_point() const;
-  inline set unite(basic_set bset2) const;
+  inline /* implicit */ ast_expr_op();
+  inline /* implicit */ ast_expr_op(const ast_expr_op &obj);
+  inline ast_expr_op &operator=(ast_expr_op obj);
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_ast_expr_op_get_type(NULL)),
+                  const T>::value>::type>
+  inline boolean isa_type(T subtype) const;
+public:
+  template <class T> inline boolean isa() const;
+  template <class T> inline T as() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::ast_expr arg(int pos) const;
+  inline isl::checked::ast_expr get_arg(int pos) const;
+  inline class size n_arg() const;
+  inline class size get_n_arg() const;
 };
 
-// declarations for isl::map
-inline map manage(__isl_take isl_map *ptr);
-inline map manage_copy(__isl_keep isl_map *ptr);
-
-class map {
-  friend inline map manage(__isl_take isl_map *ptr);
-  friend inline map manage_copy(__isl_keep isl_map *ptr);
+// declarations for isl::ast_expr_op_access
 
-  isl_map *ptr = nullptr;
+class ast_expr_op_access : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_access ast_expr_op::as<ast_expr_op_access>() const;
+  static const auto type = isl_ast_expr_op_access;
 
-  inline explicit map(__isl_take isl_map *ptr);
+protected:
+  inline explicit ast_expr_op_access(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ map();
-  inline /* implicit */ map(const map &obj);
-  inline explicit map(ctx ctx, const std::string &str);
-  inline /* implicit */ map(basic_map bmap);
-  inline map &operator=(map obj);
-  inline ~map();
-  inline __isl_give isl_map *copy() const &;
-  inline __isl_give isl_map *copy() && = delete;
-  inline __isl_keep isl_map *get() const;
-  inline __isl_give isl_map *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_map affine_hull() const;
-  inline map apply_domain(map map2) const;
-  inline map apply_range(map map2) const;
-  inline map coalesce() const;
-  inline map complement() const;
-  inline set deltas() const;
-  inline map detect_equalities() const;
-  inline map flatten() const;
-  inline map flatten_domain() const;
-  inline map flatten_range() const;
-  inline stat foreach_basic_map(const std::function<stat(basic_map)> &fn) const;
-  inline map gist(map context) const;
-  inline map gist_domain(set context) const;
-  inline map intersect(map map2) const;
-  inline map intersect_domain(set set) const;
-  inline map intersect_params(set params) const;
-  inline map intersect_range(set set) const;
-  inline boolean is_bijective() const;
-  inline boolean is_disjoint(const map &map2) const;
-  inline boolean is_empty() const;
-  inline boolean is_equal(const map &map2) const;
-  inline boolean is_injective() const;
-  inline boolean is_single_valued() const;
-  inline boolean is_strict_subset(const map &map2) const;
-  inline boolean is_subset(const map &map2) const;
-  inline map lexmax() const;
-  inline map lexmin() const;
-  inline basic_map polyhedral_hull() const;
-  inline map reverse() const;
-  inline basic_map sample() const;
-  inline map subtract(map map2) const;
-  inline map unite(map map2) const;
-  inline basic_map unshifted_simple_hull() const;
-};
+  inline /* implicit */ ast_expr_op_access();
+  inline /* implicit */ ast_expr_op_access(const ast_expr_op_access &obj);
+  inline ast_expr_op_access &operator=(ast_expr_op_access obj);
+  inline isl::checked::ctx ctx() const;
 
-// declarations for isl::multi_aff
-inline multi_aff manage(__isl_take isl_multi_aff *ptr);
-inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+};
 
-class multi_aff {
-  friend inline multi_aff manage(__isl_take isl_multi_aff *ptr);
-  friend inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+// declarations for isl::ast_expr_op_add
 
-  isl_multi_aff *ptr = nullptr;
+class ast_expr_op_add : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_add ast_expr_op::as<ast_expr_op_add>() const;
+  static const auto type = isl_ast_expr_op_add;
 
-  inline explicit multi_aff(__isl_take isl_multi_aff *ptr);
+protected:
+  inline explicit ast_expr_op_add(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_aff();
-  inline /* implicit */ multi_aff(const multi_aff &obj);
-  inline /* implicit */ multi_aff(aff aff);
-  inline explicit multi_aff(ctx ctx, const std::string &str);
-  inline multi_aff &operator=(multi_aff obj);
-  inline ~multi_aff();
-  inline __isl_give isl_multi_aff *copy() const &;
-  inline __isl_give isl_multi_aff *copy() && = delete;
-  inline __isl_keep isl_multi_aff *get() const;
-  inline __isl_give isl_multi_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_add();
+  inline /* implicit */ ast_expr_op_add(const ast_expr_op_add &obj);
+  inline ast_expr_op_add &operator=(ast_expr_op_add obj);
+  inline isl::checked::ctx ctx() const;
 
-  inline multi_aff add(multi_aff multi2) const;
-  inline multi_aff flat_range_product(multi_aff multi2) const;
-  inline multi_aff product(multi_aff multi2) const;
-  inline multi_aff pullback(multi_aff ma2) const;
-  inline multi_aff range_product(multi_aff multi2) const;
 };
 
-// declarations for isl::multi_pw_aff
-inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
-inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
-
-class multi_pw_aff {
-  friend inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
-  friend inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+// declarations for isl::ast_expr_op_address_of
 
-  isl_multi_pw_aff *ptr = nullptr;
+class ast_expr_op_address_of : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_address_of ast_expr_op::as<ast_expr_op_address_of>() const;
+  static const auto type = isl_ast_expr_op_address_of;
 
-  inline explicit multi_pw_aff(__isl_take isl_multi_pw_aff *ptr);
+protected:
+  inline explicit ast_expr_op_address_of(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_pw_aff();
-  inline /* implicit */ multi_pw_aff(const multi_pw_aff &obj);
-  inline /* implicit */ multi_pw_aff(multi_aff ma);
-  inline /* implicit */ multi_pw_aff(pw_aff pa);
-  inline /* implicit */ multi_pw_aff(pw_multi_aff pma);
-  inline explicit multi_pw_aff(ctx ctx, const std::string &str);
-  inline multi_pw_aff &operator=(multi_pw_aff obj);
-  inline ~multi_pw_aff();
-  inline __isl_give isl_multi_pw_aff *copy() const &;
-  inline __isl_give isl_multi_pw_aff *copy() && = delete;
-  inline __isl_keep isl_multi_pw_aff *get() const;
-  inline __isl_give isl_multi_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline multi_pw_aff add(multi_pw_aff multi2) const;
-  inline multi_pw_aff flat_range_product(multi_pw_aff multi2) const;
-  inline multi_pw_aff product(multi_pw_aff multi2) const;
-  inline multi_pw_aff pullback(multi_aff ma) const;
-  inline multi_pw_aff pullback(pw_multi_aff pma) const;
-  inline multi_pw_aff pullback(multi_pw_aff mpa2) const;
-  inline multi_pw_aff range_product(multi_pw_aff multi2) const;
-};
+  inline /* implicit */ ast_expr_op_address_of();
+  inline /* implicit */ ast_expr_op_address_of(const ast_expr_op_address_of &obj);
+  inline ast_expr_op_address_of &operator=(ast_expr_op_address_of obj);
+  inline isl::checked::ctx ctx() const;
 
-// declarations for isl::multi_union_pw_aff
-inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
-inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+};
 
-class multi_union_pw_aff {
-  friend inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
-  friend inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+// declarations for isl::ast_expr_op_and
 
-  isl_multi_union_pw_aff *ptr = nullptr;
+class ast_expr_op_and : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_and ast_expr_op::as<ast_expr_op_and>() const;
+  static const auto type = isl_ast_expr_op_and;
 
-  inline explicit multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr);
+protected:
+  inline explicit ast_expr_op_and(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_union_pw_aff();
-  inline /* implicit */ multi_union_pw_aff(const multi_union_pw_aff &obj);
-  inline /* implicit */ multi_union_pw_aff(union_pw_aff upa);
-  inline /* implicit */ multi_union_pw_aff(multi_pw_aff mpa);
-  inline explicit multi_union_pw_aff(ctx ctx, const std::string &str);
-  inline multi_union_pw_aff &operator=(multi_union_pw_aff obj);
-  inline ~multi_union_pw_aff();
-  inline __isl_give isl_multi_union_pw_aff *copy() const &;
-  inline __isl_give isl_multi_union_pw_aff *copy() && = delete;
-  inline __isl_keep isl_multi_union_pw_aff *get() const;
-  inline __isl_give isl_multi_union_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_and();
+  inline /* implicit */ ast_expr_op_and(const ast_expr_op_and &obj);
+  inline ast_expr_op_and &operator=(ast_expr_op_and obj);
+  inline isl::checked::ctx ctx() const;
 
-  inline multi_union_pw_aff add(multi_union_pw_aff multi2) const;
-  inline multi_union_pw_aff flat_range_product(multi_union_pw_aff multi2) const;
-  inline multi_union_pw_aff pullback(union_pw_multi_aff upma) const;
-  inline multi_union_pw_aff range_product(multi_union_pw_aff multi2) const;
-  inline multi_union_pw_aff union_add(multi_union_pw_aff mupa2) const;
 };
 
-// declarations for isl::multi_val
-inline multi_val manage(__isl_take isl_multi_val *ptr);
-inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
-
-class multi_val {
-  friend inline multi_val manage(__isl_take isl_multi_val *ptr);
-  friend inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+// declarations for isl::ast_expr_op_and_then
 
-  isl_multi_val *ptr = nullptr;
+class ast_expr_op_and_then : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_and_then ast_expr_op::as<ast_expr_op_and_then>() const;
+  static const auto type = isl_ast_expr_op_and_then;
 
-  inline explicit multi_val(__isl_take isl_multi_val *ptr);
+protected:
+  inline explicit ast_expr_op_and_then(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_val();
-  inline /* implicit */ multi_val(const multi_val &obj);
-  inline multi_val &operator=(multi_val obj);
-  inline ~multi_val();
-  inline __isl_give isl_multi_val *copy() const &;
-  inline __isl_give isl_multi_val *copy() && = delete;
-  inline __isl_keep isl_multi_val *get() const;
-  inline __isl_give isl_multi_val *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_and_then();
+  inline /* implicit */ ast_expr_op_and_then(const ast_expr_op_and_then &obj);
+  inline ast_expr_op_and_then &operator=(ast_expr_op_and_then obj);
+  inline isl::checked::ctx ctx() const;
 
-  inline multi_val add(multi_val multi2) const;
-  inline multi_val flat_range_product(multi_val multi2) const;
-  inline multi_val product(multi_val multi2) const;
-  inline multi_val range_product(multi_val multi2) const;
 };
 
-// declarations for isl::point
-inline point manage(__isl_take isl_point *ptr);
-inline point manage_copy(__isl_keep isl_point *ptr);
-
-class point {
-  friend inline point manage(__isl_take isl_point *ptr);
-  friend inline point manage_copy(__isl_keep isl_point *ptr);
+// declarations for isl::ast_expr_op_call
 
-  isl_point *ptr = nullptr;
+class ast_expr_op_call : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_call ast_expr_op::as<ast_expr_op_call>() const;
+  static const auto type = isl_ast_expr_op_call;
 
-  inline explicit point(__isl_take isl_point *ptr);
+protected:
+  inline explicit ast_expr_op_call(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ point();
-  inline /* implicit */ point(const point &obj);
-  inline point &operator=(point obj);
-  inline ~point();
-  inline __isl_give isl_point *copy() const &;
-  inline __isl_give isl_point *copy() && = delete;
-  inline __isl_keep isl_point *get() const;
-  inline __isl_give isl_point *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_call();
+  inline /* implicit */ ast_expr_op_call(const ast_expr_op_call &obj);
+  inline ast_expr_op_call &operator=(ast_expr_op_call obj);
+  inline isl::checked::ctx ctx() const;
 
 };
 
-// declarations for isl::pw_aff
-inline pw_aff manage(__isl_take isl_pw_aff *ptr);
-inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
-
-class pw_aff {
-  friend inline pw_aff manage(__isl_take isl_pw_aff *ptr);
-  friend inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+// declarations for isl::ast_expr_op_cond
 
-  isl_pw_aff *ptr = nullptr;
+class ast_expr_op_cond : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_cond ast_expr_op::as<ast_expr_op_cond>() const;
+  static const auto type = isl_ast_expr_op_cond;
 
-  inline explicit pw_aff(__isl_take isl_pw_aff *ptr);
+protected:
+  inline explicit ast_expr_op_cond(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ pw_aff();
-  inline /* implicit */ pw_aff(const pw_aff &obj);
-  inline /* implicit */ pw_aff(aff aff);
-  inline explicit pw_aff(ctx ctx, const std::string &str);
-  inline pw_aff &operator=(pw_aff obj);
-  inline ~pw_aff();
-  inline __isl_give isl_pw_aff *copy() const &;
-  inline __isl_give isl_pw_aff *copy() && = delete;
-  inline __isl_keep isl_pw_aff *get() const;
-  inline __isl_give isl_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline pw_aff add(pw_aff pwaff2) const;
-  inline pw_aff ceil() const;
-  inline pw_aff cond(pw_aff pwaff_true, pw_aff pwaff_false) const;
-  inline pw_aff div(pw_aff pa2) const;
-  inline set eq_set(pw_aff pwaff2) const;
-  inline pw_aff floor() const;
-  inline set ge_set(pw_aff pwaff2) const;
-  inline set gt_set(pw_aff pwaff2) const;
-  inline set le_set(pw_aff pwaff2) const;
-  inline set lt_set(pw_aff pwaff2) const;
-  inline pw_aff max(pw_aff pwaff2) const;
-  inline pw_aff min(pw_aff pwaff2) const;
-  inline pw_aff mod(val mod) const;
-  inline pw_aff mul(pw_aff pwaff2) const;
-  inline set ne_set(pw_aff pwaff2) const;
-  inline pw_aff neg() const;
-  inline pw_aff pullback(multi_aff ma) const;
-  inline pw_aff pullback(pw_multi_aff pma) const;
-  inline pw_aff pullback(multi_pw_aff mpa) const;
-  inline pw_aff scale(val v) const;
-  inline pw_aff scale_down(val f) const;
-  inline pw_aff sub(pw_aff pwaff2) const;
-  inline pw_aff tdiv_q(pw_aff pa2) const;
-  inline pw_aff tdiv_r(pw_aff pa2) const;
-  inline pw_aff union_add(pw_aff pwaff2) const;
+  inline /* implicit */ ast_expr_op_cond();
+  inline /* implicit */ ast_expr_op_cond(const ast_expr_op_cond &obj);
+  inline ast_expr_op_cond &operator=(ast_expr_op_cond obj);
+  inline isl::checked::ctx ctx() const;
+
 };
 
-// declarations for isl::pw_multi_aff
-inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
-inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+// declarations for isl::ast_expr_op_div
 
-class pw_multi_aff {
-  friend inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
-  friend inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+class ast_expr_op_div : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_div ast_expr_op::as<ast_expr_op_div>() const;
+  static const auto type = isl_ast_expr_op_div;
 
-  isl_pw_multi_aff *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_div(__isl_take isl_ast_expr *ptr);
 
-  inline explicit pw_multi_aff(__isl_take isl_pw_multi_aff *ptr);
+public:
+  inline /* implicit */ ast_expr_op_div();
+  inline /* implicit */ ast_expr_op_div(const ast_expr_op_div &obj);
+  inline ast_expr_op_div &operator=(ast_expr_op_div obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_eq
+
+class ast_expr_op_eq : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_eq ast_expr_op::as<ast_expr_op_eq>() const;
+  static const auto type = isl_ast_expr_op_eq;
+
+protected:
+  inline explicit ast_expr_op_eq(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ pw_multi_aff();
-  inline /* implicit */ pw_multi_aff(const pw_multi_aff &obj);
-  inline /* implicit */ pw_multi_aff(multi_aff ma);
-  inline /* implicit */ pw_multi_aff(pw_aff pa);
-  inline explicit pw_multi_aff(ctx ctx, const std::string &str);
-  inline pw_multi_aff &operator=(pw_multi_aff obj);
-  inline ~pw_multi_aff();
-  inline __isl_give isl_pw_multi_aff *copy() const &;
-  inline __isl_give isl_pw_multi_aff *copy() && = delete;
-  inline __isl_keep isl_pw_multi_aff *get() const;
-  inline __isl_give isl_pw_multi_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline pw_multi_aff add(pw_multi_aff pma2) const;
-  inline pw_multi_aff flat_range_product(pw_multi_aff pma2) const;
-  inline pw_multi_aff product(pw_multi_aff pma2) const;
-  inline pw_multi_aff pullback(multi_aff ma) const;
-  inline pw_multi_aff pullback(pw_multi_aff pma2) const;
-  inline pw_multi_aff range_product(pw_multi_aff pma2) const;
-  inline pw_multi_aff union_add(pw_multi_aff pma2) const;
-};
+  inline /* implicit */ ast_expr_op_eq();
+  inline /* implicit */ ast_expr_op_eq(const ast_expr_op_eq &obj);
+  inline ast_expr_op_eq &operator=(ast_expr_op_eq obj);
+  inline isl::checked::ctx ctx() const;
 
-// declarations for isl::schedule
-inline schedule manage(__isl_take isl_schedule *ptr);
-inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+};
 
-class schedule {
-  friend inline schedule manage(__isl_take isl_schedule *ptr);
-  friend inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+// declarations for isl::ast_expr_op_fdiv_q
 
-  isl_schedule *ptr = nullptr;
+class ast_expr_op_fdiv_q : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_fdiv_q ast_expr_op::as<ast_expr_op_fdiv_q>() const;
+  static const auto type = isl_ast_expr_op_fdiv_q;
 
-  inline explicit schedule(__isl_take isl_schedule *ptr);
+protected:
+  inline explicit ast_expr_op_fdiv_q(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ schedule();
-  inline /* implicit */ schedule(const schedule &obj);
-  inline explicit schedule(ctx ctx, const std::string &str);
-  inline schedule &operator=(schedule obj);
-  inline ~schedule();
-  inline __isl_give isl_schedule *copy() const &;
-  inline __isl_give isl_schedule *copy() && = delete;
-  inline __isl_keep isl_schedule *get() const;
-  inline __isl_give isl_schedule *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_fdiv_q();
+  inline /* implicit */ ast_expr_op_fdiv_q(const ast_expr_op_fdiv_q &obj);
+  inline ast_expr_op_fdiv_q &operator=(ast_expr_op_fdiv_q obj);
+  inline isl::checked::ctx ctx() const;
 
-  inline union_map get_map() const;
-  inline schedule_node get_root() const;
-  inline schedule pullback(union_pw_multi_aff upma) const;
 };
 
-// declarations for isl::schedule_constraints
-inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
-inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
-
-class schedule_constraints {
-  friend inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
-  friend inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+// declarations for isl::ast_expr_op_ge
 
-  isl_schedule_constraints *ptr = nullptr;
+class ast_expr_op_ge : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_ge ast_expr_op::as<ast_expr_op_ge>() const;
+  static const auto type = isl_ast_expr_op_ge;
 
-  inline explicit schedule_constraints(__isl_take isl_schedule_constraints *ptr);
+protected:
+  inline explicit ast_expr_op_ge(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ schedule_constraints();
-  inline /* implicit */ schedule_constraints(const schedule_constraints &obj);
-  inline explicit schedule_constraints(ctx ctx, const std::string &str);
-  inline schedule_constraints &operator=(schedule_constraints obj);
-  inline ~schedule_constraints();
-  inline __isl_give isl_schedule_constraints *copy() const &;
-  inline __isl_give isl_schedule_constraints *copy() && = delete;
-  inline __isl_keep isl_schedule_constraints *get() const;
-  inline __isl_give isl_schedule_constraints *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline schedule compute_schedule() const;
-  inline union_map get_coincidence() const;
-  inline union_map get_conditional_validity() const;
-  inline union_map get_conditional_validity_condition() const;
-  inline set get_context() const;
-  inline union_set get_domain() const;
-  inline union_map get_proximity() const;
-  inline union_map get_validity() const;
-  static inline schedule_constraints on_domain(union_set domain);
-  inline schedule_constraints set_coincidence(union_map coincidence) const;
-  inline schedule_constraints set_conditional_validity(union_map condition, union_map validity) const;
-  inline schedule_constraints set_context(set context) const;
-  inline schedule_constraints set_proximity(union_map proximity) const;
-  inline schedule_constraints set_validity(union_map validity) const;
-};
+  inline /* implicit */ ast_expr_op_ge();
+  inline /* implicit */ ast_expr_op_ge(const ast_expr_op_ge &obj);
+  inline ast_expr_op_ge &operator=(ast_expr_op_ge obj);
+  inline isl::checked::ctx ctx() const;
 
-// declarations for isl::schedule_node
-inline schedule_node manage(__isl_take isl_schedule_node *ptr);
-inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+};
 
-class schedule_node {
-  friend inline schedule_node manage(__isl_take isl_schedule_node *ptr);
-  friend inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+// declarations for isl::ast_expr_op_gt
 
-  isl_schedule_node *ptr = nullptr;
+class ast_expr_op_gt : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_gt ast_expr_op::as<ast_expr_op_gt>() const;
+  static const auto type = isl_ast_expr_op_gt;
 
-  inline explicit schedule_node(__isl_take isl_schedule_node *ptr);
+protected:
+  inline explicit ast_expr_op_gt(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ schedule_node();
-  inline /* implicit */ schedule_node(const schedule_node &obj);
-  inline schedule_node &operator=(schedule_node obj);
-  inline ~schedule_node();
-  inline __isl_give isl_schedule_node *copy() const &;
-  inline __isl_give isl_schedule_node *copy() && = delete;
-  inline __isl_keep isl_schedule_node *get() const;
-  inline __isl_give isl_schedule_node *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline boolean band_member_get_coincident(int pos) const;
-  inline schedule_node band_member_set_coincident(int pos, int coincident) const;
-  inline schedule_node child(int pos) const;
-  inline multi_union_pw_aff get_prefix_schedule_multi_union_pw_aff() const;
-  inline union_map get_prefix_schedule_union_map() const;
-  inline union_pw_multi_aff get_prefix_schedule_union_pw_multi_aff() const;
-  inline schedule get_schedule() const;
-  inline schedule_node parent() const;
+  inline /* implicit */ ast_expr_op_gt();
+  inline /* implicit */ ast_expr_op_gt(const ast_expr_op_gt &obj);
+  inline ast_expr_op_gt &operator=(ast_expr_op_gt obj);
+  inline isl::checked::ctx ctx() const;
+
 };
 
-// declarations for isl::set
-inline set manage(__isl_take isl_set *ptr);
-inline set manage_copy(__isl_keep isl_set *ptr);
+// declarations for isl::ast_expr_op_le
 
-class set {
-  friend inline set manage(__isl_take isl_set *ptr);
-  friend inline set manage_copy(__isl_keep isl_set *ptr);
+class ast_expr_op_le : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_le ast_expr_op::as<ast_expr_op_le>() const;
+  static const auto type = isl_ast_expr_op_le;
 
-  isl_set *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_le(__isl_take isl_ast_expr *ptr);
 
-  inline explicit set(__isl_take isl_set *ptr);
+public:
+  inline /* implicit */ ast_expr_op_le();
+  inline /* implicit */ ast_expr_op_le(const ast_expr_op_le &obj);
+  inline ast_expr_op_le &operator=(ast_expr_op_le obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_lt
+
+class ast_expr_op_lt : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_lt ast_expr_op::as<ast_expr_op_lt>() const;
+  static const auto type = isl_ast_expr_op_lt;
+
+protected:
+  inline explicit ast_expr_op_lt(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ set();
-  inline /* implicit */ set(const set &obj);
-  inline explicit set(ctx ctx, const std::string &str);
-  inline /* implicit */ set(basic_set bset);
-  inline /* implicit */ set(point pnt);
-  inline set &operator=(set obj);
-  inline ~set();
-  inline __isl_give isl_set *copy() const &;
-  inline __isl_give isl_set *copy() && = delete;
-  inline __isl_keep isl_set *get() const;
-  inline __isl_give isl_set *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_set affine_hull() const;
-  inline set apply(map map) const;
-  inline set coalesce() const;
-  inline set complement() const;
-  inline set detect_equalities() const;
-  inline set flatten() const;
-  inline stat foreach_basic_set(const std::function<stat(basic_set)> &fn) const;
-  inline val get_stride(int pos) const;
-  inline set gist(set context) const;
-  inline map identity() const;
-  inline set intersect(set set2) const;
-  inline set intersect_params(set params) const;
-  inline boolean is_disjoint(const set &set2) const;
-  inline boolean is_empty() const;
-  inline boolean is_equal(const set &set2) const;
-  inline boolean is_strict_subset(const set &set2) const;
-  inline boolean is_subset(const set &set2) const;
-  inline boolean is_wrapping() const;
-  inline set lexmax() const;
-  inline set lexmin() const;
-  inline val max_val(const aff &obj) const;
-  inline val min_val(const aff &obj) const;
-  inline basic_set polyhedral_hull() const;
-  inline basic_set sample() const;
-  inline point sample_point() const;
-  inline set subtract(set set2) const;
-  inline set unite(set set2) const;
-  inline basic_set unshifted_simple_hull() const;
+  inline /* implicit */ ast_expr_op_lt();
+  inline /* implicit */ ast_expr_op_lt(const ast_expr_op_lt &obj);
+  inline ast_expr_op_lt &operator=(ast_expr_op_lt obj);
+  inline isl::checked::ctx ctx() const;
+
 };
 
-// declarations for isl::union_access_info
-inline union_access_info manage(__isl_take isl_union_access_info *ptr);
-inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+// declarations for isl::ast_expr_op_max
 
-class union_access_info {
-  friend inline union_access_info manage(__isl_take isl_union_access_info *ptr);
-  friend inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+class ast_expr_op_max : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_max ast_expr_op::as<ast_expr_op_max>() const;
+  static const auto type = isl_ast_expr_op_max;
 
-  isl_union_access_info *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_max(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_access_info(__isl_take isl_union_access_info *ptr);
+public:
+  inline /* implicit */ ast_expr_op_max();
+  inline /* implicit */ ast_expr_op_max(const ast_expr_op_max &obj);
+  inline ast_expr_op_max &operator=(ast_expr_op_max obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_member
+
+class ast_expr_op_member : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_member ast_expr_op::as<ast_expr_op_member>() const;
+  static const auto type = isl_ast_expr_op_member;
+
+protected:
+  inline explicit ast_expr_op_member(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_access_info();
-  inline /* implicit */ union_access_info(const union_access_info &obj);
-  inline explicit union_access_info(union_map sink);
-  inline union_access_info &operator=(union_access_info obj);
-  inline ~union_access_info();
-  inline __isl_give isl_union_access_info *copy() const &;
-  inline __isl_give isl_union_access_info *copy() && = delete;
-  inline __isl_keep isl_union_access_info *get() const;
-  inline __isl_give isl_union_access_info *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_flow compute_flow() const;
-  inline union_access_info set_kill(union_map kill) const;
-  inline union_access_info set_may_source(union_map may_source) const;
-  inline union_access_info set_must_source(union_map must_source) const;
-  inline union_access_info set_schedule(schedule schedule) const;
-  inline union_access_info set_schedule_map(union_map schedule_map) const;
+  inline /* implicit */ ast_expr_op_member();
+  inline /* implicit */ ast_expr_op_member(const ast_expr_op_member &obj);
+  inline ast_expr_op_member &operator=(ast_expr_op_member obj);
+  inline isl::checked::ctx ctx() const;
+
 };
 
-// declarations for isl::union_flow
-inline union_flow manage(__isl_take isl_union_flow *ptr);
-inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+// declarations for isl::ast_expr_op_min
 
-class union_flow {
-  friend inline union_flow manage(__isl_take isl_union_flow *ptr);
-  friend inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+class ast_expr_op_min : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_min ast_expr_op::as<ast_expr_op_min>() const;
+  static const auto type = isl_ast_expr_op_min;
 
-  isl_union_flow *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_min(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_flow(__isl_take isl_union_flow *ptr);
+public:
+  inline /* implicit */ ast_expr_op_min();
+  inline /* implicit */ ast_expr_op_min(const ast_expr_op_min &obj);
+  inline ast_expr_op_min &operator=(ast_expr_op_min obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_minus
+
+class ast_expr_op_minus : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_minus ast_expr_op::as<ast_expr_op_minus>() const;
+  static const auto type = isl_ast_expr_op_minus;
+
+protected:
+  inline explicit ast_expr_op_minus(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_flow();
-  inline /* implicit */ union_flow(const union_flow &obj);
-  inline union_flow &operator=(union_flow obj);
-  inline ~union_flow();
-  inline __isl_give isl_union_flow *copy() const &;
-  inline __isl_give isl_union_flow *copy() && = delete;
-  inline __isl_keep isl_union_flow *get() const;
-  inline __isl_give isl_union_flow *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_map get_full_may_dependence() const;
-  inline union_map get_full_must_dependence() const;
-  inline union_map get_may_dependence() const;
-  inline union_map get_may_no_source() const;
-  inline union_map get_must_dependence() const;
-  inline union_map get_must_no_source() const;
+  inline /* implicit */ ast_expr_op_minus();
+  inline /* implicit */ ast_expr_op_minus(const ast_expr_op_minus &obj);
+  inline ast_expr_op_minus &operator=(ast_expr_op_minus obj);
+  inline isl::checked::ctx ctx() const;
+
 };
 
-// declarations for isl::union_map
-inline union_map manage(__isl_take isl_union_map *ptr);
-inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+// declarations for isl::ast_expr_op_mul
 
-class union_map {
-  friend inline union_map manage(__isl_take isl_union_map *ptr);
-  friend inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+class ast_expr_op_mul : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_mul ast_expr_op::as<ast_expr_op_mul>() const;
+  static const auto type = isl_ast_expr_op_mul;
 
-  isl_union_map *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_mul(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_map(__isl_take isl_union_map *ptr);
+public:
+  inline /* implicit */ ast_expr_op_mul();
+  inline /* implicit */ ast_expr_op_mul(const ast_expr_op_mul &obj);
+  inline ast_expr_op_mul &operator=(ast_expr_op_mul obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_or
+
+class ast_expr_op_or : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_or ast_expr_op::as<ast_expr_op_or>() const;
+  static const auto type = isl_ast_expr_op_or;
+
+protected:
+  inline explicit ast_expr_op_or(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_map();
-  inline /* implicit */ union_map(const union_map &obj);
-  inline /* implicit */ union_map(basic_map bmap);
-  inline /* implicit */ union_map(map map);
-  inline explicit union_map(ctx ctx, const std::string &str);
-  inline union_map &operator=(union_map obj);
-  inline ~union_map();
-  inline __isl_give isl_union_map *copy() const &;
-  inline __isl_give isl_union_map *copy() && = delete;
-  inline __isl_keep isl_union_map *get() const;
-  inline __isl_give isl_union_map *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_map affine_hull() const;
-  inline union_map apply_domain(union_map umap2) const;
-  inline union_map apply_range(union_map umap2) const;
-  inline union_map coalesce() const;
-  inline union_map compute_divs() const;
-  inline union_set deltas() const;
-  inline union_map detect_equalities() const;
-  inline union_set domain() const;
-  inline union_map domain_factor_domain() const;
-  inline union_map domain_factor_range() const;
-  inline union_map domain_map() const;
-  inline union_pw_multi_aff domain_map_union_pw_multi_aff() const;
-  inline union_map domain_product(union_map umap2) const;
-  inline union_map eq_at(multi_union_pw_aff mupa) const;
-  inline union_map factor_domain() const;
-  inline union_map factor_range() const;
-  inline union_map fixed_power(val exp) const;
-  inline stat foreach_map(const std::function<stat(map)> &fn) const;
-  static inline union_map from(union_pw_multi_aff upma);
-  static inline union_map from(multi_union_pw_aff mupa);
-  static inline union_map from_domain(union_set uset);
-  static inline union_map from_domain_and_range(union_set domain, union_set range);
-  static inline union_map from_range(union_set uset);
-  inline union_map gist(union_map context) const;
-  inline union_map gist_domain(union_set uset) const;
-  inline union_map gist_params(set set) const;
-  inline union_map gist_range(union_set uset) const;
-  inline union_map intersect(union_map umap2) const;
-  inline union_map intersect_domain(union_set uset) const;
-  inline union_map intersect_params(set set) const;
-  inline union_map intersect_range(union_set uset) const;
-  inline boolean is_bijective() const;
-  inline boolean is_empty() const;
-  inline boolean is_equal(const union_map &umap2) const;
-  inline boolean is_injective() const;
-  inline boolean is_single_valued() const;
-  inline boolean is_strict_subset(const union_map &umap2) const;
-  inline boolean is_subset(const union_map &umap2) const;
-  inline union_map lexmax() const;
-  inline union_map lexmin() const;
-  inline union_map polyhedral_hull() const;
-  inline union_map product(union_map umap2) const;
-  inline union_map project_out_all_params() const;
-  inline union_set range() const;
-  inline union_map range_factor_domain() const;
-  inline union_map range_factor_range() const;
-  inline union_map range_map() const;
-  inline union_map range_product(union_map umap2) const;
-  inline union_map reverse() const;
-  inline union_map subtract(union_map umap2) const;
-  inline union_map subtract_domain(union_set dom) const;
-  inline union_map subtract_range(union_set dom) const;
-  inline union_map unite(union_map umap2) const;
-  inline union_set wrap() const;
-  inline union_map zip() const;
+  inline /* implicit */ ast_expr_op_or();
+  inline /* implicit */ ast_expr_op_or(const ast_expr_op_or &obj);
+  inline ast_expr_op_or &operator=(ast_expr_op_or obj);
+  inline isl::checked::ctx ctx() const;
+
 };
 
-// declarations for isl::union_pw_aff
-inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
-inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+// declarations for isl::ast_expr_op_or_else
 
-class union_pw_aff {
-  friend inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
-  friend inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+class ast_expr_op_or_else : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_or_else ast_expr_op::as<ast_expr_op_or_else>() const;
+  static const auto type = isl_ast_expr_op_or_else;
 
-  isl_union_pw_aff *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_or_else(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_pw_aff(__isl_take isl_union_pw_aff *ptr);
+public:
+  inline /* implicit */ ast_expr_op_or_else();
+  inline /* implicit */ ast_expr_op_or_else(const ast_expr_op_or_else &obj);
+  inline ast_expr_op_or_else &operator=(ast_expr_op_or_else obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_pdiv_q
+
+class ast_expr_op_pdiv_q : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_pdiv_q ast_expr_op::as<ast_expr_op_pdiv_q>() const;
+  static const auto type = isl_ast_expr_op_pdiv_q;
+
+protected:
+  inline explicit ast_expr_op_pdiv_q(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_pw_aff();
-  inline /* implicit */ union_pw_aff(const union_pw_aff &obj);
-  inline /* implicit */ union_pw_aff(pw_aff pa);
-  inline explicit union_pw_aff(ctx ctx, const std::string &str);
-  inline union_pw_aff &operator=(union_pw_aff obj);
-  inline ~union_pw_aff();
-  inline __isl_give isl_union_pw_aff *copy() const &;
-  inline __isl_give isl_union_pw_aff *copy() && = delete;
-  inline __isl_keep isl_union_pw_aff *get() const;
-  inline __isl_give isl_union_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_pdiv_q();
+  inline /* implicit */ ast_expr_op_pdiv_q(const ast_expr_op_pdiv_q &obj);
+  inline ast_expr_op_pdiv_q &operator=(ast_expr_op_pdiv_q obj);
+  inline isl::checked::ctx ctx() const;
 
-  inline union_pw_aff add(union_pw_aff upa2) const;
-  inline union_pw_aff pullback(union_pw_multi_aff upma) const;
-  inline union_pw_aff union_add(union_pw_aff upa2) const;
 };
 
-// declarations for isl::union_pw_multi_aff
-inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
-inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+// declarations for isl::ast_expr_op_pdiv_r
 
-class union_pw_multi_aff {
-  friend inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
-  friend inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+class ast_expr_op_pdiv_r : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_pdiv_r ast_expr_op::as<ast_expr_op_pdiv_r>() const;
+  static const auto type = isl_ast_expr_op_pdiv_r;
 
-  isl_union_pw_multi_aff *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_pdiv_r(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr);
+public:
+  inline /* implicit */ ast_expr_op_pdiv_r();
+  inline /* implicit */ ast_expr_op_pdiv_r(const ast_expr_op_pdiv_r &obj);
+  inline ast_expr_op_pdiv_r &operator=(ast_expr_op_pdiv_r obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_select
+
+class ast_expr_op_select : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_select ast_expr_op::as<ast_expr_op_select>() const;
+  static const auto type = isl_ast_expr_op_select;
+
+protected:
+  inline explicit ast_expr_op_select(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_pw_multi_aff();
-  inline /* implicit */ union_pw_multi_aff(const union_pw_multi_aff &obj);
-  inline /* implicit */ union_pw_multi_aff(pw_multi_aff pma);
-  inline explicit union_pw_multi_aff(ctx ctx, const std::string &str);
-  inline /* implicit */ union_pw_multi_aff(union_pw_aff upa);
-  inline union_pw_multi_aff &operator=(union_pw_multi_aff obj);
-  inline ~union_pw_multi_aff();
-  inline __isl_give isl_union_pw_multi_aff *copy() const &;
-  inline __isl_give isl_union_pw_multi_aff *copy() && = delete;
-  inline __isl_keep isl_union_pw_multi_aff *get() const;
-  inline __isl_give isl_union_pw_multi_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_select();
+  inline /* implicit */ ast_expr_op_select(const ast_expr_op_select &obj);
+  inline ast_expr_op_select &operator=(ast_expr_op_select obj);
+  inline isl::checked::ctx ctx() const;
 
-  inline union_pw_multi_aff add(union_pw_multi_aff upma2) const;
-  inline union_pw_multi_aff flat_range_product(union_pw_multi_aff upma2) const;
-  inline union_pw_multi_aff pullback(union_pw_multi_aff upma2) const;
-  inline union_pw_multi_aff union_add(union_pw_multi_aff upma2) const;
 };
 
-// declarations for isl::union_set
-inline union_set manage(__isl_take isl_union_set *ptr);
-inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+// declarations for isl::ast_expr_op_sub
 
-class union_set {
-  friend inline union_set manage(__isl_take isl_union_set *ptr);
-  friend inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+class ast_expr_op_sub : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_sub ast_expr_op::as<ast_expr_op_sub>() const;
+  static const auto type = isl_ast_expr_op_sub;
 
-  isl_union_set *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_sub(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_set(__isl_take isl_union_set *ptr);
+public:
+  inline /* implicit */ ast_expr_op_sub();
+  inline /* implicit */ ast_expr_op_sub(const ast_expr_op_sub &obj);
+  inline ast_expr_op_sub &operator=(ast_expr_op_sub obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_zdiv_r
+
+class ast_expr_op_zdiv_r : public ast_expr_op {
+  template <class T>
+  friend boolean ast_expr_op::isa() const;
+  friend ast_expr_op_zdiv_r ast_expr_op::as<ast_expr_op_zdiv_r>() const;
+  static const auto type = isl_ast_expr_op_zdiv_r;
+
+protected:
+  inline explicit ast_expr_op_zdiv_r(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_set();
-  inline /* implicit */ union_set(const union_set &obj);
-  inline /* implicit */ union_set(basic_set bset);
-  inline /* implicit */ union_set(set set);
-  inline /* implicit */ union_set(point pnt);
-  inline explicit union_set(ctx ctx, const std::string &str);
-  inline union_set &operator=(union_set obj);
-  inline ~union_set();
-  inline __isl_give isl_union_set *copy() const &;
-  inline __isl_give isl_union_set *copy() && = delete;
-  inline __isl_keep isl_union_set *get() const;
-  inline __isl_give isl_union_set *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_set affine_hull() const;
-  inline union_set apply(union_map umap) const;
-  inline union_set coalesce() const;
-  inline union_set compute_divs() const;
-  inline union_set detect_equalities() const;
-  inline stat foreach_point(const std::function<stat(point)> &fn) const;
-  inline stat foreach_set(const std::function<stat(set)> &fn) const;
-  inline union_set gist(union_set context) const;
-  inline union_set gist_params(set set) const;
-  inline union_map identity() const;
-  inline union_set intersect(union_set uset2) const;
-  inline union_set intersect_params(set set) const;
-  inline boolean is_empty() const;
-  inline boolean is_equal(const union_set &uset2) const;
-  inline boolean is_strict_subset(const union_set &uset2) const;
-  inline boolean is_subset(const union_set &uset2) const;
-  inline union_set lexmax() const;
-  inline union_set lexmin() const;
-  inline union_set polyhedral_hull() const;
-  inline union_set preimage(multi_aff ma) const;
-  inline union_set preimage(pw_multi_aff pma) const;
-  inline union_set preimage(union_pw_multi_aff upma) const;
-  inline point sample_point() const;
-  inline union_set subtract(union_set uset2) const;
-  inline union_set unite(union_set uset2) const;
-  inline union_map unwrap() const;
+  inline /* implicit */ ast_expr_op_zdiv_r();
+  inline /* implicit */ ast_expr_op_zdiv_r(const ast_expr_op_zdiv_r &obj);
+  inline ast_expr_op_zdiv_r &operator=(ast_expr_op_zdiv_r obj);
+  inline isl::checked::ctx ctx() const;
+
 };
 
-// declarations for isl::val
-inline val manage(__isl_take isl_val *ptr);
-inline val manage_copy(__isl_keep isl_val *ptr);
+// declarations for isl::ast_node
+inline ast_node manage(__isl_take isl_ast_node *ptr);
+inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
 
-class val {
-  friend inline val manage(__isl_take isl_val *ptr);
-  friend inline val manage_copy(__isl_keep isl_val *ptr);
+class ast_node {
+  friend inline ast_node manage(__isl_take isl_ast_node *ptr);
+  friend inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
 
-  isl_val *ptr = nullptr;
+protected:
+  isl_ast_node *ptr = nullptr;
 
-  inline explicit val(__isl_take isl_val *ptr);
+  inline explicit ast_node(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node();
+  inline /* implicit */ ast_node(const ast_node &obj);
+  inline ast_node &operator=(ast_node obj);
+  inline ~ast_node();
+  inline __isl_give isl_ast_node *copy() const &;
+  inline __isl_give isl_ast_node *copy() && = delete;
+  inline __isl_keep isl_ast_node *get() const;
+  inline __isl_give isl_ast_node *release();
+  inline bool is_null() const;
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_ast_node_get_type(NULL)),
+                  const T>::value>::type>
+  inline boolean isa_type(T subtype) const;
+public:
+  template <class T> inline boolean isa() const;
+  template <class T> inline T as() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline std::string to_C_str() const;
+};
+
+// declarations for isl::ast_node_block
+
+class ast_node_block : public ast_node {
+  template <class T>
+  friend boolean ast_node::isa() const;
+  friend ast_node_block ast_node::as<ast_node_block>() const;
+  static const auto type = isl_ast_node_block;
+
+protected:
+  inline explicit ast_node_block(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_block();
+  inline /* implicit */ ast_node_block(const ast_node_block &obj);
+  inline ast_node_block &operator=(ast_node_block obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::ast_node_list children() const;
+  inline isl::checked::ast_node_list get_children() const;
+};
+
+// declarations for isl::ast_node_for
+
+class ast_node_for : public ast_node {
+  template <class T>
+  friend boolean ast_node::isa() const;
+  friend ast_node_for ast_node::as<ast_node_for>() const;
+  static const auto type = isl_ast_node_for;
+
+protected:
+  inline explicit ast_node_for(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_for();
+  inline /* implicit */ ast_node_for(const ast_node_for &obj);
+  inline ast_node_for &operator=(ast_node_for obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::ast_node body() const;
+  inline isl::checked::ast_node get_body() const;
+  inline isl::checked::ast_expr cond() const;
+  inline isl::checked::ast_expr get_cond() const;
+  inline isl::checked::ast_expr inc() const;
+  inline isl::checked::ast_expr get_inc() const;
+  inline isl::checked::ast_expr init() const;
+  inline isl::checked::ast_expr get_init() const;
+  inline isl::checked::ast_expr iterator() const;
+  inline isl::checked::ast_expr get_iterator() const;
+  inline boolean is_degenerate() const;
+};
+
+// declarations for isl::ast_node_if
+
+class ast_node_if : public ast_node {
+  template <class T>
+  friend boolean ast_node::isa() const;
+  friend ast_node_if ast_node::as<ast_node_if>() const;
+  static const auto type = isl_ast_node_if;
+
+protected:
+  inline explicit ast_node_if(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_if();
+  inline /* implicit */ ast_node_if(const ast_node_if &obj);
+  inline ast_node_if &operator=(ast_node_if obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::ast_expr cond() const;
+  inline isl::checked::ast_expr get_cond() const;
+  inline isl::checked::ast_node else_node() const;
+  inline isl::checked::ast_node get_else_node() const;
+  inline isl::checked::ast_node then_node() const;
+  inline isl::checked::ast_node get_then_node() const;
+  inline boolean has_else_node() const;
+};
+
+// declarations for isl::ast_node_list
+inline ast_node_list manage(__isl_take isl_ast_node_list *ptr);
+inline ast_node_list manage_copy(__isl_keep isl_ast_node_list *ptr);
+
+class ast_node_list {
+  friend inline ast_node_list manage(__isl_take isl_ast_node_list *ptr);
+  friend inline ast_node_list manage_copy(__isl_keep isl_ast_node_list *ptr);
+
+protected:
+  isl_ast_node_list *ptr = nullptr;
+
+  inline explicit ast_node_list(__isl_take isl_ast_node_list *ptr);
+
+public:
+  inline /* implicit */ ast_node_list();
+  inline /* implicit */ ast_node_list(const ast_node_list &obj);
+  inline explicit ast_node_list(isl::checked::ctx ctx, int n);
+  inline explicit ast_node_list(isl::checked::ast_node el);
+  inline ast_node_list &operator=(ast_node_list obj);
+  inline ~ast_node_list();
+  inline __isl_give isl_ast_node_list *copy() const &;
+  inline __isl_give isl_ast_node_list *copy() && = delete;
+  inline __isl_keep isl_ast_node_list *get() const;
+  inline __isl_give isl_ast_node_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::ast_node_list add(isl::checked::ast_node el) const;
+  inline isl::checked::ast_node_list clear() const;
+  inline isl::checked::ast_node_list concat(isl::checked::ast_node_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::ast_node)> &fn) const;
+  inline isl::checked::ast_node at(int index) const;
+  inline isl::checked::ast_node get_at(int index) const;
+  inline class size size() const;
+};
+
+// declarations for isl::ast_node_mark
+
+class ast_node_mark : public ast_node {
+  template <class T>
+  friend boolean ast_node::isa() const;
+  friend ast_node_mark ast_node::as<ast_node_mark>() const;
+  static const auto type = isl_ast_node_mark;
+
+protected:
+  inline explicit ast_node_mark(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_mark();
+  inline /* implicit */ ast_node_mark(const ast_node_mark &obj);
+  inline ast_node_mark &operator=(ast_node_mark obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::id id() const;
+  inline isl::checked::id get_id() const;
+  inline isl::checked::ast_node node() const;
+  inline isl::checked::ast_node get_node() const;
+};
+
+// declarations for isl::ast_node_user
+
+class ast_node_user : public ast_node {
+  template <class T>
+  friend boolean ast_node::isa() const;
+  friend ast_node_user ast_node::as<ast_node_user>() const;
+  static const auto type = isl_ast_node_user;
+
+protected:
+  inline explicit ast_node_user(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_user();
+  inline /* implicit */ ast_node_user(const ast_node_user &obj);
+  inline ast_node_user &operator=(ast_node_user obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::ast_expr expr() const;
+  inline isl::checked::ast_expr get_expr() const;
+};
+
+// declarations for isl::basic_map
+inline basic_map manage(__isl_take isl_basic_map *ptr);
+inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+class basic_map {
+  friend inline basic_map manage(__isl_take isl_basic_map *ptr);
+  friend inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+protected:
+  isl_basic_map *ptr = nullptr;
+
+  inline explicit basic_map(__isl_take isl_basic_map *ptr);
+
+public:
+  inline /* implicit */ basic_map();
+  inline /* implicit */ basic_map(const basic_map &obj);
+  inline explicit basic_map(isl::checked::ctx ctx, const std::string &str);
+  inline basic_map &operator=(basic_map obj);
+  inline ~basic_map();
+  inline __isl_give isl_basic_map *copy() const &;
+  inline __isl_give isl_basic_map *copy() && = delete;
+  inline __isl_keep isl_basic_map *get() const;
+  inline __isl_give isl_basic_map *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::basic_map affine_hull() const;
+  inline isl::checked::basic_map apply_domain(isl::checked::basic_map bmap2) const;
+  inline isl::checked::basic_map apply_range(isl::checked::basic_map bmap2) const;
+  inline isl::checked::basic_set deltas() const;
+  inline isl::checked::basic_map detect_equalities() const;
+  inline isl::checked::basic_map flatten() const;
+  inline isl::checked::basic_map flatten_domain() const;
+  inline isl::checked::basic_map flatten_range() const;
+  inline isl::checked::basic_map gist(isl::checked::basic_map context) const;
+  inline isl::checked::basic_map intersect(isl::checked::basic_map bmap2) const;
+  inline isl::checked::basic_map intersect_domain(isl::checked::basic_set bset) const;
+  inline isl::checked::basic_map intersect_range(isl::checked::basic_set bset) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const isl::checked::basic_map &bmap2) const;
+  inline boolean is_subset(const isl::checked::basic_map &bmap2) const;
+  inline isl::checked::map lexmax() const;
+  inline isl::checked::map lexmin() const;
+  inline isl::checked::basic_map reverse() const;
+  inline isl::checked::basic_map sample() const;
+  inline isl::checked::map unite(isl::checked::basic_map bmap2) const;
+};
+
+// declarations for isl::basic_set
+inline basic_set manage(__isl_take isl_basic_set *ptr);
+inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+class basic_set {
+  friend inline basic_set manage(__isl_take isl_basic_set *ptr);
+  friend inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+protected:
+  isl_basic_set *ptr = nullptr;
+
+  inline explicit basic_set(__isl_take isl_basic_set *ptr);
+
+public:
+  inline /* implicit */ basic_set();
+  inline /* implicit */ basic_set(const basic_set &obj);
+  inline /* implicit */ basic_set(isl::checked::point pnt);
+  inline explicit basic_set(isl::checked::ctx ctx, const std::string &str);
+  inline basic_set &operator=(basic_set obj);
+  inline ~basic_set();
+  inline __isl_give isl_basic_set *copy() const &;
+  inline __isl_give isl_basic_set *copy() && = delete;
+  inline __isl_keep isl_basic_set *get() const;
+  inline __isl_give isl_basic_set *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::basic_set affine_hull() const;
+  inline isl::checked::basic_set apply(isl::checked::basic_map bmap) const;
+  inline isl::checked::basic_set detect_equalities() const;
+  inline isl::checked::val dim_max_val(int pos) const;
+  inline isl::checked::basic_set flatten() const;
+  inline isl::checked::basic_set gist(isl::checked::basic_set context) const;
+  inline isl::checked::basic_set intersect(isl::checked::basic_set bset2) const;
+  inline isl::checked::basic_set intersect_params(isl::checked::basic_set bset2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const isl::checked::basic_set &bset2) const;
+  inline boolean is_subset(const isl::checked::basic_set &bset2) const;
+  inline boolean is_wrapping() const;
+  inline isl::checked::set lexmax() const;
+  inline isl::checked::set lexmin() const;
+  inline isl::checked::basic_set params() const;
+  inline isl::checked::basic_set sample() const;
+  inline isl::checked::point sample_point() const;
+  inline isl::checked::set unite(isl::checked::basic_set bset2) const;
+};
+
+// declarations for isl::fixed_box
+inline fixed_box manage(__isl_take isl_fixed_box *ptr);
+inline fixed_box manage_copy(__isl_keep isl_fixed_box *ptr);
+
+class fixed_box {
+  friend inline fixed_box manage(__isl_take isl_fixed_box *ptr);
+  friend inline fixed_box manage_copy(__isl_keep isl_fixed_box *ptr);
+
+protected:
+  isl_fixed_box *ptr = nullptr;
+
+  inline explicit fixed_box(__isl_take isl_fixed_box *ptr);
+
+public:
+  inline /* implicit */ fixed_box();
+  inline /* implicit */ fixed_box(const fixed_box &obj);
+  inline fixed_box &operator=(fixed_box obj);
+  inline ~fixed_box();
+  inline __isl_give isl_fixed_box *copy() const &;
+  inline __isl_give isl_fixed_box *copy() && = delete;
+  inline __isl_keep isl_fixed_box *get() const;
+  inline __isl_give isl_fixed_box *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::multi_aff offset() const;
+  inline isl::checked::multi_aff get_offset() const;
+  inline isl::checked::multi_val size() const;
+  inline isl::checked::multi_val get_size() const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline boolean is_valid() const;
+};
+
+// declarations for isl::id
+inline id manage(__isl_take isl_id *ptr);
+inline id manage_copy(__isl_keep isl_id *ptr);
+
+class id {
+  friend inline id manage(__isl_take isl_id *ptr);
+  friend inline id manage_copy(__isl_keep isl_id *ptr);
+
+protected:
+  isl_id *ptr = nullptr;
+
+  inline explicit id(__isl_take isl_id *ptr);
+
+public:
+  inline /* implicit */ id();
+  inline /* implicit */ id(const id &obj);
+  inline explicit id(isl::checked::ctx ctx, const std::string &str);
+  inline id &operator=(id obj);
+  inline ~id();
+  inline __isl_give isl_id *copy() const &;
+  inline __isl_give isl_id *copy() && = delete;
+  inline __isl_keep isl_id *get() const;
+  inline __isl_give isl_id *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline std::string name() const;
+  inline std::string get_name() const;
+};
+
+// declarations for isl::id_list
+inline id_list manage(__isl_take isl_id_list *ptr);
+inline id_list manage_copy(__isl_keep isl_id_list *ptr);
+
+class id_list {
+  friend inline id_list manage(__isl_take isl_id_list *ptr);
+  friend inline id_list manage_copy(__isl_keep isl_id_list *ptr);
+
+protected:
+  isl_id_list *ptr = nullptr;
+
+  inline explicit id_list(__isl_take isl_id_list *ptr);
+
+public:
+  inline /* implicit */ id_list();
+  inline /* implicit */ id_list(const id_list &obj);
+  inline explicit id_list(isl::checked::ctx ctx, int n);
+  inline explicit id_list(isl::checked::id el);
+  inline id_list &operator=(id_list obj);
+  inline ~id_list();
+  inline __isl_give isl_id_list *copy() const &;
+  inline __isl_give isl_id_list *copy() && = delete;
+  inline __isl_keep isl_id_list *get() const;
+  inline __isl_give isl_id_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::id_list add(isl::checked::id el) const;
+  inline isl::checked::id_list add(const std::string &el) const;
+  inline isl::checked::id_list clear() const;
+  inline isl::checked::id_list concat(isl::checked::id_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::id)> &fn) const;
+  inline isl::checked::id at(int index) const;
+  inline isl::checked::id get_at(int index) const;
+  inline class size size() const;
+};
+
+// declarations for isl::map
+inline map manage(__isl_take isl_map *ptr);
+inline map manage_copy(__isl_keep isl_map *ptr);
+
+class map {
+  friend inline map manage(__isl_take isl_map *ptr);
+  friend inline map manage_copy(__isl_keep isl_map *ptr);
+
+protected:
+  isl_map *ptr = nullptr;
+
+  inline explicit map(__isl_take isl_map *ptr);
+
+public:
+  inline /* implicit */ map();
+  inline /* implicit */ map(const map &obj);
+  inline /* implicit */ map(isl::checked::basic_map bmap);
+  inline explicit map(isl::checked::ctx ctx, const std::string &str);
+  inline map &operator=(map obj);
+  inline ~map();
+  inline __isl_give isl_map *copy() const &;
+  inline __isl_give isl_map *copy() && = delete;
+  inline __isl_keep isl_map *get() const;
+  inline __isl_give isl_map *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::basic_map affine_hull() const;
+  inline isl::checked::map apply_domain(isl::checked::map map2) const;
+  inline isl::checked::map apply_range(isl::checked::map map2) const;
+  inline isl::checked::set bind_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::set bind_range(isl::checked::multi_id tuple) const;
+  inline isl::checked::map coalesce() const;
+  inline isl::checked::map complement() const;
+  inline isl::checked::map curry() const;
+  inline isl::checked::set deltas() const;
+  inline isl::checked::map detect_equalities() const;
+  inline isl::checked::set domain() const;
+  inline isl::checked::map domain_factor_domain() const;
+  inline isl::checked::map domain_factor_range() const;
+  inline isl::checked::map domain_product(isl::checked::map map2) const;
+  static inline isl::checked::map empty(isl::checked::space space);
+  inline isl::checked::map factor_domain() const;
+  inline isl::checked::map factor_range() const;
+  inline isl::checked::map flatten() const;
+  inline isl::checked::map flatten_domain() const;
+  inline isl::checked::map flatten_range() const;
+  inline stat foreach_basic_map(const std::function<stat(isl::checked::basic_map)> &fn) const;
+  inline isl::checked::fixed_box range_simple_fixed_box_hull() const;
+  inline isl::checked::fixed_box get_range_simple_fixed_box_hull() const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::map gist(isl::checked::map context) const;
+  inline isl::checked::map gist_domain(isl::checked::set context) const;
+  inline isl::checked::map intersect(isl::checked::map map2) const;
+  inline isl::checked::map intersect_domain(isl::checked::set set) const;
+  inline isl::checked::map intersect_params(isl::checked::set params) const;
+  inline isl::checked::map intersect_range(isl::checked::set set) const;
+  inline boolean is_bijective() const;
+  inline boolean is_disjoint(const isl::checked::map &map2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const isl::checked::map &map2) const;
+  inline boolean is_injective() const;
+  inline boolean is_single_valued() const;
+  inline boolean is_strict_subset(const isl::checked::map &map2) const;
+  inline boolean is_subset(const isl::checked::map &map2) const;
+  inline isl::checked::map lexmax() const;
+  inline isl::checked::pw_multi_aff lexmax_pw_multi_aff() const;
+  inline isl::checked::map lexmin() const;
+  inline isl::checked::pw_multi_aff lexmin_pw_multi_aff() const;
+  inline isl::checked::map lower_bound(isl::checked::multi_pw_aff lower) const;
+  inline isl::checked::map lower_bound(isl::checked::multi_val lower) const;
+  inline isl::checked::basic_map polyhedral_hull() const;
+  inline isl::checked::map preimage_domain(isl::checked::multi_aff ma) const;
+  inline isl::checked::map preimage_domain(isl::checked::multi_pw_aff mpa) const;
+  inline isl::checked::map preimage_domain(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::map preimage_range(isl::checked::multi_aff ma) const;
+  inline isl::checked::map preimage_range(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::map project_out_all_params() const;
+  inline isl::checked::set range() const;
+  inline isl::checked::map range_factor_domain() const;
+  inline isl::checked::map range_factor_range() const;
+  inline isl::checked::map range_product(isl::checked::map map2) const;
+  inline isl::checked::map range_reverse() const;
+  inline isl::checked::map reverse() const;
+  inline isl::checked::basic_map sample() const;
+  inline isl::checked::map subtract(isl::checked::map map2) const;
+  inline isl::checked::map uncurry() const;
+  inline isl::checked::map unite(isl::checked::map map2) const;
+  static inline isl::checked::map universe(isl::checked::space space);
+  inline isl::checked::basic_map unshifted_simple_hull() const;
+  inline isl::checked::map upper_bound(isl::checked::multi_pw_aff upper) const;
+  inline isl::checked::map upper_bound(isl::checked::multi_val upper) const;
+  inline isl::checked::set wrap() const;
+};
+
+// declarations for isl::multi_aff
+inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+class multi_aff {
+  friend inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+  friend inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+protected:
+  isl_multi_aff *ptr = nullptr;
+
+  inline explicit multi_aff(__isl_take isl_multi_aff *ptr);
+
+public:
+  inline /* implicit */ multi_aff();
+  inline /* implicit */ multi_aff(const multi_aff &obj);
+  inline /* implicit */ multi_aff(isl::checked::aff aff);
+  inline explicit multi_aff(isl::checked::space space, isl::checked::aff_list list);
+  inline explicit multi_aff(isl::checked::ctx ctx, const std::string &str);
+  inline multi_aff &operator=(multi_aff obj);
+  inline ~multi_aff();
+  inline __isl_give isl_multi_aff *copy() const &;
+  inline __isl_give isl_multi_aff *copy() && = delete;
+  inline __isl_keep isl_multi_aff *get() const;
+  inline __isl_give isl_multi_aff *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::multi_aff add(isl::checked::multi_aff multi2) const;
+  inline isl::checked::multi_aff add_constant(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_aff add_constant(isl::checked::val v) const;
+  inline isl::checked::multi_aff add_constant(long v) const;
+  inline isl::checked::basic_set bind(isl::checked::multi_id tuple) const;
+  inline isl::checked::multi_aff bind_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::multi_aff bind_domain_wrapped_domain(isl::checked::multi_id tuple) const;
+  static inline isl::checked::multi_aff domain_map(isl::checked::space space);
+  inline isl::checked::multi_aff flat_range_product(isl::checked::multi_aff multi2) const;
+  inline isl::checked::multi_aff floor() const;
+  inline isl::checked::aff at(int pos) const;
+  inline isl::checked::aff get_at(int pos) const;
+  inline isl::checked::multi_val constant_multi_val() const;
+  inline isl::checked::multi_val get_constant_multi_val() const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::multi_aff gist(isl::checked::set context) const;
+  inline isl::checked::multi_aff identity() const;
+  static inline isl::checked::multi_aff identity_on_domain(isl::checked::space space);
+  inline boolean involves_locals() const;
+  inline isl::checked::multi_aff neg() const;
+  inline boolean plain_is_equal(const isl::checked::multi_aff &multi2) const;
+  inline isl::checked::multi_aff product(isl::checked::multi_aff multi2) const;
+  inline isl::checked::multi_aff pullback(isl::checked::multi_aff ma2) const;
+  static inline isl::checked::multi_aff range_map(isl::checked::space space);
+  inline isl::checked::multi_aff range_product(isl::checked::multi_aff multi2) const;
+  inline isl::checked::multi_aff scale(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_aff scale(isl::checked::val v) const;
+  inline isl::checked::multi_aff scale(long v) const;
+  inline isl::checked::multi_aff scale_down(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_aff scale_down(isl::checked::val v) const;
+  inline isl::checked::multi_aff scale_down(long v) const;
+  inline isl::checked::multi_aff set_at(int pos, isl::checked::aff el) const;
+  inline class size size() const;
+  inline isl::checked::multi_aff sub(isl::checked::multi_aff multi2) const;
+  static inline isl::checked::multi_aff zero(isl::checked::space space);
+};
+
+// declarations for isl::multi_id
+inline multi_id manage(__isl_take isl_multi_id *ptr);
+inline multi_id manage_copy(__isl_keep isl_multi_id *ptr);
+
+class multi_id {
+  friend inline multi_id manage(__isl_take isl_multi_id *ptr);
+  friend inline multi_id manage_copy(__isl_keep isl_multi_id *ptr);
+
+protected:
+  isl_multi_id *ptr = nullptr;
+
+  inline explicit multi_id(__isl_take isl_multi_id *ptr);
+
+public:
+  inline /* implicit */ multi_id();
+  inline /* implicit */ multi_id(const multi_id &obj);
+  inline explicit multi_id(isl::checked::space space, isl::checked::id_list list);
+  inline explicit multi_id(isl::checked::ctx ctx, const std::string &str);
+  inline multi_id &operator=(multi_id obj);
+  inline ~multi_id();
+  inline __isl_give isl_multi_id *copy() const &;
+  inline __isl_give isl_multi_id *copy() && = delete;
+  inline __isl_keep isl_multi_id *get() const;
+  inline __isl_give isl_multi_id *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::multi_id flat_range_product(isl::checked::multi_id multi2) const;
+  inline isl::checked::id at(int pos) const;
+  inline isl::checked::id get_at(int pos) const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline boolean plain_is_equal(const isl::checked::multi_id &multi2) const;
+  inline isl::checked::multi_id range_product(isl::checked::multi_id multi2) const;
+  inline isl::checked::multi_id set_at(int pos, isl::checked::id el) const;
+  inline isl::checked::multi_id set_at(int pos, const std::string &el) const;
+  inline class size size() const;
+};
+
+// declarations for isl::multi_pw_aff
+inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+class multi_pw_aff {
+  friend inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+  friend inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+protected:
+  isl_multi_pw_aff *ptr = nullptr;
+
+  inline explicit multi_pw_aff(__isl_take isl_multi_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_pw_aff();
+  inline /* implicit */ multi_pw_aff(const multi_pw_aff &obj);
+  inline /* implicit */ multi_pw_aff(isl::checked::multi_aff ma);
+  inline /* implicit */ multi_pw_aff(isl::checked::pw_aff pa);
+  inline explicit multi_pw_aff(isl::checked::space space, isl::checked::pw_aff_list list);
+  inline /* implicit */ multi_pw_aff(isl::checked::pw_multi_aff pma);
+  inline explicit multi_pw_aff(isl::checked::ctx ctx, const std::string &str);
+  inline multi_pw_aff &operator=(multi_pw_aff obj);
+  inline ~multi_pw_aff();
+  inline __isl_give isl_multi_pw_aff *copy() const &;
+  inline __isl_give isl_multi_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_pw_aff *get() const;
+  inline __isl_give isl_multi_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::multi_pw_aff add(isl::checked::multi_pw_aff multi2) const;
+  inline isl::checked::multi_pw_aff add_constant(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_pw_aff add_constant(isl::checked::val v) const;
+  inline isl::checked::multi_pw_aff add_constant(long v) const;
+  inline isl::checked::set bind(isl::checked::multi_id tuple) const;
+  inline isl::checked::multi_pw_aff bind_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::multi_pw_aff bind_domain_wrapped_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::multi_pw_aff coalesce() const;
+  inline isl::checked::set domain() const;
+  inline isl::checked::multi_pw_aff flat_range_product(isl::checked::multi_pw_aff multi2) const;
+  inline isl::checked::pw_aff at(int pos) const;
+  inline isl::checked::pw_aff get_at(int pos) const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::multi_pw_aff gist(isl::checked::set set) const;
+  inline isl::checked::multi_pw_aff identity() const;
+  static inline isl::checked::multi_pw_aff identity_on_domain(isl::checked::space space);
+  inline isl::checked::multi_pw_aff intersect_domain(isl::checked::set domain) const;
+  inline isl::checked::multi_pw_aff intersect_params(isl::checked::set set) const;
+  inline boolean involves_param(const isl::checked::id &id) const;
+  inline boolean involves_param(const std::string &id) const;
+  inline boolean involves_param(const isl::checked::id_list &list) const;
+  inline isl::checked::multi_pw_aff neg() const;
+  inline boolean plain_is_equal(const isl::checked::multi_pw_aff &multi2) const;
+  inline isl::checked::multi_pw_aff product(isl::checked::multi_pw_aff multi2) const;
+  inline isl::checked::multi_pw_aff pullback(isl::checked::multi_aff ma) const;
+  inline isl::checked::multi_pw_aff pullback(isl::checked::multi_pw_aff mpa2) const;
+  inline isl::checked::multi_pw_aff pullback(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::multi_pw_aff range_product(isl::checked::multi_pw_aff multi2) const;
+  inline isl::checked::multi_pw_aff scale(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_pw_aff scale(isl::checked::val v) const;
+  inline isl::checked::multi_pw_aff scale(long v) const;
+  inline isl::checked::multi_pw_aff scale_down(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_pw_aff scale_down(isl::checked::val v) const;
+  inline isl::checked::multi_pw_aff scale_down(long v) const;
+  inline isl::checked::multi_pw_aff set_at(int pos, isl::checked::pw_aff el) const;
+  inline class size size() const;
+  inline isl::checked::multi_pw_aff sub(isl::checked::multi_pw_aff multi2) const;
+  static inline isl::checked::multi_pw_aff zero(isl::checked::space space);
+};
+
+// declarations for isl::multi_union_pw_aff
+inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+class multi_union_pw_aff {
+  friend inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+  friend inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+protected:
+  isl_multi_union_pw_aff *ptr = nullptr;
+
+  inline explicit multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_union_pw_aff();
+  inline /* implicit */ multi_union_pw_aff(const multi_union_pw_aff &obj);
+  inline /* implicit */ multi_union_pw_aff(isl::checked::multi_pw_aff mpa);
+  inline /* implicit */ multi_union_pw_aff(isl::checked::union_pw_aff upa);
+  inline explicit multi_union_pw_aff(isl::checked::space space, isl::checked::union_pw_aff_list list);
+  inline explicit multi_union_pw_aff(isl::checked::ctx ctx, const std::string &str);
+  inline multi_union_pw_aff &operator=(multi_union_pw_aff obj);
+  inline ~multi_union_pw_aff();
+  inline __isl_give isl_multi_union_pw_aff *copy() const &;
+  inline __isl_give isl_multi_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_union_pw_aff *get() const;
+  inline __isl_give isl_multi_union_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::multi_union_pw_aff add(isl::checked::multi_union_pw_aff multi2) const;
+  inline isl::checked::union_set bind(isl::checked::multi_id tuple) const;
+  inline isl::checked::multi_union_pw_aff coalesce() const;
+  inline isl::checked::union_set domain() const;
+  inline isl::checked::multi_union_pw_aff flat_range_product(isl::checked::multi_union_pw_aff multi2) const;
+  inline isl::checked::union_pw_aff at(int pos) const;
+  inline isl::checked::union_pw_aff get_at(int pos) const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::multi_union_pw_aff gist(isl::checked::union_set context) const;
+  inline isl::checked::multi_union_pw_aff intersect_domain(isl::checked::union_set uset) const;
+  inline isl::checked::multi_union_pw_aff intersect_params(isl::checked::set params) const;
+  inline isl::checked::multi_union_pw_aff neg() const;
+  inline boolean plain_is_equal(const isl::checked::multi_union_pw_aff &multi2) const;
+  inline isl::checked::multi_union_pw_aff pullback(isl::checked::union_pw_multi_aff upma) const;
+  inline isl::checked::multi_union_pw_aff range_product(isl::checked::multi_union_pw_aff multi2) const;
+  inline isl::checked::multi_union_pw_aff scale(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_union_pw_aff scale(isl::checked::val v) const;
+  inline isl::checked::multi_union_pw_aff scale(long v) const;
+  inline isl::checked::multi_union_pw_aff scale_down(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_union_pw_aff scale_down(isl::checked::val v) const;
+  inline isl::checked::multi_union_pw_aff scale_down(long v) const;
+  inline isl::checked::multi_union_pw_aff set_at(int pos, isl::checked::union_pw_aff el) const;
+  inline class size size() const;
+  inline isl::checked::multi_union_pw_aff sub(isl::checked::multi_union_pw_aff multi2) const;
+  inline isl::checked::multi_union_pw_aff union_add(isl::checked::multi_union_pw_aff mupa2) const;
+  static inline isl::checked::multi_union_pw_aff zero(isl::checked::space space);
+};
+
+// declarations for isl::multi_val
+inline multi_val manage(__isl_take isl_multi_val *ptr);
+inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+class multi_val {
+  friend inline multi_val manage(__isl_take isl_multi_val *ptr);
+  friend inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+protected:
+  isl_multi_val *ptr = nullptr;
+
+  inline explicit multi_val(__isl_take isl_multi_val *ptr);
+
+public:
+  inline /* implicit */ multi_val();
+  inline /* implicit */ multi_val(const multi_val &obj);
+  inline explicit multi_val(isl::checked::space space, isl::checked::val_list list);
+  inline explicit multi_val(isl::checked::ctx ctx, const std::string &str);
+  inline multi_val &operator=(multi_val obj);
+  inline ~multi_val();
+  inline __isl_give isl_multi_val *copy() const &;
+  inline __isl_give isl_multi_val *copy() && = delete;
+  inline __isl_keep isl_multi_val *get() const;
+  inline __isl_give isl_multi_val *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::multi_val add(isl::checked::multi_val multi2) const;
+  inline isl::checked::multi_val add(isl::checked::val v) const;
+  inline isl::checked::multi_val add(long v) const;
+  inline isl::checked::multi_val flat_range_product(isl::checked::multi_val multi2) const;
+  inline isl::checked::val at(int pos) const;
+  inline isl::checked::val get_at(int pos) const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::multi_val neg() const;
+  inline boolean plain_is_equal(const isl::checked::multi_val &multi2) const;
+  inline isl::checked::multi_val product(isl::checked::multi_val multi2) const;
+  inline isl::checked::multi_val range_product(isl::checked::multi_val multi2) const;
+  inline isl::checked::multi_val scale(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_val scale(isl::checked::val v) const;
+  inline isl::checked::multi_val scale(long v) const;
+  inline isl::checked::multi_val scale_down(isl::checked::multi_val mv) const;
+  inline isl::checked::multi_val scale_down(isl::checked::val v) const;
+  inline isl::checked::multi_val scale_down(long v) const;
+  inline isl::checked::multi_val set_at(int pos, isl::checked::val el) const;
+  inline isl::checked::multi_val set_at(int pos, long el) const;
+  inline class size size() const;
+  inline isl::checked::multi_val sub(isl::checked::multi_val multi2) const;
+  static inline isl::checked::multi_val zero(isl::checked::space space);
+};
+
+// declarations for isl::point
+inline point manage(__isl_take isl_point *ptr);
+inline point manage_copy(__isl_keep isl_point *ptr);
+
+class point {
+  friend inline point manage(__isl_take isl_point *ptr);
+  friend inline point manage_copy(__isl_keep isl_point *ptr);
+
+protected:
+  isl_point *ptr = nullptr;
+
+  inline explicit point(__isl_take isl_point *ptr);
+
+public:
+  inline /* implicit */ point();
+  inline /* implicit */ point(const point &obj);
+  inline point &operator=(point obj);
+  inline ~point();
+  inline __isl_give isl_point *copy() const &;
+  inline __isl_give isl_point *copy() && = delete;
+  inline __isl_keep isl_point *get() const;
+  inline __isl_give isl_point *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::multi_val multi_val() const;
+  inline isl::checked::multi_val get_multi_val() const;
+};
+
+// declarations for isl::pw_aff
+inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+class pw_aff {
+  friend inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+  friend inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+protected:
+  isl_pw_aff *ptr = nullptr;
+
+  inline explicit pw_aff(__isl_take isl_pw_aff *ptr);
+
+public:
+  inline /* implicit */ pw_aff();
+  inline /* implicit */ pw_aff(const pw_aff &obj);
+  inline /* implicit */ pw_aff(isl::checked::aff aff);
+  inline explicit pw_aff(isl::checked::ctx ctx, const std::string &str);
+  inline pw_aff &operator=(pw_aff obj);
+  inline ~pw_aff();
+  inline __isl_give isl_pw_aff *copy() const &;
+  inline __isl_give isl_pw_aff *copy() && = delete;
+  inline __isl_keep isl_pw_aff *get() const;
+  inline __isl_give isl_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::pw_aff add(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff add_constant(isl::checked::val v) const;
+  inline isl::checked::pw_aff add_constant(long v) const;
+  inline isl::checked::aff as_aff() const;
+  inline isl::checked::set bind(isl::checked::id id) const;
+  inline isl::checked::set bind(const std::string &id) const;
+  inline isl::checked::pw_aff bind_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::pw_aff bind_domain_wrapped_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::pw_aff ceil() const;
+  inline isl::checked::pw_aff coalesce() const;
+  inline isl::checked::pw_aff cond(isl::checked::pw_aff pwaff_true, isl::checked::pw_aff pwaff_false) const;
+  inline isl::checked::pw_aff div(isl::checked::pw_aff pa2) const;
+  inline isl::checked::set domain() const;
+  inline isl::checked::set eq_set(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::val eval(isl::checked::point pnt) const;
+  inline isl::checked::pw_aff floor() const;
+  inline isl::checked::set ge_set(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff gist(isl::checked::set context) const;
+  inline isl::checked::set gt_set(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff intersect_domain(isl::checked::set set) const;
+  inline isl::checked::pw_aff intersect_params(isl::checked::set set) const;
+  inline boolean isa_aff() const;
+  inline isl::checked::set le_set(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::set lt_set(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff max(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff min(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff mod(isl::checked::val mod) const;
+  inline isl::checked::pw_aff mod(long mod) const;
+  inline isl::checked::pw_aff mul(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::set ne_set(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff neg() const;
+  static inline isl::checked::pw_aff param_on_domain(isl::checked::set domain, isl::checked::id id);
+  inline isl::checked::pw_aff pullback(isl::checked::multi_aff ma) const;
+  inline isl::checked::pw_aff pullback(isl::checked::multi_pw_aff mpa) const;
+  inline isl::checked::pw_aff pullback(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::pw_aff scale(isl::checked::val v) const;
+  inline isl::checked::pw_aff scale(long v) const;
+  inline isl::checked::pw_aff scale_down(isl::checked::val f) const;
+  inline isl::checked::pw_aff scale_down(long f) const;
+  inline isl::checked::pw_aff sub(isl::checked::pw_aff pwaff2) const;
+  inline isl::checked::pw_aff subtract_domain(isl::checked::set set) const;
+  inline isl::checked::pw_aff tdiv_q(isl::checked::pw_aff pa2) const;
+  inline isl::checked::pw_aff tdiv_r(isl::checked::pw_aff pa2) const;
+  inline isl::checked::pw_aff union_add(isl::checked::pw_aff pwaff2) const;
+};
+
+// declarations for isl::pw_aff_list
+inline pw_aff_list manage(__isl_take isl_pw_aff_list *ptr);
+inline pw_aff_list manage_copy(__isl_keep isl_pw_aff_list *ptr);
+
+class pw_aff_list {
+  friend inline pw_aff_list manage(__isl_take isl_pw_aff_list *ptr);
+  friend inline pw_aff_list manage_copy(__isl_keep isl_pw_aff_list *ptr);
+
+protected:
+  isl_pw_aff_list *ptr = nullptr;
+
+  inline explicit pw_aff_list(__isl_take isl_pw_aff_list *ptr);
+
+public:
+  inline /* implicit */ pw_aff_list();
+  inline /* implicit */ pw_aff_list(const pw_aff_list &obj);
+  inline explicit pw_aff_list(isl::checked::ctx ctx, int n);
+  inline explicit pw_aff_list(isl::checked::pw_aff el);
+  inline pw_aff_list &operator=(pw_aff_list obj);
+  inline ~pw_aff_list();
+  inline __isl_give isl_pw_aff_list *copy() const &;
+  inline __isl_give isl_pw_aff_list *copy() && = delete;
+  inline __isl_keep isl_pw_aff_list *get() const;
+  inline __isl_give isl_pw_aff_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::pw_aff_list add(isl::checked::pw_aff el) const;
+  inline isl::checked::pw_aff_list clear() const;
+  inline isl::checked::pw_aff_list concat(isl::checked::pw_aff_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::pw_aff)> &fn) const;
+  inline isl::checked::pw_aff at(int index) const;
+  inline isl::checked::pw_aff get_at(int index) const;
+  inline class size size() const;
+};
+
+// declarations for isl::pw_multi_aff
+inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+class pw_multi_aff {
+  friend inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+  friend inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+protected:
+  isl_pw_multi_aff *ptr = nullptr;
+
+  inline explicit pw_multi_aff(__isl_take isl_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ pw_multi_aff();
+  inline /* implicit */ pw_multi_aff(const pw_multi_aff &obj);
+  inline /* implicit */ pw_multi_aff(isl::checked::multi_aff ma);
+  inline /* implicit */ pw_multi_aff(isl::checked::pw_aff pa);
+  inline explicit pw_multi_aff(isl::checked::ctx ctx, const std::string &str);
+  inline pw_multi_aff &operator=(pw_multi_aff obj);
+  inline ~pw_multi_aff();
+  inline __isl_give isl_pw_multi_aff *copy() const &;
+  inline __isl_give isl_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_pw_multi_aff *get() const;
+  inline __isl_give isl_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::pw_multi_aff add(isl::checked::pw_multi_aff pma2) const;
+  inline isl::checked::pw_multi_aff add_constant(isl::checked::multi_val mv) const;
+  inline isl::checked::pw_multi_aff add_constant(isl::checked::val v) const;
+  inline isl::checked::pw_multi_aff add_constant(long v) const;
+  inline isl::checked::multi_aff as_multi_aff() const;
+  inline isl::checked::pw_multi_aff bind_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::pw_multi_aff bind_domain_wrapped_domain(isl::checked::multi_id tuple) const;
+  inline isl::checked::pw_multi_aff coalesce() const;
+  inline isl::checked::set domain() const;
+  inline isl::checked::pw_multi_aff flat_range_product(isl::checked::pw_multi_aff pma2) const;
+  inline stat foreach_piece(const std::function<stat(isl::checked::set, isl::checked::multi_aff)> &fn) const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::pw_multi_aff gist(isl::checked::set set) const;
+  inline isl::checked::pw_multi_aff intersect_domain(isl::checked::set set) const;
+  inline isl::checked::pw_multi_aff intersect_params(isl::checked::set set) const;
+  inline boolean isa_multi_aff() const;
+  inline class size n_piece() const;
+  inline isl::checked::pw_multi_aff product(isl::checked::pw_multi_aff pma2) const;
+  inline isl::checked::pw_multi_aff pullback(isl::checked::multi_aff ma) const;
+  inline isl::checked::pw_multi_aff pullback(isl::checked::pw_multi_aff pma2) const;
+  inline isl::checked::pw_multi_aff range_factor_domain() const;
+  inline isl::checked::pw_multi_aff range_factor_range() const;
+  inline isl::checked::pw_multi_aff range_product(isl::checked::pw_multi_aff pma2) const;
+  inline isl::checked::pw_multi_aff scale(isl::checked::val v) const;
+  inline isl::checked::pw_multi_aff scale(long v) const;
+  inline isl::checked::pw_multi_aff scale_down(isl::checked::val v) const;
+  inline isl::checked::pw_multi_aff scale_down(long v) const;
+  inline isl::checked::pw_multi_aff sub(isl::checked::pw_multi_aff pma2) const;
+  inline isl::checked::pw_multi_aff subtract_domain(isl::checked::set set) const;
+  inline isl::checked::pw_multi_aff union_add(isl::checked::pw_multi_aff pma2) const;
+  static inline isl::checked::pw_multi_aff zero(isl::checked::space space);
+};
+
+// declarations for isl::pw_multi_aff_list
+inline pw_multi_aff_list manage(__isl_take isl_pw_multi_aff_list *ptr);
+inline pw_multi_aff_list manage_copy(__isl_keep isl_pw_multi_aff_list *ptr);
+
+class pw_multi_aff_list {
+  friend inline pw_multi_aff_list manage(__isl_take isl_pw_multi_aff_list *ptr);
+  friend inline pw_multi_aff_list manage_copy(__isl_keep isl_pw_multi_aff_list *ptr);
+
+protected:
+  isl_pw_multi_aff_list *ptr = nullptr;
+
+  inline explicit pw_multi_aff_list(__isl_take isl_pw_multi_aff_list *ptr);
+
+public:
+  inline /* implicit */ pw_multi_aff_list();
+  inline /* implicit */ pw_multi_aff_list(const pw_multi_aff_list &obj);
+  inline explicit pw_multi_aff_list(isl::checked::ctx ctx, int n);
+  inline explicit pw_multi_aff_list(isl::checked::pw_multi_aff el);
+  inline pw_multi_aff_list &operator=(pw_multi_aff_list obj);
+  inline ~pw_multi_aff_list();
+  inline __isl_give isl_pw_multi_aff_list *copy() const &;
+  inline __isl_give isl_pw_multi_aff_list *copy() && = delete;
+  inline __isl_keep isl_pw_multi_aff_list *get() const;
+  inline __isl_give isl_pw_multi_aff_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::pw_multi_aff_list add(isl::checked::pw_multi_aff el) const;
+  inline isl::checked::pw_multi_aff_list clear() const;
+  inline isl::checked::pw_multi_aff_list concat(isl::checked::pw_multi_aff_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::pw_multi_aff)> &fn) const;
+  inline isl::checked::pw_multi_aff at(int index) const;
+  inline isl::checked::pw_multi_aff get_at(int index) const;
+  inline class size size() const;
+};
+
+// declarations for isl::schedule
+inline schedule manage(__isl_take isl_schedule *ptr);
+inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+class schedule {
+  friend inline schedule manage(__isl_take isl_schedule *ptr);
+  friend inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+protected:
+  isl_schedule *ptr = nullptr;
+
+  inline explicit schedule(__isl_take isl_schedule *ptr);
+
+public:
+  inline /* implicit */ schedule();
+  inline /* implicit */ schedule(const schedule &obj);
+  inline explicit schedule(isl::checked::ctx ctx, const std::string &str);
+  inline schedule &operator=(schedule obj);
+  inline ~schedule();
+  inline __isl_give isl_schedule *copy() const &;
+  inline __isl_give isl_schedule *copy() && = delete;
+  inline __isl_keep isl_schedule *get() const;
+  inline __isl_give isl_schedule *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  static inline isl::checked::schedule from_domain(isl::checked::union_set domain);
+  inline isl::checked::union_map map() const;
+  inline isl::checked::union_map get_map() const;
+  inline isl::checked::schedule_node root() const;
+  inline isl::checked::schedule_node get_root() const;
+  inline isl::checked::schedule pullback(isl::checked::union_pw_multi_aff upma) const;
+};
+
+// declarations for isl::schedule_constraints
+inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+class schedule_constraints {
+  friend inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+  friend inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+protected:
+  isl_schedule_constraints *ptr = nullptr;
+
+  inline explicit schedule_constraints(__isl_take isl_schedule_constraints *ptr);
+
+public:
+  inline /* implicit */ schedule_constraints();
+  inline /* implicit */ schedule_constraints(const schedule_constraints &obj);
+  inline explicit schedule_constraints(isl::checked::ctx ctx, const std::string &str);
+  inline schedule_constraints &operator=(schedule_constraints obj);
+  inline ~schedule_constraints();
+  inline __isl_give isl_schedule_constraints *copy() const &;
+  inline __isl_give isl_schedule_constraints *copy() && = delete;
+  inline __isl_keep isl_schedule_constraints *get() const;
+  inline __isl_give isl_schedule_constraints *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::schedule compute_schedule() const;
+  inline isl::checked::union_map coincidence() const;
+  inline isl::checked::union_map get_coincidence() const;
+  inline isl::checked::union_map conditional_validity() const;
+  inline isl::checked::union_map get_conditional_validity() const;
+  inline isl::checked::union_map conditional_validity_condition() const;
+  inline isl::checked::union_map get_conditional_validity_condition() const;
+  inline isl::checked::set context() const;
+  inline isl::checked::set get_context() const;
+  inline isl::checked::union_set domain() const;
+  inline isl::checked::union_set get_domain() const;
+  inline isl::checked::union_map proximity() const;
+  inline isl::checked::union_map get_proximity() const;
+  inline isl::checked::union_map validity() const;
+  inline isl::checked::union_map get_validity() const;
+  static inline isl::checked::schedule_constraints on_domain(isl::checked::union_set domain);
+  inline isl::checked::schedule_constraints set_coincidence(isl::checked::union_map coincidence) const;
+  inline isl::checked::schedule_constraints set_conditional_validity(isl::checked::union_map condition, isl::checked::union_map validity) const;
+  inline isl::checked::schedule_constraints set_context(isl::checked::set context) const;
+  inline isl::checked::schedule_constraints set_proximity(isl::checked::union_map proximity) const;
+  inline isl::checked::schedule_constraints set_validity(isl::checked::union_map validity) const;
+};
+
+// declarations for isl::schedule_node
+inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+class schedule_node {
+  friend inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+  friend inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+protected:
+  isl_schedule_node *ptr = nullptr;
+
+  inline explicit schedule_node(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node();
+  inline /* implicit */ schedule_node(const schedule_node &obj);
+  inline schedule_node &operator=(schedule_node obj);
+  inline ~schedule_node();
+  inline __isl_give isl_schedule_node *copy() const &;
+  inline __isl_give isl_schedule_node *copy() && = delete;
+  inline __isl_keep isl_schedule_node *get() const;
+  inline __isl_give isl_schedule_node *release();
+  inline bool is_null() const;
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_schedule_node_get_type(NULL)),
+                  const T>::value>::type>
+  inline boolean isa_type(T subtype) const;
+public:
+  template <class T> inline boolean isa() const;
+  template <class T> inline T as() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::schedule_node ancestor(int generation) const;
+  inline isl::checked::schedule_node child(int pos) const;
+  inline boolean every_descendant(const std::function<boolean(isl::checked::schedule_node)> &test) const;
+  inline isl::checked::schedule_node first_child() const;
+  inline stat foreach_ancestor_top_down(const std::function<stat(isl::checked::schedule_node)> &fn) const;
+  inline stat foreach_descendant_top_down(const std::function<boolean(isl::checked::schedule_node)> &fn) const;
+  static inline isl::checked::schedule_node from_domain(isl::checked::union_set domain);
+  static inline isl::checked::schedule_node from_extension(isl::checked::union_map extension);
+  inline class size ancestor_child_position(const isl::checked::schedule_node &ancestor) const;
+  inline class size get_ancestor_child_position(const isl::checked::schedule_node &ancestor) const;
+  inline class size child_position() const;
+  inline class size get_child_position() const;
+  inline isl::checked::multi_union_pw_aff prefix_schedule_multi_union_pw_aff() const;
+  inline isl::checked::multi_union_pw_aff get_prefix_schedule_multi_union_pw_aff() const;
+  inline isl::checked::union_map prefix_schedule_union_map() const;
+  inline isl::checked::union_map get_prefix_schedule_union_map() const;
+  inline isl::checked::union_pw_multi_aff prefix_schedule_union_pw_multi_aff() const;
+  inline isl::checked::union_pw_multi_aff get_prefix_schedule_union_pw_multi_aff() const;
+  inline isl::checked::schedule schedule() const;
+  inline isl::checked::schedule get_schedule() const;
+  inline isl::checked::schedule_node shared_ancestor(const isl::checked::schedule_node &node2) const;
+  inline isl::checked::schedule_node get_shared_ancestor(const isl::checked::schedule_node &node2) const;
+  inline class size tree_depth() const;
+  inline class size get_tree_depth() const;
+  inline isl::checked::schedule_node graft_after(isl::checked::schedule_node graft) const;
+  inline isl::checked::schedule_node graft_before(isl::checked::schedule_node graft) const;
+  inline boolean has_children() const;
+  inline boolean has_next_sibling() const;
+  inline boolean has_parent() const;
+  inline boolean has_previous_sibling() const;
+  inline isl::checked::schedule_node insert_context(isl::checked::set context) const;
+  inline isl::checked::schedule_node insert_filter(isl::checked::union_set filter) const;
+  inline isl::checked::schedule_node insert_guard(isl::checked::set context) const;
+  inline isl::checked::schedule_node insert_mark(isl::checked::id mark) const;
+  inline isl::checked::schedule_node insert_mark(const std::string &mark) const;
+  inline isl::checked::schedule_node insert_partial_schedule(isl::checked::multi_union_pw_aff schedule) const;
+  inline isl::checked::schedule_node insert_sequence(isl::checked::union_set_list filters) const;
+  inline isl::checked::schedule_node insert_set(isl::checked::union_set_list filters) const;
+  inline boolean is_equal(const isl::checked::schedule_node &node2) const;
+  inline boolean is_subtree_anchored() const;
+  inline isl::checked::schedule_node map_descendant_bottom_up(const std::function<isl::checked::schedule_node(isl::checked::schedule_node)> &fn) const;
+  inline class size n_children() const;
+  inline isl::checked::schedule_node next_sibling() const;
+  inline isl::checked::schedule_node order_after(isl::checked::union_set filter) const;
+  inline isl::checked::schedule_node order_before(isl::checked::union_set filter) const;
+  inline isl::checked::schedule_node parent() const;
+  inline isl::checked::schedule_node previous_sibling() const;
+  inline isl::checked::schedule_node root() const;
+};
+
+// declarations for isl::schedule_node_band
+
+class schedule_node_band : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_band schedule_node::as<schedule_node_band>() const;
+  static const auto type = isl_schedule_node_band;
+
+protected:
+  inline explicit schedule_node_band(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_band();
+  inline /* implicit */ schedule_node_band(const schedule_node_band &obj);
+  inline schedule_node_band &operator=(schedule_node_band obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_set ast_build_options() const;
+  inline isl::checked::union_set get_ast_build_options() const;
+  inline isl::checked::set ast_isolate_option() const;
+  inline isl::checked::set get_ast_isolate_option() const;
+  inline isl::checked::multi_union_pw_aff partial_schedule() const;
+  inline isl::checked::multi_union_pw_aff get_partial_schedule() const;
+  inline boolean permutable() const;
+  inline boolean get_permutable() const;
+  inline boolean member_get_coincident(int pos) const;
+  inline schedule_node_band member_set_coincident(int pos, int coincident) const;
+  inline schedule_node_band mod(isl::checked::multi_val mv) const;
+  inline class size n_member() const;
+  inline schedule_node_band scale(isl::checked::multi_val mv) const;
+  inline schedule_node_band scale_down(isl::checked::multi_val mv) const;
+  inline schedule_node_band set_ast_build_options(isl::checked::union_set options) const;
+  inline schedule_node_band set_permutable(int permutable) const;
+  inline schedule_node_band shift(isl::checked::multi_union_pw_aff shift) const;
+  inline schedule_node_band split(int pos) const;
+  inline schedule_node_band tile(isl::checked::multi_val sizes) const;
+  inline schedule_node_band member_set_ast_loop_default(int pos) const;
+  inline schedule_node_band member_set_ast_loop_atomic(int pos) const;
+  inline schedule_node_band member_set_ast_loop_unroll(int pos) const;
+  inline schedule_node_band member_set_ast_loop_separate(int pos) const;
+};
+
+// declarations for isl::schedule_node_context
+
+class schedule_node_context : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_context schedule_node::as<schedule_node_context>() const;
+  static const auto type = isl_schedule_node_context;
+
+protected:
+  inline explicit schedule_node_context(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_context();
+  inline /* implicit */ schedule_node_context(const schedule_node_context &obj);
+  inline schedule_node_context &operator=(schedule_node_context obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::set context() const;
+  inline isl::checked::set get_context() const;
+};
+
+// declarations for isl::schedule_node_domain
+
+class schedule_node_domain : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_domain schedule_node::as<schedule_node_domain>() const;
+  static const auto type = isl_schedule_node_domain;
+
+protected:
+  inline explicit schedule_node_domain(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_domain();
+  inline /* implicit */ schedule_node_domain(const schedule_node_domain &obj);
+  inline schedule_node_domain &operator=(schedule_node_domain obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_set domain() const;
+  inline isl::checked::union_set get_domain() const;
+};
+
+// declarations for isl::schedule_node_expansion
+
+class schedule_node_expansion : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_expansion schedule_node::as<schedule_node_expansion>() const;
+  static const auto type = isl_schedule_node_expansion;
+
+protected:
+  inline explicit schedule_node_expansion(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_expansion();
+  inline /* implicit */ schedule_node_expansion(const schedule_node_expansion &obj);
+  inline schedule_node_expansion &operator=(schedule_node_expansion obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_pw_multi_aff contraction() const;
+  inline isl::checked::union_pw_multi_aff get_contraction() const;
+  inline isl::checked::union_map expansion() const;
+  inline isl::checked::union_map get_expansion() const;
+};
+
+// declarations for isl::schedule_node_extension
+
+class schedule_node_extension : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_extension schedule_node::as<schedule_node_extension>() const;
+  static const auto type = isl_schedule_node_extension;
+
+protected:
+  inline explicit schedule_node_extension(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_extension();
+  inline /* implicit */ schedule_node_extension(const schedule_node_extension &obj);
+  inline schedule_node_extension &operator=(schedule_node_extension obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_map extension() const;
+  inline isl::checked::union_map get_extension() const;
+};
+
+// declarations for isl::schedule_node_filter
+
+class schedule_node_filter : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_filter schedule_node::as<schedule_node_filter>() const;
+  static const auto type = isl_schedule_node_filter;
+
+protected:
+  inline explicit schedule_node_filter(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_filter();
+  inline /* implicit */ schedule_node_filter(const schedule_node_filter &obj);
+  inline schedule_node_filter &operator=(schedule_node_filter obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_set filter() const;
+  inline isl::checked::union_set get_filter() const;
+};
+
+// declarations for isl::schedule_node_guard
+
+class schedule_node_guard : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_guard schedule_node::as<schedule_node_guard>() const;
+  static const auto type = isl_schedule_node_guard;
+
+protected:
+  inline explicit schedule_node_guard(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_guard();
+  inline /* implicit */ schedule_node_guard(const schedule_node_guard &obj);
+  inline schedule_node_guard &operator=(schedule_node_guard obj);
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::set guard() const;
+  inline isl::checked::set get_guard() const;
+};
+
+// declarations for isl::schedule_node_leaf
+
+class schedule_node_leaf : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_leaf schedule_node::as<schedule_node_leaf>() const;
+  static const auto type = isl_schedule_node_leaf;
+
+protected:
+  inline explicit schedule_node_leaf(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_leaf();
+  inline /* implicit */ schedule_node_leaf(const schedule_node_leaf &obj);
+  inline schedule_node_leaf &operator=(schedule_node_leaf obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::schedule_node_mark
+
+class schedule_node_mark : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_mark schedule_node::as<schedule_node_mark>() const;
+  static const auto type = isl_schedule_node_mark;
+
+protected:
+  inline explicit schedule_node_mark(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_mark();
+  inline /* implicit */ schedule_node_mark(const schedule_node_mark &obj);
+  inline schedule_node_mark &operator=(schedule_node_mark obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::schedule_node_sequence
+
+class schedule_node_sequence : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_sequence schedule_node::as<schedule_node_sequence>() const;
+  static const auto type = isl_schedule_node_sequence;
+
+protected:
+  inline explicit schedule_node_sequence(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_sequence();
+  inline /* implicit */ schedule_node_sequence(const schedule_node_sequence &obj);
+  inline schedule_node_sequence &operator=(schedule_node_sequence obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::schedule_node_set
+
+class schedule_node_set : public schedule_node {
+  template <class T>
+  friend boolean schedule_node::isa() const;
+  friend schedule_node_set schedule_node::as<schedule_node_set>() const;
+  static const auto type = isl_schedule_node_set;
+
+protected:
+  inline explicit schedule_node_set(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_set();
+  inline /* implicit */ schedule_node_set(const schedule_node_set &obj);
+  inline schedule_node_set &operator=(schedule_node_set obj);
+  inline isl::checked::ctx ctx() const;
+
+};
+
+// declarations for isl::set
+inline set manage(__isl_take isl_set *ptr);
+inline set manage_copy(__isl_keep isl_set *ptr);
+
+class set {
+  friend inline set manage(__isl_take isl_set *ptr);
+  friend inline set manage_copy(__isl_keep isl_set *ptr);
+
+protected:
+  isl_set *ptr = nullptr;
+
+  inline explicit set(__isl_take isl_set *ptr);
+
+public:
+  inline /* implicit */ set();
+  inline /* implicit */ set(const set &obj);
+  inline /* implicit */ set(isl::checked::basic_set bset);
+  inline /* implicit */ set(isl::checked::point pnt);
+  inline explicit set(isl::checked::ctx ctx, const std::string &str);
+  inline set &operator=(set obj);
+  inline ~set();
+  inline __isl_give isl_set *copy() const &;
+  inline __isl_give isl_set *copy() && = delete;
+  inline __isl_keep isl_set *get() const;
+  inline __isl_give isl_set *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::basic_set affine_hull() const;
+  inline isl::checked::set apply(isl::checked::map map) const;
+  inline isl::checked::set bind(isl::checked::multi_id tuple) const;
+  inline isl::checked::set coalesce() const;
+  inline isl::checked::set complement() const;
+  inline isl::checked::set detect_equalities() const;
+  static inline isl::checked::set empty(isl::checked::space space);
+  inline isl::checked::set flatten() const;
+  inline stat foreach_basic_set(const std::function<stat(isl::checked::basic_set)> &fn) const;
+  inline stat foreach_point(const std::function<stat(isl::checked::point)> &fn) const;
+  inline isl::checked::multi_val plain_multi_val_if_fixed() const;
+  inline isl::checked::multi_val get_plain_multi_val_if_fixed() const;
+  inline isl::checked::fixed_box simple_fixed_box_hull() const;
+  inline isl::checked::fixed_box get_simple_fixed_box_hull() const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::val stride(int pos) const;
+  inline isl::checked::val get_stride(int pos) const;
+  inline isl::checked::set gist(isl::checked::set context) const;
+  inline isl::checked::map identity() const;
+  inline isl::checked::pw_aff indicator_function() const;
+  inline isl::checked::set intersect(isl::checked::set set2) const;
+  inline isl::checked::set intersect_params(isl::checked::set params) const;
+  inline boolean is_disjoint(const isl::checked::set &set2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const isl::checked::set &set2) const;
+  inline boolean is_singleton() const;
+  inline boolean is_strict_subset(const isl::checked::set &set2) const;
+  inline boolean is_subset(const isl::checked::set &set2) const;
+  inline boolean is_wrapping() const;
+  inline isl::checked::set lexmax() const;
+  inline isl::checked::pw_multi_aff lexmax_pw_multi_aff() const;
+  inline isl::checked::set lexmin() const;
+  inline isl::checked::pw_multi_aff lexmin_pw_multi_aff() const;
+  inline isl::checked::set lower_bound(isl::checked::multi_pw_aff lower) const;
+  inline isl::checked::set lower_bound(isl::checked::multi_val lower) const;
+  inline isl::checked::val max_val(const isl::checked::aff &obj) const;
+  inline isl::checked::val min_val(const isl::checked::aff &obj) const;
+  inline isl::checked::set params() const;
+  inline isl::checked::basic_set polyhedral_hull() const;
+  inline isl::checked::set preimage(isl::checked::multi_aff ma) const;
+  inline isl::checked::set preimage(isl::checked::multi_pw_aff mpa) const;
+  inline isl::checked::set preimage(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::set product(isl::checked::set set2) const;
+  inline isl::checked::set project_out_all_params() const;
+  inline isl::checked::set project_out_param(isl::checked::id id) const;
+  inline isl::checked::set project_out_param(const std::string &id) const;
+  inline isl::checked::set project_out_param(isl::checked::id_list list) const;
+  inline isl::checked::basic_set sample() const;
+  inline isl::checked::point sample_point() const;
+  inline isl::checked::set subtract(isl::checked::set set2) const;
+  inline isl::checked::set unbind_params(isl::checked::multi_id tuple) const;
+  inline isl::checked::map unbind_params_insert_domain(isl::checked::multi_id domain) const;
+  inline isl::checked::set unite(isl::checked::set set2) const;
+  static inline isl::checked::set universe(isl::checked::space space);
+  inline isl::checked::basic_set unshifted_simple_hull() const;
+  inline isl::checked::map unwrap() const;
+  inline isl::checked::set upper_bound(isl::checked::multi_pw_aff upper) const;
+  inline isl::checked::set upper_bound(isl::checked::multi_val upper) const;
+};
+
+// declarations for isl::space
+inline space manage(__isl_take isl_space *ptr);
+inline space manage_copy(__isl_keep isl_space *ptr);
+
+class space {
+  friend inline space manage(__isl_take isl_space *ptr);
+  friend inline space manage_copy(__isl_keep isl_space *ptr);
+
+protected:
+  isl_space *ptr = nullptr;
+
+  inline explicit space(__isl_take isl_space *ptr);
+
+public:
+  inline /* implicit */ space();
+  inline /* implicit */ space(const space &obj);
+  inline space &operator=(space obj);
+  inline ~space();
+  inline __isl_give isl_space *copy() const &;
+  inline __isl_give isl_space *copy() && = delete;
+  inline __isl_keep isl_space *get() const;
+  inline __isl_give isl_space *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::space add_named_tuple(isl::checked::id tuple_id, unsigned int dim) const;
+  inline isl::checked::space add_named_tuple(const std::string &tuple_id, unsigned int dim) const;
+  inline isl::checked::space add_unnamed_tuple(unsigned int dim) const;
+  inline isl::checked::space domain() const;
+  inline isl::checked::space flatten_domain() const;
+  inline isl::checked::space flatten_range() const;
+  inline boolean is_equal(const isl::checked::space &space2) const;
+  inline boolean is_wrapping() const;
+  inline isl::checked::space map_from_set() const;
+  inline isl::checked::space params() const;
+  inline isl::checked::space range() const;
+  static inline isl::checked::space unit(isl::checked::ctx ctx);
+  inline isl::checked::space unwrap() const;
+  inline isl::checked::space wrap() const;
+};
+
+// declarations for isl::union_access_info
+inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+class union_access_info {
+  friend inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+  friend inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+protected:
+  isl_union_access_info *ptr = nullptr;
+
+  inline explicit union_access_info(__isl_take isl_union_access_info *ptr);
+
+public:
+  inline /* implicit */ union_access_info();
+  inline /* implicit */ union_access_info(const union_access_info &obj);
+  inline explicit union_access_info(isl::checked::union_map sink);
+  inline union_access_info &operator=(union_access_info obj);
+  inline ~union_access_info();
+  inline __isl_give isl_union_access_info *copy() const &;
+  inline __isl_give isl_union_access_info *copy() && = delete;
+  inline __isl_keep isl_union_access_info *get() const;
+  inline __isl_give isl_union_access_info *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_flow compute_flow() const;
+  inline isl::checked::union_access_info set_kill(isl::checked::union_map kill) const;
+  inline isl::checked::union_access_info set_may_source(isl::checked::union_map may_source) const;
+  inline isl::checked::union_access_info set_must_source(isl::checked::union_map must_source) const;
+  inline isl::checked::union_access_info set_schedule(isl::checked::schedule schedule) const;
+  inline isl::checked::union_access_info set_schedule_map(isl::checked::union_map schedule_map) const;
+};
+
+// declarations for isl::union_flow
+inline union_flow manage(__isl_take isl_union_flow *ptr);
+inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+class union_flow {
+  friend inline union_flow manage(__isl_take isl_union_flow *ptr);
+  friend inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+protected:
+  isl_union_flow *ptr = nullptr;
+
+  inline explicit union_flow(__isl_take isl_union_flow *ptr);
+
+public:
+  inline /* implicit */ union_flow();
+  inline /* implicit */ union_flow(const union_flow &obj);
+  inline union_flow &operator=(union_flow obj);
+  inline ~union_flow();
+  inline __isl_give isl_union_flow *copy() const &;
+  inline __isl_give isl_union_flow *copy() && = delete;
+  inline __isl_keep isl_union_flow *get() const;
+  inline __isl_give isl_union_flow *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_map full_may_dependence() const;
+  inline isl::checked::union_map get_full_may_dependence() const;
+  inline isl::checked::union_map full_must_dependence() const;
+  inline isl::checked::union_map get_full_must_dependence() const;
+  inline isl::checked::union_map may_dependence() const;
+  inline isl::checked::union_map get_may_dependence() const;
+  inline isl::checked::union_map may_no_source() const;
+  inline isl::checked::union_map get_may_no_source() const;
+  inline isl::checked::union_map must_dependence() const;
+  inline isl::checked::union_map get_must_dependence() const;
+  inline isl::checked::union_map must_no_source() const;
+  inline isl::checked::union_map get_must_no_source() const;
+};
+
+// declarations for isl::union_map
+inline union_map manage(__isl_take isl_union_map *ptr);
+inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+class union_map {
+  friend inline union_map manage(__isl_take isl_union_map *ptr);
+  friend inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+protected:
+  isl_union_map *ptr = nullptr;
+
+  inline explicit union_map(__isl_take isl_union_map *ptr);
+
+public:
+  inline /* implicit */ union_map();
+  inline /* implicit */ union_map(const union_map &obj);
+  inline /* implicit */ union_map(isl::checked::basic_map bmap);
+  inline /* implicit */ union_map(isl::checked::map map);
+  inline explicit union_map(isl::checked::ctx ctx, const std::string &str);
+  inline union_map &operator=(union_map obj);
+  inline ~union_map();
+  inline __isl_give isl_union_map *copy() const &;
+  inline __isl_give isl_union_map *copy() && = delete;
+  inline __isl_keep isl_union_map *get() const;
+  inline __isl_give isl_union_map *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_map affine_hull() const;
+  inline isl::checked::union_map apply_domain(isl::checked::union_map umap2) const;
+  inline isl::checked::union_map apply_range(isl::checked::union_map umap2) const;
+  inline isl::checked::union_set bind_range(isl::checked::multi_id tuple) const;
+  inline isl::checked::union_map coalesce() const;
+  inline isl::checked::union_map compute_divs() const;
+  inline isl::checked::union_map curry() const;
+  inline isl::checked::union_set deltas() const;
+  inline isl::checked::union_map detect_equalities() const;
+  inline isl::checked::union_set domain() const;
+  inline isl::checked::union_map domain_factor_domain() const;
+  inline isl::checked::union_map domain_factor_range() const;
+  inline isl::checked::union_map domain_map() const;
+  inline isl::checked::union_pw_multi_aff domain_map_union_pw_multi_aff() const;
+  inline isl::checked::union_map domain_product(isl::checked::union_map umap2) const;
+  static inline isl::checked::union_map empty(isl::checked::ctx ctx);
+  inline isl::checked::union_map eq_at(isl::checked::multi_union_pw_aff mupa) const;
+  inline boolean every_map(const std::function<boolean(isl::checked::map)> &test) const;
+  inline isl::checked::map extract_map(isl::checked::space space) const;
+  inline isl::checked::union_map factor_domain() const;
+  inline isl::checked::union_map factor_range() const;
+  inline isl::checked::union_map fixed_power(isl::checked::val exp) const;
+  inline isl::checked::union_map fixed_power(long exp) const;
+  inline stat foreach_map(const std::function<stat(isl::checked::map)> &fn) const;
+  static inline isl::checked::union_map from(isl::checked::multi_union_pw_aff mupa);
+  static inline isl::checked::union_map from(isl::checked::union_pw_multi_aff upma);
+  static inline isl::checked::union_map from_domain(isl::checked::union_set uset);
+  static inline isl::checked::union_map from_domain_and_range(isl::checked::union_set domain, isl::checked::union_set range);
+  static inline isl::checked::union_map from_range(isl::checked::union_set uset);
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::union_map gist(isl::checked::union_map context) const;
+  inline isl::checked::union_map gist_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_map gist_params(isl::checked::set set) const;
+  inline isl::checked::union_map gist_range(isl::checked::union_set uset) const;
+  inline isl::checked::union_map intersect(isl::checked::union_map umap2) const;
+  inline isl::checked::union_map intersect_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_map intersect_params(isl::checked::set set) const;
+  inline isl::checked::union_map intersect_range(isl::checked::union_set uset) const;
+  inline boolean is_bijective() const;
+  inline boolean is_disjoint(const isl::checked::union_map &umap2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const isl::checked::union_map &umap2) const;
+  inline boolean is_injective() const;
+  inline boolean is_single_valued() const;
+  inline boolean is_strict_subset(const isl::checked::union_map &umap2) const;
+  inline boolean is_subset(const isl::checked::union_map &umap2) const;
+  inline boolean isa_map() const;
+  inline isl::checked::union_map lexmax() const;
+  inline isl::checked::union_map lexmin() const;
+  inline isl::checked::union_map polyhedral_hull() const;
+  inline isl::checked::union_map preimage_domain(isl::checked::multi_aff ma) const;
+  inline isl::checked::union_map preimage_domain(isl::checked::multi_pw_aff mpa) const;
+  inline isl::checked::union_map preimage_domain(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::union_map preimage_domain(isl::checked::union_pw_multi_aff upma) const;
+  inline isl::checked::union_map preimage_range(isl::checked::multi_aff ma) const;
+  inline isl::checked::union_map preimage_range(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::union_map preimage_range(isl::checked::union_pw_multi_aff upma) const;
+  inline isl::checked::union_map product(isl::checked::union_map umap2) const;
+  inline isl::checked::union_map project_out_all_params() const;
+  inline isl::checked::union_set range() const;
+  inline isl::checked::union_map range_factor_domain() const;
+  inline isl::checked::union_map range_factor_range() const;
+  inline isl::checked::union_map range_map() const;
+  inline isl::checked::union_map range_product(isl::checked::union_map umap2) const;
+  inline isl::checked::union_map range_reverse() const;
+  inline isl::checked::union_map reverse() const;
+  inline isl::checked::union_map subtract(isl::checked::union_map umap2) const;
+  inline isl::checked::union_map subtract_domain(isl::checked::union_set dom) const;
+  inline isl::checked::union_map subtract_range(isl::checked::union_set dom) const;
+  inline isl::checked::union_map uncurry() const;
+  inline isl::checked::union_map unite(isl::checked::union_map umap2) const;
+  inline isl::checked::union_map universe() const;
+  inline isl::checked::union_set wrap() const;
+  inline isl::checked::union_map zip() const;
+};
+
+// declarations for isl::union_pw_aff
+inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+class union_pw_aff {
+  friend inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+  friend inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+protected:
+  isl_union_pw_aff *ptr = nullptr;
+
+  inline explicit union_pw_aff(__isl_take isl_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_aff();
+  inline /* implicit */ union_pw_aff(const union_pw_aff &obj);
+  inline /* implicit */ union_pw_aff(isl::checked::pw_aff pa);
+  inline explicit union_pw_aff(isl::checked::ctx ctx, const std::string &str);
+  inline union_pw_aff &operator=(union_pw_aff obj);
+  inline ~union_pw_aff();
+  inline __isl_give isl_union_pw_aff *copy() const &;
+  inline __isl_give isl_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_aff *get() const;
+  inline __isl_give isl_union_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_pw_aff add(isl::checked::union_pw_aff upa2) const;
+  inline isl::checked::union_set bind(isl::checked::id id) const;
+  inline isl::checked::union_set bind(const std::string &id) const;
+  inline isl::checked::union_pw_aff coalesce() const;
+  inline isl::checked::union_set domain() const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::union_pw_aff gist(isl::checked::union_set context) const;
+  inline isl::checked::union_pw_aff intersect_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_aff intersect_domain_wrapped_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_aff intersect_domain_wrapped_range(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_aff intersect_params(isl::checked::set set) const;
+  inline isl::checked::union_pw_aff pullback(isl::checked::union_pw_multi_aff upma) const;
+  inline isl::checked::union_pw_aff sub(isl::checked::union_pw_aff upa2) const;
+  inline isl::checked::union_pw_aff subtract_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_aff union_add(isl::checked::union_pw_aff upa2) const;
+};
+
+// declarations for isl::union_pw_aff_list
+inline union_pw_aff_list manage(__isl_take isl_union_pw_aff_list *ptr);
+inline union_pw_aff_list manage_copy(__isl_keep isl_union_pw_aff_list *ptr);
+
+class union_pw_aff_list {
+  friend inline union_pw_aff_list manage(__isl_take isl_union_pw_aff_list *ptr);
+  friend inline union_pw_aff_list manage_copy(__isl_keep isl_union_pw_aff_list *ptr);
+
+protected:
+  isl_union_pw_aff_list *ptr = nullptr;
+
+  inline explicit union_pw_aff_list(__isl_take isl_union_pw_aff_list *ptr);
+
+public:
+  inline /* implicit */ union_pw_aff_list();
+  inline /* implicit */ union_pw_aff_list(const union_pw_aff_list &obj);
+  inline explicit union_pw_aff_list(isl::checked::ctx ctx, int n);
+  inline explicit union_pw_aff_list(isl::checked::union_pw_aff el);
+  inline union_pw_aff_list &operator=(union_pw_aff_list obj);
+  inline ~union_pw_aff_list();
+  inline __isl_give isl_union_pw_aff_list *copy() const &;
+  inline __isl_give isl_union_pw_aff_list *copy() && = delete;
+  inline __isl_keep isl_union_pw_aff_list *get() const;
+  inline __isl_give isl_union_pw_aff_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_pw_aff_list add(isl::checked::union_pw_aff el) const;
+  inline isl::checked::union_pw_aff_list clear() const;
+  inline isl::checked::union_pw_aff_list concat(isl::checked::union_pw_aff_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::union_pw_aff)> &fn) const;
+  inline isl::checked::union_pw_aff at(int index) const;
+  inline isl::checked::union_pw_aff get_at(int index) const;
+  inline class size size() const;
+};
+
+// declarations for isl::union_pw_multi_aff
+inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+class union_pw_multi_aff {
+  friend inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+  friend inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+protected:
+  isl_union_pw_multi_aff *ptr = nullptr;
+
+  inline explicit union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_multi_aff();
+  inline /* implicit */ union_pw_multi_aff(const union_pw_multi_aff &obj);
+  inline /* implicit */ union_pw_multi_aff(isl::checked::pw_multi_aff pma);
+  inline /* implicit */ union_pw_multi_aff(isl::checked::union_pw_aff upa);
+  inline explicit union_pw_multi_aff(isl::checked::ctx ctx, const std::string &str);
+  inline union_pw_multi_aff &operator=(union_pw_multi_aff obj);
+  inline ~union_pw_multi_aff();
+  inline __isl_give isl_union_pw_multi_aff *copy() const &;
+  inline __isl_give isl_union_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_multi_aff *get() const;
+  inline __isl_give isl_union_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_pw_multi_aff add(isl::checked::union_pw_multi_aff upma2) const;
+  inline isl::checked::pw_multi_aff as_pw_multi_aff() const;
+  inline isl::checked::union_pw_multi_aff coalesce() const;
+  inline isl::checked::union_set domain() const;
+  static inline isl::checked::union_pw_multi_aff empty(isl::checked::ctx ctx);
+  inline isl::checked::pw_multi_aff extract_pw_multi_aff(isl::checked::space space) const;
+  inline isl::checked::union_pw_multi_aff flat_range_product(isl::checked::union_pw_multi_aff upma2) const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::union_pw_multi_aff gist(isl::checked::union_set context) const;
+  inline isl::checked::union_pw_multi_aff intersect_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_multi_aff intersect_domain_wrapped_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_multi_aff intersect_domain_wrapped_range(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_multi_aff intersect_params(isl::checked::set set) const;
+  inline boolean isa_pw_multi_aff() const;
+  inline isl::checked::union_pw_multi_aff pullback(isl::checked::union_pw_multi_aff upma2) const;
+  inline isl::checked::union_pw_multi_aff range_factor_domain() const;
+  inline isl::checked::union_pw_multi_aff range_factor_range() const;
+  inline isl::checked::union_pw_multi_aff sub(isl::checked::union_pw_multi_aff upma2) const;
+  inline isl::checked::union_pw_multi_aff subtract_domain(isl::checked::union_set uset) const;
+  inline isl::checked::union_pw_multi_aff union_add(isl::checked::union_pw_multi_aff upma2) const;
+};
+
+// declarations for isl::union_set
+inline union_set manage(__isl_take isl_union_set *ptr);
+inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+class union_set {
+  friend inline union_set manage(__isl_take isl_union_set *ptr);
+  friend inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+protected:
+  isl_union_set *ptr = nullptr;
+
+  inline explicit union_set(__isl_take isl_union_set *ptr);
+
+public:
+  inline /* implicit */ union_set();
+  inline /* implicit */ union_set(const union_set &obj);
+  inline /* implicit */ union_set(isl::checked::basic_set bset);
+  inline /* implicit */ union_set(isl::checked::point pnt);
+  inline /* implicit */ union_set(isl::checked::set set);
+  inline explicit union_set(isl::checked::ctx ctx, const std::string &str);
+  inline union_set &operator=(union_set obj);
+  inline ~union_set();
+  inline __isl_give isl_union_set *copy() const &;
+  inline __isl_give isl_union_set *copy() && = delete;
+  inline __isl_keep isl_union_set *get() const;
+  inline __isl_give isl_union_set *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_set affine_hull() const;
+  inline isl::checked::union_set apply(isl::checked::union_map umap) const;
+  inline isl::checked::union_set coalesce() const;
+  inline isl::checked::union_set compute_divs() const;
+  inline isl::checked::union_set detect_equalities() const;
+  static inline isl::checked::union_set empty(isl::checked::ctx ctx);
+  inline boolean every_set(const std::function<boolean(isl::checked::set)> &test) const;
+  inline isl::checked::set extract_set(isl::checked::space space) const;
+  inline stat foreach_point(const std::function<stat(isl::checked::point)> &fn) const;
+  inline stat foreach_set(const std::function<stat(isl::checked::set)> &fn) const;
+  inline isl::checked::space space() const;
+  inline isl::checked::space get_space() const;
+  inline isl::checked::union_set gist(isl::checked::union_set context) const;
+  inline isl::checked::union_set gist_params(isl::checked::set set) const;
+  inline isl::checked::union_map identity() const;
+  inline isl::checked::union_set intersect(isl::checked::union_set uset2) const;
+  inline isl::checked::union_set intersect_params(isl::checked::set set) const;
+  inline boolean is_disjoint(const isl::checked::union_set &uset2) const;
+  inline boolean is_empty() const;
+  inline boolean is_equal(const isl::checked::union_set &uset2) const;
+  inline boolean is_strict_subset(const isl::checked::union_set &uset2) const;
+  inline boolean is_subset(const isl::checked::union_set &uset2) const;
+  inline boolean isa_set() const;
+  inline isl::checked::union_set lexmax() const;
+  inline isl::checked::union_set lexmin() const;
+  inline isl::checked::union_set polyhedral_hull() const;
+  inline isl::checked::union_set preimage(isl::checked::multi_aff ma) const;
+  inline isl::checked::union_set preimage(isl::checked::pw_multi_aff pma) const;
+  inline isl::checked::union_set preimage(isl::checked::union_pw_multi_aff upma) const;
+  inline isl::checked::point sample_point() const;
+  inline isl::checked::union_set subtract(isl::checked::union_set uset2) const;
+  inline isl::checked::union_set unite(isl::checked::union_set uset2) const;
+  inline isl::checked::union_set universe() const;
+  inline isl::checked::union_map unwrap() const;
+};
+
+// declarations for isl::union_set_list
+inline union_set_list manage(__isl_take isl_union_set_list *ptr);
+inline union_set_list manage_copy(__isl_keep isl_union_set_list *ptr);
+
+class union_set_list {
+  friend inline union_set_list manage(__isl_take isl_union_set_list *ptr);
+  friend inline union_set_list manage_copy(__isl_keep isl_union_set_list *ptr);
+
+protected:
+  isl_union_set_list *ptr = nullptr;
+
+  inline explicit union_set_list(__isl_take isl_union_set_list *ptr);
+
+public:
+  inline /* implicit */ union_set_list();
+  inline /* implicit */ union_set_list(const union_set_list &obj);
+  inline explicit union_set_list(isl::checked::ctx ctx, int n);
+  inline explicit union_set_list(isl::checked::union_set el);
+  inline union_set_list &operator=(union_set_list obj);
+  inline ~union_set_list();
+  inline __isl_give isl_union_set_list *copy() const &;
+  inline __isl_give isl_union_set_list *copy() && = delete;
+  inline __isl_keep isl_union_set_list *get() const;
+  inline __isl_give isl_union_set_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::union_set_list add(isl::checked::union_set el) const;
+  inline isl::checked::union_set_list clear() const;
+  inline isl::checked::union_set_list concat(isl::checked::union_set_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::union_set)> &fn) const;
+  inline isl::checked::union_set at(int index) const;
+  inline isl::checked::union_set get_at(int index) const;
+  inline class size size() const;
+};
+
+// declarations for isl::val
+inline val manage(__isl_take isl_val *ptr);
+inline val manage_copy(__isl_keep isl_val *ptr);
+
+class val {
+  friend inline val manage(__isl_take isl_val *ptr);
+  friend inline val manage_copy(__isl_keep isl_val *ptr);
+
+protected:
+  isl_val *ptr = nullptr;
+
+  inline explicit val(__isl_take isl_val *ptr);
+
+public:
+  inline /* implicit */ val();
+  inline /* implicit */ val(const val &obj);
+  inline explicit val(isl::checked::ctx ctx, long i);
+  inline explicit val(isl::checked::ctx ctx, const std::string &str);
+  inline val &operator=(val obj);
+  inline ~val();
+  inline __isl_give isl_val *copy() const &;
+  inline __isl_give isl_val *copy() && = delete;
+  inline __isl_keep isl_val *get() const;
+  inline __isl_give isl_val *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::val abs() const;
+  inline boolean abs_eq(const isl::checked::val &v2) const;
+  inline boolean abs_eq(long v2) const;
+  inline isl::checked::val add(isl::checked::val v2) const;
+  inline isl::checked::val add(long v2) const;
+  inline isl::checked::val ceil() const;
+  inline int cmp_si(long i) const;
+  inline isl::checked::val div(isl::checked::val v2) const;
+  inline isl::checked::val div(long v2) const;
+  inline boolean eq(const isl::checked::val &v2) const;
+  inline boolean eq(long v2) const;
+  inline isl::checked::val floor() const;
+  inline isl::checked::val gcd(isl::checked::val v2) const;
+  inline isl::checked::val gcd(long v2) const;
+  inline boolean ge(const isl::checked::val &v2) const;
+  inline boolean ge(long v2) const;
+  inline long den_si() const;
+  inline long get_den_si() const;
+  inline long num_si() const;
+  inline long get_num_si() const;
+  inline boolean gt(const isl::checked::val &v2) const;
+  inline boolean gt(long v2) const;
+  static inline isl::checked::val infty(isl::checked::ctx ctx);
+  inline isl::checked::val inv() const;
+  inline boolean is_divisible_by(const isl::checked::val &v2) const;
+  inline boolean is_divisible_by(long v2) const;
+  inline boolean is_infty() const;
+  inline boolean is_int() const;
+  inline boolean is_nan() const;
+  inline boolean is_neg() const;
+  inline boolean is_neginfty() const;
+  inline boolean is_negone() const;
+  inline boolean is_nonneg() const;
+  inline boolean is_nonpos() const;
+  inline boolean is_one() const;
+  inline boolean is_pos() const;
+  inline boolean is_rat() const;
+  inline boolean is_zero() const;
+  inline boolean le(const isl::checked::val &v2) const;
+  inline boolean le(long v2) const;
+  inline boolean lt(const isl::checked::val &v2) const;
+  inline boolean lt(long v2) const;
+  inline isl::checked::val max(isl::checked::val v2) const;
+  inline isl::checked::val max(long v2) const;
+  inline isl::checked::val min(isl::checked::val v2) const;
+  inline isl::checked::val min(long v2) const;
+  inline isl::checked::val mod(isl::checked::val v2) const;
+  inline isl::checked::val mod(long v2) const;
+  inline isl::checked::val mul(isl::checked::val v2) const;
+  inline isl::checked::val mul(long v2) const;
+  static inline isl::checked::val nan(isl::checked::ctx ctx);
+  inline boolean ne(const isl::checked::val &v2) const;
+  inline boolean ne(long v2) const;
+  inline isl::checked::val neg() const;
+  static inline isl::checked::val neginfty(isl::checked::ctx ctx);
+  static inline isl::checked::val negone(isl::checked::ctx ctx);
+  static inline isl::checked::val one(isl::checked::ctx ctx);
+  inline isl::checked::val pow2() const;
+  inline int sgn() const;
+  inline isl::checked::val sub(isl::checked::val v2) const;
+  inline isl::checked::val sub(long v2) const;
+  inline isl::checked::val trunc() const;
+  static inline isl::checked::val zero(isl::checked::ctx ctx);
+};
+
+// declarations for isl::val_list
+inline val_list manage(__isl_take isl_val_list *ptr);
+inline val_list manage_copy(__isl_keep isl_val_list *ptr);
+
+class val_list {
+  friend inline val_list manage(__isl_take isl_val_list *ptr);
+  friend inline val_list manage_copy(__isl_keep isl_val_list *ptr);
+
+protected:
+  isl_val_list *ptr = nullptr;
+
+  inline explicit val_list(__isl_take isl_val_list *ptr);
+
+public:
+  inline /* implicit */ val_list();
+  inline /* implicit */ val_list(const val_list &obj);
+  inline explicit val_list(isl::checked::ctx ctx, int n);
+  inline explicit val_list(isl::checked::val el);
+  inline val_list &operator=(val_list obj);
+  inline ~val_list();
+  inline __isl_give isl_val_list *copy() const &;
+  inline __isl_give isl_val_list *copy() && = delete;
+  inline __isl_keep isl_val_list *get() const;
+  inline __isl_give isl_val_list *release();
+  inline bool is_null() const;
+  inline isl::checked::ctx ctx() const;
+
+  inline isl::checked::val_list add(isl::checked::val el) const;
+  inline isl::checked::val_list add(long el) const;
+  inline isl::checked::val_list clear() const;
+  inline isl::checked::val_list concat(isl::checked::val_list list2) const;
+  inline stat foreach(const std::function<stat(isl::checked::val)> &fn) const;
+  inline isl::checked::val at(int index) const;
+  inline isl::checked::val get_at(int index) const;
+  inline class size size() const;
+};
+
+// implementations for isl::aff
+aff manage(__isl_take isl_aff *ptr) {
+  return aff(ptr);
+}
+aff manage_copy(__isl_keep isl_aff *ptr) {
+  ptr = isl_aff_copy(ptr);
+  return aff(ptr);
+}
+
+aff::aff()
+    : ptr(nullptr) {}
+
+aff::aff(const aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+aff::aff(__isl_take isl_aff *ptr)
+    : ptr(ptr) {}
+
+aff::aff(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+aff &aff::operator=(aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+aff::~aff() {
+  if (ptr)
+    isl_aff_free(ptr);
+}
+
+__isl_give isl_aff *aff::copy() const & {
+  return isl_aff_copy(ptr);
+}
+
+__isl_keep isl_aff *aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_aff *aff::release() {
+  isl_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx aff::ctx() const {
+  return isl::checked::ctx(isl_aff_get_ctx(ptr));
+}
+
+isl::checked::aff aff::add(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_add(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::add_constant(isl::checked::val v) const
+{
+  auto res = isl_aff_add_constant_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::add_constant(long v) const
+{
+  return this->add_constant(isl::checked::val(ctx(), v));
+}
+
+isl::checked::basic_set aff::bind(isl::checked::id id) const
+{
+  auto res = isl_aff_bind_id(copy(), id.release());
+  return manage(res);
+}
+
+isl::checked::basic_set aff::bind(const std::string &id) const
+{
+  return this->bind(isl::checked::id(ctx(), id));
+}
+
+isl::checked::aff aff::ceil() const
+{
+  auto res = isl_aff_ceil(copy());
+  return manage(res);
+}
+
+isl::checked::aff aff::div(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_div(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::set aff::eq_set(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_eq_set(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::val aff::eval(isl::checked::point pnt) const
+{
+  auto res = isl_aff_eval(copy(), pnt.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::floor() const
+{
+  auto res = isl_aff_floor(copy());
+  return manage(res);
+}
+
+isl::checked::set aff::ge_set(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_ge_set(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::gist(isl::checked::set context) const
+{
+  auto res = isl_aff_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::set aff::gt_set(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_gt_set(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::set aff::le_set(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_le_set(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::set aff::lt_set(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_lt_set(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::mod(isl::checked::val mod) const
+{
+  auto res = isl_aff_mod_val(copy(), mod.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::mod(long mod) const
+{
+  return this->mod(isl::checked::val(ctx(), mod));
+}
+
+isl::checked::aff aff::mul(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_mul(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::set aff::ne_set(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_ne_set(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::neg() const
+{
+  auto res = isl_aff_neg(copy());
+  return manage(res);
+}
+
+isl::checked::aff aff::pullback(isl::checked::multi_aff ma) const
+{
+  auto res = isl_aff_pullback_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::scale(isl::checked::val v) const
+{
+  auto res = isl_aff_scale_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::scale(long v) const
+{
+  return this->scale(isl::checked::val(ctx(), v));
+}
+
+isl::checked::aff aff::scale_down(isl::checked::val v) const
+{
+  auto res = isl_aff_scale_down_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::scale_down(long v) const
+{
+  return this->scale_down(isl::checked::val(ctx(), v));
+}
+
+isl::checked::aff aff::sub(isl::checked::aff aff2) const
+{
+  auto res = isl_aff_sub(copy(), aff2.release());
+  return manage(res);
+}
+
+isl::checked::aff aff::unbind_params_insert_domain(isl::checked::multi_id domain) const
+{
+  auto res = isl_aff_unbind_params_insert_domain(copy(), domain.release());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const aff &obj)
+{
+  char *str = isl_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::aff_list
+aff_list manage(__isl_take isl_aff_list *ptr) {
+  return aff_list(ptr);
+}
+aff_list manage_copy(__isl_keep isl_aff_list *ptr) {
+  ptr = isl_aff_list_copy(ptr);
+  return aff_list(ptr);
+}
+
+aff_list::aff_list()
+    : ptr(nullptr) {}
+
+aff_list::aff_list(const aff_list &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+aff_list::aff_list(__isl_take isl_aff_list *ptr)
+    : ptr(ptr) {}
+
+aff_list::aff_list(isl::checked::ctx ctx, int n)
+{
+  auto res = isl_aff_list_alloc(ctx.release(), n);
+  ptr = res;
+}
+
+aff_list::aff_list(isl::checked::aff el)
+{
+  auto res = isl_aff_list_from_aff(el.release());
+  ptr = res;
+}
+
+aff_list &aff_list::operator=(aff_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+aff_list::~aff_list() {
+  if (ptr)
+    isl_aff_list_free(ptr);
+}
+
+__isl_give isl_aff_list *aff_list::copy() const & {
+  return isl_aff_list_copy(ptr);
+}
+
+__isl_keep isl_aff_list *aff_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_aff_list *aff_list::release() {
+  isl_aff_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool aff_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx aff_list::ctx() const {
+  return isl::checked::ctx(isl_aff_list_get_ctx(ptr));
+}
+
+isl::checked::aff_list aff_list::add(isl::checked::aff el) const
+{
+  auto res = isl_aff_list_add(copy(), el.release());
+  return manage(res);
+}
+
+isl::checked::aff_list aff_list::clear() const
+{
+  auto res = isl_aff_list_clear(copy());
+  return manage(res);
+}
+
+isl::checked::aff_list aff_list::concat(isl::checked::aff_list list2) const
+{
+  auto res = isl_aff_list_concat(copy(), list2.release());
+  return manage(res);
+}
+
+stat aff_list::foreach(const std::function<stat(isl::checked::aff)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::aff)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_aff_list_foreach(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::aff aff_list::at(int index) const
+{
+  auto res = isl_aff_list_get_at(get(), index);
+  return manage(res);
+}
+
+isl::checked::aff aff_list::get_at(int index) const
+{
+  return at(index);
+}
+
+class size aff_list::size() const
+{
+  auto res = isl_aff_list_size(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const aff_list &obj)
+{
+  char *str = isl_aff_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_build
+ast_build manage(__isl_take isl_ast_build *ptr) {
+  return ast_build(ptr);
+}
+ast_build manage_copy(__isl_keep isl_ast_build *ptr) {
+  ptr = isl_ast_build_copy(ptr);
+  return ast_build(ptr);
+}
+
+ast_build::ast_build()
+    : ptr(nullptr) {}
+
+ast_build::ast_build(const ast_build &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+  copy_callbacks(obj);
+}
+
+ast_build::ast_build(__isl_take isl_ast_build *ptr)
+    : ptr(ptr) {}
+
+ast_build::ast_build(isl::checked::ctx ctx)
+{
+  auto res = isl_ast_build_alloc(ctx.release());
+  ptr = res;
+}
+
+ast_build &ast_build::operator=(ast_build obj) {
+  std::swap(this->ptr, obj.ptr);
+  copy_callbacks(obj);
+  return *this;
+}
+
+ast_build::~ast_build() {
+  if (ptr)
+    isl_ast_build_free(ptr);
+}
+
+__isl_give isl_ast_build *ast_build::copy() const & {
+  return isl_ast_build_copy(ptr);
+}
+
+__isl_keep isl_ast_build *ast_build::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_build *ast_build::release() {
+  if (at_each_domain_data)
+    isl_die(ctx().get(), isl_error_invalid, "cannot release object with persistent callbacks", return nullptr);
+  isl_ast_build *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_build::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx ast_build::ctx() const {
+  return isl::checked::ctx(isl_ast_build_get_ctx(ptr));
+}
+
+ast_build &ast_build::copy_callbacks(const ast_build &obj)
+{
+  at_each_domain_data = obj.at_each_domain_data;
+  return *this;
+}
+
+isl_ast_node *ast_build::at_each_domain(isl_ast_node *arg_0, isl_ast_build *arg_1, void *arg_2)
+{
+  auto *data = static_cast<struct at_each_domain_data *>(arg_2);
+  auto ret = (data->func)(manage(arg_0), manage_copy(arg_1));
+  return ret.release();
+}
+
+void ast_build::set_at_each_domain_data(const std::function<isl::checked::ast_node(isl::checked::ast_node, isl::checked::ast_build)> &fn)
+{
+  at_each_domain_data = std::make_shared<struct at_each_domain_data>();
+  at_each_domain_data->func = fn;
+  ptr = isl_ast_build_set_at_each_domain(ptr, &at_each_domain, at_each_domain_data.get());
+}
+
+isl::checked::ast_build ast_build::set_at_each_domain(const std::function<isl::checked::ast_node(isl::checked::ast_node, isl::checked::ast_build)> &fn) const
+{
+  auto copy = *this;
+  copy.set_at_each_domain_data(fn);
+  return copy;
+}
+
+isl::checked::ast_expr ast_build::access_from(isl::checked::multi_pw_aff mpa) const
+{
+  auto res = isl_ast_build_access_from_multi_pw_aff(get(), mpa.release());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_build::access_from(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_ast_build_access_from_pw_multi_aff(get(), pma.release());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_build::call_from(isl::checked::multi_pw_aff mpa) const
+{
+  auto res = isl_ast_build_call_from_multi_pw_aff(get(), mpa.release());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_build::call_from(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_ast_build_call_from_pw_multi_aff(get(), pma.release());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_build::expr_from(isl::checked::pw_aff pa) const
+{
+  auto res = isl_ast_build_expr_from_pw_aff(get(), pa.release());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_build::expr_from(isl::checked::set set) const
+{
+  auto res = isl_ast_build_expr_from_set(get(), set.release());
+  return manage(res);
+}
+
+isl::checked::ast_build ast_build::from_context(isl::checked::set set)
+{
+  auto res = isl_ast_build_from_context(set.release());
+  return manage(res);
+}
+
+isl::checked::union_map ast_build::schedule() const
+{
+  auto res = isl_ast_build_get_schedule(get());
+  return manage(res);
+}
+
+isl::checked::union_map ast_build::get_schedule() const
+{
+  return schedule();
+}
+
+isl::checked::ast_node ast_build::node_from(isl::checked::schedule schedule) const
+{
+  auto res = isl_ast_build_node_from_schedule(get(), schedule.release());
+  return manage(res);
+}
+
+isl::checked::ast_node ast_build::node_from_schedule_map(isl::checked::union_map schedule) const
+{
+  auto res = isl_ast_build_node_from_schedule_map(get(), schedule.release());
+  return manage(res);
+}
+
+// implementations for isl::ast_expr
+ast_expr manage(__isl_take isl_ast_expr *ptr) {
+  return ast_expr(ptr);
+}
+ast_expr manage_copy(__isl_keep isl_ast_expr *ptr) {
+  ptr = isl_ast_expr_copy(ptr);
+  return ast_expr(ptr);
+}
+
+ast_expr::ast_expr()
+    : ptr(nullptr) {}
+
+ast_expr::ast_expr(const ast_expr &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+ast_expr::ast_expr(__isl_take isl_ast_expr *ptr)
+    : ptr(ptr) {}
+
+ast_expr &ast_expr::operator=(ast_expr obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_expr::~ast_expr() {
+  if (ptr)
+    isl_ast_expr_free(ptr);
+}
+
+__isl_give isl_ast_expr *ast_expr::copy() const & {
+  return isl_ast_expr_copy(ptr);
+}
+
+__isl_keep isl_ast_expr *ast_expr::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_expr *ast_expr::release() {
+  isl_ast_expr *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_expr::is_null() const {
+  return ptr == nullptr;
+}
+
+template <typename T, typename>
+boolean ast_expr::isa_type(T subtype) const
+{
+  if (is_null())
+    return boolean();
+  return isl_ast_expr_get_type(get()) == subtype;
+}
+template <class T>
+boolean ast_expr::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T ast_expr::as() const
+{
+ if (isa<T>().is_false())
+    isl_die(ctx().get(), isl_error_invalid, "not an object of the requested subtype", return T());
+  return T(copy());
+}
+
+isl::checked::ctx ast_expr::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+std::string ast_expr::to_C_str() const
+{
+  auto res = isl_ast_expr_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_id
+ast_expr_id::ast_expr_id()
+    : ast_expr() {}
+
+ast_expr_id::ast_expr_id(const ast_expr_id &obj)
+    : ast_expr(obj)
+{
+}
+
+ast_expr_id::ast_expr_id(__isl_take isl_ast_expr *ptr)
+    : ast_expr(ptr) {}
+
+ast_expr_id &ast_expr_id::operator=(ast_expr_id obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_id::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+isl::checked::id ast_expr_id::id() const
+{
+  auto res = isl_ast_expr_id_get_id(get());
+  return manage(res);
+}
+
+isl::checked::id ast_expr_id::get_id() const
+{
+  return id();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_id &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_int
+ast_expr_int::ast_expr_int()
+    : ast_expr() {}
+
+ast_expr_int::ast_expr_int(const ast_expr_int &obj)
+    : ast_expr(obj)
+{
+}
+
+ast_expr_int::ast_expr_int(__isl_take isl_ast_expr *ptr)
+    : ast_expr(ptr) {}
+
+ast_expr_int &ast_expr_int::operator=(ast_expr_int obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_int::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+isl::checked::val ast_expr_int::val() const
+{
+  auto res = isl_ast_expr_int_get_val(get());
+  return manage(res);
+}
+
+isl::checked::val ast_expr_int::get_val() const
+{
+  return val();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_int &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op
+ast_expr_op::ast_expr_op()
+    : ast_expr() {}
+
+ast_expr_op::ast_expr_op(const ast_expr_op &obj)
+    : ast_expr(obj)
+{
+}
+
+ast_expr_op::ast_expr_op(__isl_take isl_ast_expr *ptr)
+    : ast_expr(ptr) {}
+
+ast_expr_op &ast_expr_op::operator=(ast_expr_op obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+template <typename T, typename>
+boolean ast_expr_op::isa_type(T subtype) const
+{
+  if (is_null())
+    return boolean();
+  return isl_ast_expr_op_get_type(get()) == subtype;
+}
+template <class T>
+boolean ast_expr_op::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T ast_expr_op::as() const
+{
+ if (isa<T>().is_false())
+    isl_die(ctx().get(), isl_error_invalid, "not an object of the requested subtype", return T());
+  return T(copy());
+}
+
+isl::checked::ctx ast_expr_op::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+isl::checked::ast_expr ast_expr_op::arg(int pos) const
+{
+  auto res = isl_ast_expr_op_get_arg(get(), pos);
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_expr_op::get_arg(int pos) const
+{
+  return arg(pos);
+}
+
+class size ast_expr_op::n_arg() const
+{
+  auto res = isl_ast_expr_op_get_n_arg(get());
+  return manage(res);
+}
+
+class size ast_expr_op::get_n_arg() const
+{
+  return n_arg();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_access
+ast_expr_op_access::ast_expr_op_access()
+    : ast_expr_op() {}
+
+ast_expr_op_access::ast_expr_op_access(const ast_expr_op_access &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_access::ast_expr_op_access(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_access &ast_expr_op_access::operator=(ast_expr_op_access obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_access::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_access &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_add
+ast_expr_op_add::ast_expr_op_add()
+    : ast_expr_op() {}
+
+ast_expr_op_add::ast_expr_op_add(const ast_expr_op_add &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_add::ast_expr_op_add(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_add &ast_expr_op_add::operator=(ast_expr_op_add obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_add::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_add &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_address_of
+ast_expr_op_address_of::ast_expr_op_address_of()
+    : ast_expr_op() {}
+
+ast_expr_op_address_of::ast_expr_op_address_of(const ast_expr_op_address_of &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_address_of::ast_expr_op_address_of(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_address_of &ast_expr_op_address_of::operator=(ast_expr_op_address_of obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_address_of::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_address_of &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_and
+ast_expr_op_and::ast_expr_op_and()
+    : ast_expr_op() {}
+
+ast_expr_op_and::ast_expr_op_and(const ast_expr_op_and &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_and::ast_expr_op_and(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_and &ast_expr_op_and::operator=(ast_expr_op_and obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_and::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_and &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_and_then
+ast_expr_op_and_then::ast_expr_op_and_then()
+    : ast_expr_op() {}
+
+ast_expr_op_and_then::ast_expr_op_and_then(const ast_expr_op_and_then &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_and_then::ast_expr_op_and_then(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_and_then &ast_expr_op_and_then::operator=(ast_expr_op_and_then obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_and_then::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_and_then &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_call
+ast_expr_op_call::ast_expr_op_call()
+    : ast_expr_op() {}
+
+ast_expr_op_call::ast_expr_op_call(const ast_expr_op_call &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_call::ast_expr_op_call(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_call &ast_expr_op_call::operator=(ast_expr_op_call obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_call::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_call &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_cond
+ast_expr_op_cond::ast_expr_op_cond()
+    : ast_expr_op() {}
+
+ast_expr_op_cond::ast_expr_op_cond(const ast_expr_op_cond &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_cond::ast_expr_op_cond(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_cond &ast_expr_op_cond::operator=(ast_expr_op_cond obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_cond::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_cond &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_div
+ast_expr_op_div::ast_expr_op_div()
+    : ast_expr_op() {}
+
+ast_expr_op_div::ast_expr_op_div(const ast_expr_op_div &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_div::ast_expr_op_div(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_div &ast_expr_op_div::operator=(ast_expr_op_div obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_div::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_div &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_eq
+ast_expr_op_eq::ast_expr_op_eq()
+    : ast_expr_op() {}
+
+ast_expr_op_eq::ast_expr_op_eq(const ast_expr_op_eq &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_eq::ast_expr_op_eq(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_eq &ast_expr_op_eq::operator=(ast_expr_op_eq obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_eq::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_eq &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_fdiv_q
+ast_expr_op_fdiv_q::ast_expr_op_fdiv_q()
+    : ast_expr_op() {}
+
+ast_expr_op_fdiv_q::ast_expr_op_fdiv_q(const ast_expr_op_fdiv_q &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_fdiv_q::ast_expr_op_fdiv_q(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_fdiv_q &ast_expr_op_fdiv_q::operator=(ast_expr_op_fdiv_q obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_fdiv_q::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_fdiv_q &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_ge
+ast_expr_op_ge::ast_expr_op_ge()
+    : ast_expr_op() {}
+
+ast_expr_op_ge::ast_expr_op_ge(const ast_expr_op_ge &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_ge::ast_expr_op_ge(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_ge &ast_expr_op_ge::operator=(ast_expr_op_ge obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_ge::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_ge &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_gt
+ast_expr_op_gt::ast_expr_op_gt()
+    : ast_expr_op() {}
+
+ast_expr_op_gt::ast_expr_op_gt(const ast_expr_op_gt &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_gt::ast_expr_op_gt(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_gt &ast_expr_op_gt::operator=(ast_expr_op_gt obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_gt::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_gt &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_le
+ast_expr_op_le::ast_expr_op_le()
+    : ast_expr_op() {}
+
+ast_expr_op_le::ast_expr_op_le(const ast_expr_op_le &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_le::ast_expr_op_le(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_le &ast_expr_op_le::operator=(ast_expr_op_le obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_le::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_le &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_lt
+ast_expr_op_lt::ast_expr_op_lt()
+    : ast_expr_op() {}
+
+ast_expr_op_lt::ast_expr_op_lt(const ast_expr_op_lt &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_lt::ast_expr_op_lt(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_lt &ast_expr_op_lt::operator=(ast_expr_op_lt obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_lt::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_lt &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_max
+ast_expr_op_max::ast_expr_op_max()
+    : ast_expr_op() {}
+
+ast_expr_op_max::ast_expr_op_max(const ast_expr_op_max &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_max::ast_expr_op_max(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_max &ast_expr_op_max::operator=(ast_expr_op_max obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_max::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_max &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_member
+ast_expr_op_member::ast_expr_op_member()
+    : ast_expr_op() {}
+
+ast_expr_op_member::ast_expr_op_member(const ast_expr_op_member &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_member::ast_expr_op_member(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_member &ast_expr_op_member::operator=(ast_expr_op_member obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_member::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_member &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_min
+ast_expr_op_min::ast_expr_op_min()
+    : ast_expr_op() {}
+
+ast_expr_op_min::ast_expr_op_min(const ast_expr_op_min &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_min::ast_expr_op_min(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_min &ast_expr_op_min::operator=(ast_expr_op_min obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_min::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_min &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_minus
+ast_expr_op_minus::ast_expr_op_minus()
+    : ast_expr_op() {}
+
+ast_expr_op_minus::ast_expr_op_minus(const ast_expr_op_minus &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_minus::ast_expr_op_minus(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_minus &ast_expr_op_minus::operator=(ast_expr_op_minus obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_minus::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_minus &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_mul
+ast_expr_op_mul::ast_expr_op_mul()
+    : ast_expr_op() {}
+
+ast_expr_op_mul::ast_expr_op_mul(const ast_expr_op_mul &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_mul::ast_expr_op_mul(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_mul &ast_expr_op_mul::operator=(ast_expr_op_mul obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_mul::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_mul &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_or
+ast_expr_op_or::ast_expr_op_or()
+    : ast_expr_op() {}
+
+ast_expr_op_or::ast_expr_op_or(const ast_expr_op_or &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_or::ast_expr_op_or(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_or &ast_expr_op_or::operator=(ast_expr_op_or obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_or::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_or &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_or_else
+ast_expr_op_or_else::ast_expr_op_or_else()
+    : ast_expr_op() {}
+
+ast_expr_op_or_else::ast_expr_op_or_else(const ast_expr_op_or_else &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_or_else::ast_expr_op_or_else(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_or_else &ast_expr_op_or_else::operator=(ast_expr_op_or_else obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_or_else::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_or_else &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_pdiv_q
+ast_expr_op_pdiv_q::ast_expr_op_pdiv_q()
+    : ast_expr_op() {}
+
+ast_expr_op_pdiv_q::ast_expr_op_pdiv_q(const ast_expr_op_pdiv_q &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_pdiv_q::ast_expr_op_pdiv_q(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_pdiv_q &ast_expr_op_pdiv_q::operator=(ast_expr_op_pdiv_q obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_pdiv_q::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_pdiv_q &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_pdiv_r
+ast_expr_op_pdiv_r::ast_expr_op_pdiv_r()
+    : ast_expr_op() {}
+
+ast_expr_op_pdiv_r::ast_expr_op_pdiv_r(const ast_expr_op_pdiv_r &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_pdiv_r::ast_expr_op_pdiv_r(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_pdiv_r &ast_expr_op_pdiv_r::operator=(ast_expr_op_pdiv_r obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_pdiv_r::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_pdiv_r &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_select
+ast_expr_op_select::ast_expr_op_select()
+    : ast_expr_op() {}
+
+ast_expr_op_select::ast_expr_op_select(const ast_expr_op_select &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_select::ast_expr_op_select(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_select &ast_expr_op_select::operator=(ast_expr_op_select obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_select::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_select &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_sub
+ast_expr_op_sub::ast_expr_op_sub()
+    : ast_expr_op() {}
+
+ast_expr_op_sub::ast_expr_op_sub(const ast_expr_op_sub &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_sub::ast_expr_op_sub(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_sub &ast_expr_op_sub::operator=(ast_expr_op_sub obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_sub::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_sub &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_zdiv_r
+ast_expr_op_zdiv_r::ast_expr_op_zdiv_r()
+    : ast_expr_op() {}
+
+ast_expr_op_zdiv_r::ast_expr_op_zdiv_r(const ast_expr_op_zdiv_r &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_zdiv_r::ast_expr_op_zdiv_r(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_zdiv_r &ast_expr_op_zdiv_r::operator=(ast_expr_op_zdiv_r obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_expr_op_zdiv_r::ctx() const {
+  return isl::checked::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_zdiv_r &obj)
+{
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node
+ast_node manage(__isl_take isl_ast_node *ptr) {
+  return ast_node(ptr);
+}
+ast_node manage_copy(__isl_keep isl_ast_node *ptr) {
+  ptr = isl_ast_node_copy(ptr);
+  return ast_node(ptr);
+}
+
+ast_node::ast_node()
+    : ptr(nullptr) {}
+
+ast_node::ast_node(const ast_node &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+ast_node::ast_node(__isl_take isl_ast_node *ptr)
+    : ptr(ptr) {}
+
+ast_node &ast_node::operator=(ast_node obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_node::~ast_node() {
+  if (ptr)
+    isl_ast_node_free(ptr);
+}
+
+__isl_give isl_ast_node *ast_node::copy() const & {
+  return isl_ast_node_copy(ptr);
+}
+
+__isl_keep isl_ast_node *ast_node::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_node *ast_node::release() {
+  isl_ast_node *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_node::is_null() const {
+  return ptr == nullptr;
+}
+
+template <typename T, typename>
+boolean ast_node::isa_type(T subtype) const
+{
+  if (is_null())
+    return boolean();
+  return isl_ast_node_get_type(get()) == subtype;
+}
+template <class T>
+boolean ast_node::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T ast_node::as() const
+{
+ if (isa<T>().is_false())
+    isl_die(ctx().get(), isl_error_invalid, "not an object of the requested subtype", return T());
+  return T(copy());
+}
+
+isl::checked::ctx ast_node::ctx() const {
+  return isl::checked::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+std::string ast_node::to_C_str() const
+{
+  auto res = isl_ast_node_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node &obj)
+{
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_block
+ast_node_block::ast_node_block()
+    : ast_node() {}
+
+ast_node_block::ast_node_block(const ast_node_block &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_block::ast_node_block(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_block &ast_node_block::operator=(ast_node_block obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_node_block::ctx() const {
+  return isl::checked::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::checked::ast_node_list ast_node_block::children() const
+{
+  auto res = isl_ast_node_block_get_children(get());
+  return manage(res);
+}
+
+isl::checked::ast_node_list ast_node_block::get_children() const
+{
+  return children();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_block &obj)
+{
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_for
+ast_node_for::ast_node_for()
+    : ast_node() {}
+
+ast_node_for::ast_node_for(const ast_node_for &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_for::ast_node_for(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_for &ast_node_for::operator=(ast_node_for obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_node_for::ctx() const {
+  return isl::checked::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::checked::ast_node ast_node_for::body() const
+{
+  auto res = isl_ast_node_for_get_body(get());
+  return manage(res);
+}
+
+isl::checked::ast_node ast_node_for::get_body() const
+{
+  return body();
+}
+
+isl::checked::ast_expr ast_node_for::cond() const
+{
+  auto res = isl_ast_node_for_get_cond(get());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_node_for::get_cond() const
+{
+  return cond();
+}
+
+isl::checked::ast_expr ast_node_for::inc() const
+{
+  auto res = isl_ast_node_for_get_inc(get());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_node_for::get_inc() const
+{
+  return inc();
+}
+
+isl::checked::ast_expr ast_node_for::init() const
+{
+  auto res = isl_ast_node_for_get_init(get());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_node_for::get_init() const
+{
+  return init();
+}
+
+isl::checked::ast_expr ast_node_for::iterator() const
+{
+  auto res = isl_ast_node_for_get_iterator(get());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_node_for::get_iterator() const
+{
+  return iterator();
+}
+
+boolean ast_node_for::is_degenerate() const
+{
+  auto res = isl_ast_node_for_is_degenerate(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_for &obj)
+{
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_if
+ast_node_if::ast_node_if()
+    : ast_node() {}
+
+ast_node_if::ast_node_if(const ast_node_if &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_if::ast_node_if(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_if &ast_node_if::operator=(ast_node_if obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_node_if::ctx() const {
+  return isl::checked::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::checked::ast_expr ast_node_if::cond() const
+{
+  auto res = isl_ast_node_if_get_cond(get());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_node_if::get_cond() const
+{
+  return cond();
+}
+
+isl::checked::ast_node ast_node_if::else_node() const
+{
+  auto res = isl_ast_node_if_get_else_node(get());
+  return manage(res);
+}
+
+isl::checked::ast_node ast_node_if::get_else_node() const
+{
+  return else_node();
+}
+
+isl::checked::ast_node ast_node_if::then_node() const
+{
+  auto res = isl_ast_node_if_get_then_node(get());
+  return manage(res);
+}
+
+isl::checked::ast_node ast_node_if::get_then_node() const
+{
+  return then_node();
+}
+
+boolean ast_node_if::has_else_node() const
+{
+  auto res = isl_ast_node_if_has_else_node(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_if &obj)
+{
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_list
+ast_node_list manage(__isl_take isl_ast_node_list *ptr) {
+  return ast_node_list(ptr);
+}
+ast_node_list manage_copy(__isl_keep isl_ast_node_list *ptr) {
+  ptr = isl_ast_node_list_copy(ptr);
+  return ast_node_list(ptr);
+}
+
+ast_node_list::ast_node_list()
+    : ptr(nullptr) {}
+
+ast_node_list::ast_node_list(const ast_node_list &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+ast_node_list::ast_node_list(__isl_take isl_ast_node_list *ptr)
+    : ptr(ptr) {}
+
+ast_node_list::ast_node_list(isl::checked::ctx ctx, int n)
+{
+  auto res = isl_ast_node_list_alloc(ctx.release(), n);
+  ptr = res;
+}
+
+ast_node_list::ast_node_list(isl::checked::ast_node el)
+{
+  auto res = isl_ast_node_list_from_ast_node(el.release());
+  ptr = res;
+}
+
+ast_node_list &ast_node_list::operator=(ast_node_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_node_list::~ast_node_list() {
+  if (ptr)
+    isl_ast_node_list_free(ptr);
+}
+
+__isl_give isl_ast_node_list *ast_node_list::copy() const & {
+  return isl_ast_node_list_copy(ptr);
+}
+
+__isl_keep isl_ast_node_list *ast_node_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_node_list *ast_node_list::release() {
+  isl_ast_node_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_node_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx ast_node_list::ctx() const {
+  return isl::checked::ctx(isl_ast_node_list_get_ctx(ptr));
+}
+
+isl::checked::ast_node_list ast_node_list::add(isl::checked::ast_node el) const
+{
+  auto res = isl_ast_node_list_add(copy(), el.release());
+  return manage(res);
+}
+
+isl::checked::ast_node_list ast_node_list::clear() const
+{
+  auto res = isl_ast_node_list_clear(copy());
+  return manage(res);
+}
+
+isl::checked::ast_node_list ast_node_list::concat(isl::checked::ast_node_list list2) const
+{
+  auto res = isl_ast_node_list_concat(copy(), list2.release());
+  return manage(res);
+}
+
+stat ast_node_list::foreach(const std::function<stat(isl::checked::ast_node)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::ast_node)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_ast_node *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_ast_node_list_foreach(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::ast_node ast_node_list::at(int index) const
+{
+  auto res = isl_ast_node_list_get_at(get(), index);
+  return manage(res);
+}
+
+isl::checked::ast_node ast_node_list::get_at(int index) const
+{
+  return at(index);
+}
+
+class size ast_node_list::size() const
+{
+  auto res = isl_ast_node_list_size(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_list &obj)
+{
+  char *str = isl_ast_node_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_mark
+ast_node_mark::ast_node_mark()
+    : ast_node() {}
+
+ast_node_mark::ast_node_mark(const ast_node_mark &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_mark::ast_node_mark(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_mark &ast_node_mark::operator=(ast_node_mark obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_node_mark::ctx() const {
+  return isl::checked::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::checked::id ast_node_mark::id() const
+{
+  auto res = isl_ast_node_mark_get_id(get());
+  return manage(res);
+}
+
+isl::checked::id ast_node_mark::get_id() const
+{
+  return id();
+}
+
+isl::checked::ast_node ast_node_mark::node() const
+{
+  auto res = isl_ast_node_mark_get_node(get());
+  return manage(res);
+}
+
+isl::checked::ast_node ast_node_mark::get_node() const
+{
+  return node();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_mark &obj)
+{
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_user
+ast_node_user::ast_node_user()
+    : ast_node() {}
+
+ast_node_user::ast_node_user(const ast_node_user &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_user::ast_node_user(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_user &ast_node_user::operator=(ast_node_user obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx ast_node_user::ctx() const {
+  return isl::checked::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::checked::ast_expr ast_node_user::expr() const
+{
+  auto res = isl_ast_node_user_get_expr(get());
+  return manage(res);
+}
+
+isl::checked::ast_expr ast_node_user::get_expr() const
+{
+  return expr();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_user &obj)
+{
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::basic_map
+basic_map manage(__isl_take isl_basic_map *ptr) {
+  return basic_map(ptr);
+}
+basic_map manage_copy(__isl_keep isl_basic_map *ptr) {
+  ptr = isl_basic_map_copy(ptr);
+  return basic_map(ptr);
+}
+
+basic_map::basic_map()
+    : ptr(nullptr) {}
+
+basic_map::basic_map(const basic_map &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+basic_map::basic_map(__isl_take isl_basic_map *ptr)
+    : ptr(ptr) {}
+
+basic_map::basic_map(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_basic_map_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+basic_map &basic_map::operator=(basic_map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_map::~basic_map() {
+  if (ptr)
+    isl_basic_map_free(ptr);
+}
+
+__isl_give isl_basic_map *basic_map::copy() const & {
+  return isl_basic_map_copy(ptr);
+}
+
+__isl_keep isl_basic_map *basic_map::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_map *basic_map::release() {
+  isl_basic_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_map::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx basic_map::ctx() const {
+  return isl::checked::ctx(isl_basic_map_get_ctx(ptr));
+}
+
+isl::checked::basic_map basic_map::affine_hull() const
+{
+  auto res = isl_basic_map_affine_hull(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::apply_domain(isl::checked::basic_map bmap2) const
+{
+  auto res = isl_basic_map_apply_domain(copy(), bmap2.release());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::apply_range(isl::checked::basic_map bmap2) const
+{
+  auto res = isl_basic_map_apply_range(copy(), bmap2.release());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_map::deltas() const
+{
+  auto res = isl_basic_map_deltas(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::detect_equalities() const
+{
+  auto res = isl_basic_map_detect_equalities(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::flatten() const
+{
+  auto res = isl_basic_map_flatten(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::flatten_domain() const
+{
+  auto res = isl_basic_map_flatten_domain(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::flatten_range() const
+{
+  auto res = isl_basic_map_flatten_range(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::gist(isl::checked::basic_map context) const
+{
+  auto res = isl_basic_map_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::intersect(isl::checked::basic_map bmap2) const
+{
+  auto res = isl_basic_map_intersect(copy(), bmap2.release());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::intersect_domain(isl::checked::basic_set bset) const
+{
+  auto res = isl_basic_map_intersect_domain(copy(), bset.release());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::intersect_range(isl::checked::basic_set bset) const
+{
+  auto res = isl_basic_map_intersect_range(copy(), bset.release());
+  return manage(res);
+}
+
+boolean basic_map::is_empty() const
+{
+  auto res = isl_basic_map_is_empty(get());
+  return manage(res);
+}
+
+boolean basic_map::is_equal(const isl::checked::basic_map &bmap2) const
+{
+  auto res = isl_basic_map_is_equal(get(), bmap2.get());
+  return manage(res);
+}
+
+boolean basic_map::is_subset(const isl::checked::basic_map &bmap2) const
+{
+  auto res = isl_basic_map_is_subset(get(), bmap2.get());
+  return manage(res);
+}
+
+isl::checked::map basic_map::lexmax() const
+{
+  auto res = isl_basic_map_lexmax(copy());
+  return manage(res);
+}
+
+isl::checked::map basic_map::lexmin() const
+{
+  auto res = isl_basic_map_lexmin(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::reverse() const
+{
+  auto res = isl_basic_map_reverse(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map basic_map::sample() const
+{
+  auto res = isl_basic_map_sample(copy());
+  return manage(res);
+}
+
+isl::checked::map basic_map::unite(isl::checked::basic_map bmap2) const
+{
+  auto res = isl_basic_map_union(copy(), bmap2.release());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const basic_map &obj)
+{
+  char *str = isl_basic_map_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::basic_set
+basic_set manage(__isl_take isl_basic_set *ptr) {
+  return basic_set(ptr);
+}
+basic_set manage_copy(__isl_keep isl_basic_set *ptr) {
+  ptr = isl_basic_set_copy(ptr);
+  return basic_set(ptr);
+}
+
+basic_set::basic_set()
+    : ptr(nullptr) {}
+
+basic_set::basic_set(const basic_set &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+basic_set::basic_set(__isl_take isl_basic_set *ptr)
+    : ptr(ptr) {}
+
+basic_set::basic_set(isl::checked::point pnt)
+{
+  auto res = isl_basic_set_from_point(pnt.release());
+  ptr = res;
+}
+
+basic_set::basic_set(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_basic_set_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+basic_set &basic_set::operator=(basic_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_set::~basic_set() {
+  if (ptr)
+    isl_basic_set_free(ptr);
+}
+
+__isl_give isl_basic_set *basic_set::copy() const & {
+  return isl_basic_set_copy(ptr);
+}
+
+__isl_keep isl_basic_set *basic_set::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_set *basic_set::release() {
+  isl_basic_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_set::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx basic_set::ctx() const {
+  return isl::checked::ctx(isl_basic_set_get_ctx(ptr));
+}
+
+isl::checked::basic_set basic_set::affine_hull() const
+{
+  auto res = isl_basic_set_affine_hull(copy());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::apply(isl::checked::basic_map bmap) const
+{
+  auto res = isl_basic_set_apply(copy(), bmap.release());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::detect_equalities() const
+{
+  auto res = isl_basic_set_detect_equalities(copy());
+  return manage(res);
+}
+
+isl::checked::val basic_set::dim_max_val(int pos) const
+{
+  auto res = isl_basic_set_dim_max_val(copy(), pos);
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::flatten() const
+{
+  auto res = isl_basic_set_flatten(copy());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::gist(isl::checked::basic_set context) const
+{
+  auto res = isl_basic_set_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::intersect(isl::checked::basic_set bset2) const
+{
+  auto res = isl_basic_set_intersect(copy(), bset2.release());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::intersect_params(isl::checked::basic_set bset2) const
+{
+  auto res = isl_basic_set_intersect_params(copy(), bset2.release());
+  return manage(res);
+}
+
+boolean basic_set::is_empty() const
+{
+  auto res = isl_basic_set_is_empty(get());
+  return manage(res);
+}
+
+boolean basic_set::is_equal(const isl::checked::basic_set &bset2) const
+{
+  auto res = isl_basic_set_is_equal(get(), bset2.get());
+  return manage(res);
+}
+
+boolean basic_set::is_subset(const isl::checked::basic_set &bset2) const
+{
+  auto res = isl_basic_set_is_subset(get(), bset2.get());
+  return manage(res);
+}
+
+boolean basic_set::is_wrapping() const
+{
+  auto res = isl_basic_set_is_wrapping(get());
+  return manage(res);
+}
+
+isl::checked::set basic_set::lexmax() const
+{
+  auto res = isl_basic_set_lexmax(copy());
+  return manage(res);
+}
+
+isl::checked::set basic_set::lexmin() const
+{
+  auto res = isl_basic_set_lexmin(copy());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::params() const
+{
+  auto res = isl_basic_set_params(copy());
+  return manage(res);
+}
+
+isl::checked::basic_set basic_set::sample() const
+{
+  auto res = isl_basic_set_sample(copy());
+  return manage(res);
+}
+
+isl::checked::point basic_set::sample_point() const
+{
+  auto res = isl_basic_set_sample_point(copy());
+  return manage(res);
+}
+
+isl::checked::set basic_set::unite(isl::checked::basic_set bset2) const
+{
+  auto res = isl_basic_set_union(copy(), bset2.release());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const basic_set &obj)
+{
+  char *str = isl_basic_set_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::fixed_box
+fixed_box manage(__isl_take isl_fixed_box *ptr) {
+  return fixed_box(ptr);
+}
+fixed_box manage_copy(__isl_keep isl_fixed_box *ptr) {
+  ptr = isl_fixed_box_copy(ptr);
+  return fixed_box(ptr);
+}
+
+fixed_box::fixed_box()
+    : ptr(nullptr) {}
+
+fixed_box::fixed_box(const fixed_box &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+fixed_box::fixed_box(__isl_take isl_fixed_box *ptr)
+    : ptr(ptr) {}
+
+fixed_box &fixed_box::operator=(fixed_box obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+fixed_box::~fixed_box() {
+  if (ptr)
+    isl_fixed_box_free(ptr);
+}
+
+__isl_give isl_fixed_box *fixed_box::copy() const & {
+  return isl_fixed_box_copy(ptr);
+}
+
+__isl_keep isl_fixed_box *fixed_box::get() const {
+  return ptr;
+}
+
+__isl_give isl_fixed_box *fixed_box::release() {
+  isl_fixed_box *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool fixed_box::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx fixed_box::ctx() const {
+  return isl::checked::ctx(isl_fixed_box_get_ctx(ptr));
+}
+
+isl::checked::multi_aff fixed_box::offset() const
+{
+  auto res = isl_fixed_box_get_offset(get());
+  return manage(res);
+}
+
+isl::checked::multi_aff fixed_box::get_offset() const
+{
+  return offset();
+}
+
+isl::checked::multi_val fixed_box::size() const
+{
+  auto res = isl_fixed_box_get_size(get());
+  return manage(res);
+}
+
+isl::checked::multi_val fixed_box::get_size() const
+{
+  return size();
+}
+
+isl::checked::space fixed_box::space() const
+{
+  auto res = isl_fixed_box_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space fixed_box::get_space() const
+{
+  return space();
+}
+
+boolean fixed_box::is_valid() const
+{
+  auto res = isl_fixed_box_is_valid(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const fixed_box &obj)
+{
+  char *str = isl_fixed_box_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::id
+id manage(__isl_take isl_id *ptr) {
+  return id(ptr);
+}
+id manage_copy(__isl_keep isl_id *ptr) {
+  ptr = isl_id_copy(ptr);
+  return id(ptr);
+}
+
+id::id()
+    : ptr(nullptr) {}
+
+id::id(const id &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+id::id(__isl_take isl_id *ptr)
+    : ptr(ptr) {}
+
+id::id(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_id_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+id &id::operator=(id obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+id::~id() {
+  if (ptr)
+    isl_id_free(ptr);
+}
+
+__isl_give isl_id *id::copy() const & {
+  return isl_id_copy(ptr);
+}
+
+__isl_keep isl_id *id::get() const {
+  return ptr;
+}
+
+__isl_give isl_id *id::release() {
+  isl_id *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool id::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx id::ctx() const {
+  return isl::checked::ctx(isl_id_get_ctx(ptr));
+}
+
+std::string id::name() const
+{
+  auto res = isl_id_get_name(get());
+  std::string tmp(res);
+  return tmp;
+}
+
+std::string id::get_name() const
+{
+  return name();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const id &obj)
+{
+  char *str = isl_id_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::id_list
+id_list manage(__isl_take isl_id_list *ptr) {
+  return id_list(ptr);
+}
+id_list manage_copy(__isl_keep isl_id_list *ptr) {
+  ptr = isl_id_list_copy(ptr);
+  return id_list(ptr);
+}
+
+id_list::id_list()
+    : ptr(nullptr) {}
+
+id_list::id_list(const id_list &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+id_list::id_list(__isl_take isl_id_list *ptr)
+    : ptr(ptr) {}
+
+id_list::id_list(isl::checked::ctx ctx, int n)
+{
+  auto res = isl_id_list_alloc(ctx.release(), n);
+  ptr = res;
+}
+
+id_list::id_list(isl::checked::id el)
+{
+  auto res = isl_id_list_from_id(el.release());
+  ptr = res;
+}
+
+id_list &id_list::operator=(id_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+id_list::~id_list() {
+  if (ptr)
+    isl_id_list_free(ptr);
+}
+
+__isl_give isl_id_list *id_list::copy() const & {
+  return isl_id_list_copy(ptr);
+}
+
+__isl_keep isl_id_list *id_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_id_list *id_list::release() {
+  isl_id_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool id_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx id_list::ctx() const {
+  return isl::checked::ctx(isl_id_list_get_ctx(ptr));
+}
+
+isl::checked::id_list id_list::add(isl::checked::id el) const
+{
+  auto res = isl_id_list_add(copy(), el.release());
+  return manage(res);
+}
+
+isl::checked::id_list id_list::add(const std::string &el) const
+{
+  return this->add(isl::checked::id(ctx(), el));
+}
+
+isl::checked::id_list id_list::clear() const
+{
+  auto res = isl_id_list_clear(copy());
+  return manage(res);
+}
+
+isl::checked::id_list id_list::concat(isl::checked::id_list list2) const
+{
+  auto res = isl_id_list_concat(copy(), list2.release());
+  return manage(res);
+}
+
+stat id_list::foreach(const std::function<stat(isl::checked::id)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::id)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_id *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_id_list_foreach(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::id id_list::at(int index) const
+{
+  auto res = isl_id_list_get_at(get(), index);
+  return manage(res);
+}
+
+isl::checked::id id_list::get_at(int index) const
+{
+  return at(index);
+}
+
+class size id_list::size() const
+{
+  auto res = isl_id_list_size(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const id_list &obj)
+{
+  char *str = isl_id_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::map
+map manage(__isl_take isl_map *ptr) {
+  return map(ptr);
+}
+map manage_copy(__isl_keep isl_map *ptr) {
+  ptr = isl_map_copy(ptr);
+  return map(ptr);
+}
+
+map::map()
+    : ptr(nullptr) {}
+
+map::map(const map &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+map::map(__isl_take isl_map *ptr)
+    : ptr(ptr) {}
+
+map::map(isl::checked::basic_map bmap)
+{
+  auto res = isl_map_from_basic_map(bmap.release());
+  ptr = res;
+}
+
+map::map(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_map_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+map &map::operator=(map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+map::~map() {
+  if (ptr)
+    isl_map_free(ptr);
+}
+
+__isl_give isl_map *map::copy() const & {
+  return isl_map_copy(ptr);
+}
+
+__isl_keep isl_map *map::get() const {
+  return ptr;
+}
+
+__isl_give isl_map *map::release() {
+  isl_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool map::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx map::ctx() const {
+  return isl::checked::ctx(isl_map_get_ctx(ptr));
+}
+
+isl::checked::basic_map map::affine_hull() const
+{
+  auto res = isl_map_affine_hull(copy());
+  return manage(res);
+}
+
+isl::checked::map map::apply_domain(isl::checked::map map2) const
+{
+  auto res = isl_map_apply_domain(copy(), map2.release());
+  return manage(res);
+}
+
+isl::checked::map map::apply_range(isl::checked::map map2) const
+{
+  auto res = isl_map_apply_range(copy(), map2.release());
+  return manage(res);
+}
+
+isl::checked::set map::bind_domain(isl::checked::multi_id tuple) const
+{
+  auto res = isl_map_bind_domain(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::set map::bind_range(isl::checked::multi_id tuple) const
+{
+  auto res = isl_map_bind_range(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::map map::coalesce() const
+{
+  auto res = isl_map_coalesce(copy());
+  return manage(res);
+}
+
+isl::checked::map map::complement() const
+{
+  auto res = isl_map_complement(copy());
+  return manage(res);
+}
+
+isl::checked::map map::curry() const
+{
+  auto res = isl_map_curry(copy());
+  return manage(res);
+}
+
+isl::checked::set map::deltas() const
+{
+  auto res = isl_map_deltas(copy());
+  return manage(res);
+}
+
+isl::checked::map map::detect_equalities() const
+{
+  auto res = isl_map_detect_equalities(copy());
+  return manage(res);
+}
+
+isl::checked::set map::domain() const
+{
+  auto res = isl_map_domain(copy());
+  return manage(res);
+}
+
+isl::checked::map map::domain_factor_domain() const
+{
+  auto res = isl_map_domain_factor_domain(copy());
+  return manage(res);
+}
+
+isl::checked::map map::domain_factor_range() const
+{
+  auto res = isl_map_domain_factor_range(copy());
+  return manage(res);
+}
+
+isl::checked::map map::domain_product(isl::checked::map map2) const
+{
+  auto res = isl_map_domain_product(copy(), map2.release());
+  return manage(res);
+}
+
+isl::checked::map map::empty(isl::checked::space space)
+{
+  auto res = isl_map_empty(space.release());
+  return manage(res);
+}
+
+isl::checked::map map::factor_domain() const
+{
+  auto res = isl_map_factor_domain(copy());
+  return manage(res);
+}
+
+isl::checked::map map::factor_range() const
+{
+  auto res = isl_map_factor_range(copy());
+  return manage(res);
+}
+
+isl::checked::map map::flatten() const
+{
+  auto res = isl_map_flatten(copy());
+  return manage(res);
+}
+
+isl::checked::map map::flatten_domain() const
+{
+  auto res = isl_map_flatten_domain(copy());
+  return manage(res);
+}
+
+isl::checked::map map::flatten_range() const
+{
+  auto res = isl_map_flatten_range(copy());
+  return manage(res);
+}
+
+stat map::foreach_basic_map(const std::function<stat(isl::checked::basic_map)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::basic_map)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_basic_map *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_map_foreach_basic_map(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::fixed_box map::range_simple_fixed_box_hull() const
+{
+  auto res = isl_map_get_range_simple_fixed_box_hull(get());
+  return manage(res);
+}
+
+isl::checked::fixed_box map::get_range_simple_fixed_box_hull() const
+{
+  return range_simple_fixed_box_hull();
+}
+
+isl::checked::space map::space() const
+{
+  auto res = isl_map_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space map::get_space() const
+{
+  return space();
+}
+
+isl::checked::map map::gist(isl::checked::map context) const
+{
+  auto res = isl_map_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::map map::gist_domain(isl::checked::set context) const
+{
+  auto res = isl_map_gist_domain(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::map map::intersect(isl::checked::map map2) const
+{
+  auto res = isl_map_intersect(copy(), map2.release());
+  return manage(res);
+}
+
+isl::checked::map map::intersect_domain(isl::checked::set set) const
+{
+  auto res = isl_map_intersect_domain(copy(), set.release());
+  return manage(res);
+}
+
+isl::checked::map map::intersect_params(isl::checked::set params) const
+{
+  auto res = isl_map_intersect_params(copy(), params.release());
+  return manage(res);
+}
+
+isl::checked::map map::intersect_range(isl::checked::set set) const
+{
+  auto res = isl_map_intersect_range(copy(), set.release());
+  return manage(res);
+}
+
+boolean map::is_bijective() const
+{
+  auto res = isl_map_is_bijective(get());
+  return manage(res);
+}
+
+boolean map::is_disjoint(const isl::checked::map &map2) const
+{
+  auto res = isl_map_is_disjoint(get(), map2.get());
+  return manage(res);
+}
+
+boolean map::is_empty() const
+{
+  auto res = isl_map_is_empty(get());
+  return manage(res);
+}
+
+boolean map::is_equal(const isl::checked::map &map2) const
+{
+  auto res = isl_map_is_equal(get(), map2.get());
+  return manage(res);
+}
+
+boolean map::is_injective() const
+{
+  auto res = isl_map_is_injective(get());
+  return manage(res);
+}
+
+boolean map::is_single_valued() const
+{
+  auto res = isl_map_is_single_valued(get());
+  return manage(res);
+}
+
+boolean map::is_strict_subset(const isl::checked::map &map2) const
+{
+  auto res = isl_map_is_strict_subset(get(), map2.get());
+  return manage(res);
+}
+
+boolean map::is_subset(const isl::checked::map &map2) const
+{
+  auto res = isl_map_is_subset(get(), map2.get());
+  return manage(res);
+}
+
+isl::checked::map map::lexmax() const
+{
+  auto res = isl_map_lexmax(copy());
+  return manage(res);
+}
+
+isl::checked::pw_multi_aff map::lexmax_pw_multi_aff() const
+{
+  auto res = isl_map_lexmax_pw_multi_aff(copy());
+  return manage(res);
+}
+
+isl::checked::map map::lexmin() const
+{
+  auto res = isl_map_lexmin(copy());
+  return manage(res);
+}
+
+isl::checked::pw_multi_aff map::lexmin_pw_multi_aff() const
+{
+  auto res = isl_map_lexmin_pw_multi_aff(copy());
+  return manage(res);
+}
+
+isl::checked::map map::lower_bound(isl::checked::multi_pw_aff lower) const
+{
+  auto res = isl_map_lower_bound_multi_pw_aff(copy(), lower.release());
+  return manage(res);
+}
+
+isl::checked::map map::lower_bound(isl::checked::multi_val lower) const
+{
+  auto res = isl_map_lower_bound_multi_val(copy(), lower.release());
+  return manage(res);
+}
+
+isl::checked::basic_map map::polyhedral_hull() const
+{
+  auto res = isl_map_polyhedral_hull(copy());
+  return manage(res);
+}
+
+isl::checked::map map::preimage_domain(isl::checked::multi_aff ma) const
+{
+  auto res = isl_map_preimage_domain_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+isl::checked::map map::preimage_domain(isl::checked::multi_pw_aff mpa) const
+{
+  auto res = isl_map_preimage_domain_multi_pw_aff(copy(), mpa.release());
+  return manage(res);
+}
+
+isl::checked::map map::preimage_domain(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_map_preimage_domain_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+isl::checked::map map::preimage_range(isl::checked::multi_aff ma) const
+{
+  auto res = isl_map_preimage_range_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+isl::checked::map map::preimage_range(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_map_preimage_range_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+isl::checked::map map::project_out_all_params() const
+{
+  auto res = isl_map_project_out_all_params(copy());
+  return manage(res);
+}
+
+isl::checked::set map::range() const
+{
+  auto res = isl_map_range(copy());
+  return manage(res);
+}
+
+isl::checked::map map::range_factor_domain() const
+{
+  auto res = isl_map_range_factor_domain(copy());
+  return manage(res);
+}
+
+isl::checked::map map::range_factor_range() const
+{
+  auto res = isl_map_range_factor_range(copy());
+  return manage(res);
+}
+
+isl::checked::map map::range_product(isl::checked::map map2) const
+{
+  auto res = isl_map_range_product(copy(), map2.release());
+  return manage(res);
+}
+
+isl::checked::map map::range_reverse() const
+{
+  auto res = isl_map_range_reverse(copy());
+  return manage(res);
+}
+
+isl::checked::map map::reverse() const
+{
+  auto res = isl_map_reverse(copy());
+  return manage(res);
+}
+
+isl::checked::basic_map map::sample() const
+{
+  auto res = isl_map_sample(copy());
+  return manage(res);
+}
+
+isl::checked::map map::subtract(isl::checked::map map2) const
+{
+  auto res = isl_map_subtract(copy(), map2.release());
+  return manage(res);
+}
+
+isl::checked::map map::uncurry() const
+{
+  auto res = isl_map_uncurry(copy());
+  return manage(res);
+}
+
+isl::checked::map map::unite(isl::checked::map map2) const
+{
+  auto res = isl_map_union(copy(), map2.release());
+  return manage(res);
+}
+
+isl::checked::map map::universe(isl::checked::space space)
+{
+  auto res = isl_map_universe(space.release());
+  return manage(res);
+}
+
+isl::checked::basic_map map::unshifted_simple_hull() const
+{
+  auto res = isl_map_unshifted_simple_hull(copy());
+  return manage(res);
+}
+
+isl::checked::map map::upper_bound(isl::checked::multi_pw_aff upper) const
+{
+  auto res = isl_map_upper_bound_multi_pw_aff(copy(), upper.release());
+  return manage(res);
+}
+
+isl::checked::map map::upper_bound(isl::checked::multi_val upper) const
+{
+  auto res = isl_map_upper_bound_multi_val(copy(), upper.release());
+  return manage(res);
+}
+
+isl::checked::set map::wrap() const
+{
+  auto res = isl_map_wrap(copy());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const map &obj)
+{
+  char *str = isl_map_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_aff
+multi_aff manage(__isl_take isl_multi_aff *ptr) {
+  return multi_aff(ptr);
+}
+multi_aff manage_copy(__isl_keep isl_multi_aff *ptr) {
+  ptr = isl_multi_aff_copy(ptr);
+  return multi_aff(ptr);
+}
+
+multi_aff::multi_aff()
+    : ptr(nullptr) {}
+
+multi_aff::multi_aff(const multi_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_aff::multi_aff(__isl_take isl_multi_aff *ptr)
+    : ptr(ptr) {}
+
+multi_aff::multi_aff(isl::checked::aff aff)
+{
+  auto res = isl_multi_aff_from_aff(aff.release());
+  ptr = res;
+}
+
+multi_aff::multi_aff(isl::checked::space space, isl::checked::aff_list list)
+{
+  auto res = isl_multi_aff_from_aff_list(space.release(), list.release());
+  ptr = res;
+}
+
+multi_aff::multi_aff(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_aff &multi_aff::operator=(multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_aff::~multi_aff() {
+  if (ptr)
+    isl_multi_aff_free(ptr);
+}
+
+__isl_give isl_multi_aff *multi_aff::copy() const & {
+  return isl_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_aff *multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_aff *multi_aff::release() {
+  isl_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx multi_aff::ctx() const {
+  return isl::checked::ctx(isl_multi_aff_get_ctx(ptr));
+}
+
+isl::checked::multi_aff multi_aff::add(isl::checked::multi_aff multi2) const
+{
+  auto res = isl_multi_aff_add(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::add_constant(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_aff_add_constant_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::add_constant(isl::checked::val v) const
+{
+  auto res = isl_multi_aff_add_constant_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::add_constant(long v) const
+{
+  return this->add_constant(isl::checked::val(ctx(), v));
+}
+
+isl::checked::basic_set multi_aff::bind(isl::checked::multi_id tuple) const
+{
+  auto res = isl_multi_aff_bind(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::bind_domain(isl::checked::multi_id tuple) const
+{
+  auto res = isl_multi_aff_bind_domain(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::bind_domain_wrapped_domain(isl::checked::multi_id tuple) const
+{
+  auto res = isl_multi_aff_bind_domain_wrapped_domain(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::domain_map(isl::checked::space space)
+{
+  auto res = isl_multi_aff_domain_map(space.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::flat_range_product(isl::checked::multi_aff multi2) const
+{
+  auto res = isl_multi_aff_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::floor() const
+{
+  auto res = isl_multi_aff_floor(copy());
+  return manage(res);
+}
+
+isl::checked::aff multi_aff::at(int pos) const
+{
+  auto res = isl_multi_aff_get_at(get(), pos);
+  return manage(res);
+}
+
+isl::checked::aff multi_aff::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::checked::multi_val multi_aff::constant_multi_val() const
+{
+  auto res = isl_multi_aff_get_constant_multi_val(get());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_aff::get_constant_multi_val() const
+{
+  return constant_multi_val();
+}
+
+isl::checked::space multi_aff::space() const
+{
+  auto res = isl_multi_aff_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space multi_aff::get_space() const
+{
+  return space();
+}
+
+isl::checked::multi_aff multi_aff::gist(isl::checked::set context) const
+{
+  auto res = isl_multi_aff_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::identity() const
+{
+  auto res = isl_multi_aff_identity_multi_aff(copy());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::identity_on_domain(isl::checked::space space)
+{
+  auto res = isl_multi_aff_identity_on_domain_space(space.release());
+  return manage(res);
+}
+
+boolean multi_aff::involves_locals() const
+{
+  auto res = isl_multi_aff_involves_locals(get());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::neg() const
+{
+  auto res = isl_multi_aff_neg(copy());
+  return manage(res);
+}
+
+boolean multi_aff::plain_is_equal(const isl::checked::multi_aff &multi2) const
+{
+  auto res = isl_multi_aff_plain_is_equal(get(), multi2.get());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::product(isl::checked::multi_aff multi2) const
+{
+  auto res = isl_multi_aff_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::pullback(isl::checked::multi_aff ma2) const
+{
+  auto res = isl_multi_aff_pullback_multi_aff(copy(), ma2.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::range_map(isl::checked::space space)
+{
+  auto res = isl_multi_aff_range_map(space.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::range_product(isl::checked::multi_aff multi2) const
+{
+  auto res = isl_multi_aff_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::scale(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_aff_scale_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::scale(isl::checked::val v) const
+{
+  auto res = isl_multi_aff_scale_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::scale(long v) const
+{
+  return this->scale(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_aff multi_aff::scale_down(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_aff_scale_down_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::scale_down(isl::checked::val v) const
+{
+  auto res = isl_multi_aff_scale_down_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::scale_down(long v) const
+{
+  return this->scale_down(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_aff multi_aff::set_at(int pos, isl::checked::aff el) const
+{
+  auto res = isl_multi_aff_set_at(copy(), pos, el.release());
+  return manage(res);
+}
+
+class size multi_aff::size() const
+{
+  auto res = isl_multi_aff_size(get());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::sub(isl::checked::multi_aff multi2) const
+{
+  auto res = isl_multi_aff_sub(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_aff multi_aff::zero(isl::checked::space space)
+{
+  auto res = isl_multi_aff_zero(space.release());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_aff &obj)
+{
+  char *str = isl_multi_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_id
+multi_id manage(__isl_take isl_multi_id *ptr) {
+  return multi_id(ptr);
+}
+multi_id manage_copy(__isl_keep isl_multi_id *ptr) {
+  ptr = isl_multi_id_copy(ptr);
+  return multi_id(ptr);
+}
+
+multi_id::multi_id()
+    : ptr(nullptr) {}
+
+multi_id::multi_id(const multi_id &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_id::multi_id(__isl_take isl_multi_id *ptr)
+    : ptr(ptr) {}
+
+multi_id::multi_id(isl::checked::space space, isl::checked::id_list list)
+{
+  auto res = isl_multi_id_from_id_list(space.release(), list.release());
+  ptr = res;
+}
+
+multi_id::multi_id(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_id_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_id &multi_id::operator=(multi_id obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_id::~multi_id() {
+  if (ptr)
+    isl_multi_id_free(ptr);
+}
+
+__isl_give isl_multi_id *multi_id::copy() const & {
+  return isl_multi_id_copy(ptr);
+}
+
+__isl_keep isl_multi_id *multi_id::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_id *multi_id::release() {
+  isl_multi_id *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_id::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx multi_id::ctx() const {
+  return isl::checked::ctx(isl_multi_id_get_ctx(ptr));
+}
+
+isl::checked::multi_id multi_id::flat_range_product(isl::checked::multi_id multi2) const
+{
+  auto res = isl_multi_id_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::id multi_id::at(int pos) const
+{
+  auto res = isl_multi_id_get_at(get(), pos);
+  return manage(res);
+}
+
+isl::checked::id multi_id::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::checked::space multi_id::space() const
+{
+  auto res = isl_multi_id_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space multi_id::get_space() const
+{
+  return space();
+}
+
+boolean multi_id::plain_is_equal(const isl::checked::multi_id &multi2) const
+{
+  auto res = isl_multi_id_plain_is_equal(get(), multi2.get());
+  return manage(res);
+}
+
+isl::checked::multi_id multi_id::range_product(isl::checked::multi_id multi2) const
+{
+  auto res = isl_multi_id_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_id multi_id::set_at(int pos, isl::checked::id el) const
+{
+  auto res = isl_multi_id_set_at(copy(), pos, el.release());
+  return manage(res);
+}
+
+isl::checked::multi_id multi_id::set_at(int pos, const std::string &el) const
+{
+  return this->set_at(pos, isl::checked::id(ctx(), el));
+}
+
+class size multi_id::size() const
+{
+  auto res = isl_multi_id_size(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_id &obj)
+{
+  char *str = isl_multi_id_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_pw_aff
+multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr) {
+  return multi_pw_aff(ptr);
+}
+multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr) {
+  ptr = isl_multi_pw_aff_copy(ptr);
+  return multi_pw_aff(ptr);
+}
+
+multi_pw_aff::multi_pw_aff()
+    : ptr(nullptr) {}
+
+multi_pw_aff::multi_pw_aff(const multi_pw_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_pw_aff::multi_pw_aff(__isl_take isl_multi_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_pw_aff::multi_pw_aff(isl::checked::multi_aff ma)
+{
+  auto res = isl_multi_pw_aff_from_multi_aff(ma.release());
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::checked::pw_aff pa)
+{
+  auto res = isl_multi_pw_aff_from_pw_aff(pa.release());
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::checked::space space, isl::checked::pw_aff_list list)
+{
+  auto res = isl_multi_pw_aff_from_pw_aff_list(space.release(), list.release());
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::checked::pw_multi_aff pma)
+{
+  auto res = isl_multi_pw_aff_from_pw_multi_aff(pma.release());
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_pw_aff &multi_pw_aff::operator=(multi_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_pw_aff::~multi_pw_aff() {
+  if (ptr)
+    isl_multi_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::copy() const & {
+  return isl_multi_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_pw_aff *multi_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::release() {
+  isl_multi_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx multi_pw_aff::ctx() const {
+  return isl::checked::ctx(isl_multi_pw_aff_get_ctx(ptr));
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::add(isl::checked::multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_add(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::add_constant(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_pw_aff_add_constant_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::add_constant(isl::checked::val v) const
+{
+  auto res = isl_multi_pw_aff_add_constant_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::add_constant(long v) const
+{
+  return this->add_constant(isl::checked::val(ctx(), v));
+}
+
+isl::checked::set multi_pw_aff::bind(isl::checked::multi_id tuple) const
+{
+  auto res = isl_multi_pw_aff_bind(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::bind_domain(isl::checked::multi_id tuple) const
+{
+  auto res = isl_multi_pw_aff_bind_domain(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::bind_domain_wrapped_domain(isl::checked::multi_id tuple) const
+{
+  auto res = isl_multi_pw_aff_bind_domain_wrapped_domain(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::coalesce() const
+{
+  auto res = isl_multi_pw_aff_coalesce(copy());
+  return manage(res);
+}
+
+isl::checked::set multi_pw_aff::domain() const
+{
+  auto res = isl_multi_pw_aff_domain(copy());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::flat_range_product(isl::checked::multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::pw_aff multi_pw_aff::at(int pos) const
+{
+  auto res = isl_multi_pw_aff_get_at(get(), pos);
+  return manage(res);
+}
+
+isl::checked::pw_aff multi_pw_aff::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::checked::space multi_pw_aff::space() const
+{
+  auto res = isl_multi_pw_aff_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space multi_pw_aff::get_space() const
+{
+  return space();
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::gist(isl::checked::set set) const
+{
+  auto res = isl_multi_pw_aff_gist(copy(), set.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::identity() const
+{
+  auto res = isl_multi_pw_aff_identity_multi_pw_aff(copy());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::identity_on_domain(isl::checked::space space)
+{
+  auto res = isl_multi_pw_aff_identity_on_domain_space(space.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::intersect_domain(isl::checked::set domain) const
+{
+  auto res = isl_multi_pw_aff_intersect_domain(copy(), domain.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::intersect_params(isl::checked::set set) const
+{
+  auto res = isl_multi_pw_aff_intersect_params(copy(), set.release());
+  return manage(res);
+}
+
+boolean multi_pw_aff::involves_param(const isl::checked::id &id) const
+{
+  auto res = isl_multi_pw_aff_involves_param_id(get(), id.get());
+  return manage(res);
+}
+
+boolean multi_pw_aff::involves_param(const std::string &id) const
+{
+  return this->involves_param(isl::checked::id(ctx(), id));
+}
+
+boolean multi_pw_aff::involves_param(const isl::checked::id_list &list) const
+{
+  auto res = isl_multi_pw_aff_involves_param_id_list(get(), list.get());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::neg() const
+{
+  auto res = isl_multi_pw_aff_neg(copy());
+  return manage(res);
+}
+
+boolean multi_pw_aff::plain_is_equal(const isl::checked::multi_pw_aff &multi2) const
+{
+  auto res = isl_multi_pw_aff_plain_is_equal(get(), multi2.get());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::product(isl::checked::multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::pullback(isl::checked::multi_aff ma) const
+{
+  auto res = isl_multi_pw_aff_pullback_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::pullback(isl::checked::multi_pw_aff mpa2) const
+{
+  auto res = isl_multi_pw_aff_pullback_multi_pw_aff(copy(), mpa2.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::pullback(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_multi_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::range_product(isl::checked::multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::scale(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_pw_aff_scale_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::scale(isl::checked::val v) const
+{
+  auto res = isl_multi_pw_aff_scale_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::scale(long v) const
+{
+  return this->scale(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::scale_down(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_pw_aff_scale_down_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::scale_down(isl::checked::val v) const
+{
+  auto res = isl_multi_pw_aff_scale_down_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::scale_down(long v) const
+{
+  return this->scale_down(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::set_at(int pos, isl::checked::pw_aff el) const
+{
+  auto res = isl_multi_pw_aff_set_at(copy(), pos, el.release());
+  return manage(res);
+}
+
+class size multi_pw_aff::size() const
+{
+  auto res = isl_multi_pw_aff_size(get());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::sub(isl::checked::multi_pw_aff multi2) const
+{
+  auto res = isl_multi_pw_aff_sub(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_pw_aff multi_pw_aff::zero(isl::checked::space space)
+{
+  auto res = isl_multi_pw_aff_zero(space.release());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_pw_aff &obj)
+{
+  char *str = isl_multi_pw_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_union_pw_aff
+multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr) {
+  return multi_union_pw_aff(ptr);
+}
+multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr) {
+  ptr = isl_multi_union_pw_aff_copy(ptr);
+  return multi_union_pw_aff(ptr);
+}
+
+multi_union_pw_aff::multi_union_pw_aff()
+    : ptr(nullptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(const multi_union_pw_aff &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_union_pw_aff::multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::checked::multi_pw_aff mpa)
+{
+  auto res = isl_multi_union_pw_aff_from_multi_pw_aff(mpa.release());
+  ptr = res;
+}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::checked::union_pw_aff upa)
+{
+  auto res = isl_multi_union_pw_aff_from_union_pw_aff(upa.release());
+  ptr = res;
+}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::checked::space space, isl::checked::union_pw_aff_list list)
+{
+  auto res = isl_multi_union_pw_aff_from_union_pw_aff_list(space.release(), list.release());
+  ptr = res;
+}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_union_pw_aff &multi_union_pw_aff::operator=(multi_union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_union_pw_aff::~multi_union_pw_aff() {
+  if (ptr)
+    isl_multi_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::copy() const & {
+  return isl_multi_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_union_pw_aff *multi_union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::release() {
+  isl_multi_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx multi_union_pw_aff::ctx() const {
+  return isl::checked::ctx(isl_multi_union_pw_aff_get_ctx(ptr));
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::add(isl::checked::multi_union_pw_aff multi2) const
+{
+  auto res = isl_multi_union_pw_aff_add(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::union_set multi_union_pw_aff::bind(isl::checked::multi_id tuple) const
+{
+  auto res = isl_multi_union_pw_aff_bind(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::coalesce() const
+{
+  auto res = isl_multi_union_pw_aff_coalesce(copy());
+  return manage(res);
+}
+
+isl::checked::union_set multi_union_pw_aff::domain() const
+{
+  auto res = isl_multi_union_pw_aff_domain(copy());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::flat_range_product(isl::checked::multi_union_pw_aff multi2) const
+{
+  auto res = isl_multi_union_pw_aff_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_aff multi_union_pw_aff::at(int pos) const
+{
+  auto res = isl_multi_union_pw_aff_get_at(get(), pos);
+  return manage(res);
+}
+
+isl::checked::union_pw_aff multi_union_pw_aff::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::checked::space multi_union_pw_aff::space() const
+{
+  auto res = isl_multi_union_pw_aff_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space multi_union_pw_aff::get_space() const
+{
+  return space();
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::gist(isl::checked::union_set context) const
+{
+  auto res = isl_multi_union_pw_aff_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::intersect_domain(isl::checked::union_set uset) const
+{
+  auto res = isl_multi_union_pw_aff_intersect_domain(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::intersect_params(isl::checked::set params) const
+{
+  auto res = isl_multi_union_pw_aff_intersect_params(copy(), params.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::neg() const
+{
+  auto res = isl_multi_union_pw_aff_neg(copy());
+  return manage(res);
+}
+
+boolean multi_union_pw_aff::plain_is_equal(const isl::checked::multi_union_pw_aff &multi2) const
+{
+  auto res = isl_multi_union_pw_aff_plain_is_equal(get(), multi2.get());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::pullback(isl::checked::union_pw_multi_aff upma) const
+{
+  auto res = isl_multi_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::range_product(isl::checked::multi_union_pw_aff multi2) const
+{
+  auto res = isl_multi_union_pw_aff_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::scale(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_union_pw_aff_scale_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::scale(isl::checked::val v) const
+{
+  auto res = isl_multi_union_pw_aff_scale_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::scale(long v) const
+{
+  return this->scale(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::scale_down(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_union_pw_aff_scale_down_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::scale_down(isl::checked::val v) const
+{
+  auto res = isl_multi_union_pw_aff_scale_down_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::scale_down(long v) const
+{
+  return this->scale_down(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::set_at(int pos, isl::checked::union_pw_aff el) const
+{
+  auto res = isl_multi_union_pw_aff_set_at(copy(), pos, el.release());
+  return manage(res);
+}
+
+class size multi_union_pw_aff::size() const
+{
+  auto res = isl_multi_union_pw_aff_size(get());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::sub(isl::checked::multi_union_pw_aff multi2) const
+{
+  auto res = isl_multi_union_pw_aff_sub(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::union_add(isl::checked::multi_union_pw_aff mupa2) const
+{
+  auto res = isl_multi_union_pw_aff_union_add(copy(), mupa2.release());
+  return manage(res);
+}
+
+isl::checked::multi_union_pw_aff multi_union_pw_aff::zero(isl::checked::space space)
+{
+  auto res = isl_multi_union_pw_aff_zero(space.release());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_union_pw_aff &obj)
+{
+  char *str = isl_multi_union_pw_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_val
+multi_val manage(__isl_take isl_multi_val *ptr) {
+  return multi_val(ptr);
+}
+multi_val manage_copy(__isl_keep isl_multi_val *ptr) {
+  ptr = isl_multi_val_copy(ptr);
+  return multi_val(ptr);
+}
+
+multi_val::multi_val()
+    : ptr(nullptr) {}
+
+multi_val::multi_val(const multi_val &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+multi_val::multi_val(__isl_take isl_multi_val *ptr)
+    : ptr(ptr) {}
+
+multi_val::multi_val(isl::checked::space space, isl::checked::val_list list)
+{
+  auto res = isl_multi_val_from_val_list(space.release(), list.release());
+  ptr = res;
+}
+
+multi_val::multi_val(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_multi_val_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+multi_val &multi_val::operator=(multi_val obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_val::~multi_val() {
+  if (ptr)
+    isl_multi_val_free(ptr);
+}
+
+__isl_give isl_multi_val *multi_val::copy() const & {
+  return isl_multi_val_copy(ptr);
+}
+
+__isl_keep isl_multi_val *multi_val::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_val *multi_val::release() {
+  isl_multi_val *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_val::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx multi_val::ctx() const {
+  return isl::checked::ctx(isl_multi_val_get_ctx(ptr));
+}
+
+isl::checked::multi_val multi_val::add(isl::checked::multi_val multi2) const
+{
+  auto res = isl_multi_val_add(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::add(isl::checked::val v) const
+{
+  auto res = isl_multi_val_add_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::add(long v) const
+{
+  return this->add(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_val multi_val::flat_range_product(isl::checked::multi_val multi2) const
+{
+  auto res = isl_multi_val_flat_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::val multi_val::at(int pos) const
+{
+  auto res = isl_multi_val_get_at(get(), pos);
+  return manage(res);
+}
+
+isl::checked::val multi_val::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::checked::space multi_val::space() const
+{
+  auto res = isl_multi_val_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space multi_val::get_space() const
+{
+  return space();
+}
+
+isl::checked::multi_val multi_val::neg() const
+{
+  auto res = isl_multi_val_neg(copy());
+  return manage(res);
+}
+
+boolean multi_val::plain_is_equal(const isl::checked::multi_val &multi2) const
+{
+  auto res = isl_multi_val_plain_is_equal(get(), multi2.get());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::product(isl::checked::multi_val multi2) const
+{
+  auto res = isl_multi_val_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::range_product(isl::checked::multi_val multi2) const
+{
+  auto res = isl_multi_val_range_product(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::scale(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_val_scale_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::scale(isl::checked::val v) const
+{
+  auto res = isl_multi_val_scale_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::scale(long v) const
+{
+  return this->scale(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_val multi_val::scale_down(isl::checked::multi_val mv) const
+{
+  auto res = isl_multi_val_scale_down_multi_val(copy(), mv.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::scale_down(isl::checked::val v) const
+{
+  auto res = isl_multi_val_scale_down_val(copy(), v.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::scale_down(long v) const
+{
+  return this->scale_down(isl::checked::val(ctx(), v));
+}
+
+isl::checked::multi_val multi_val::set_at(int pos, isl::checked::val el) const
+{
+  auto res = isl_multi_val_set_at(copy(), pos, el.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::set_at(int pos, long el) const
+{
+  return this->set_at(pos, isl::checked::val(ctx(), el));
+}
+
+class size multi_val::size() const
+{
+  auto res = isl_multi_val_size(get());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::sub(isl::checked::multi_val multi2) const
+{
+  auto res = isl_multi_val_sub(copy(), multi2.release());
+  return manage(res);
+}
+
+isl::checked::multi_val multi_val::zero(isl::checked::space space)
+{
+  auto res = isl_multi_val_zero(space.release());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_val &obj)
+{
+  char *str = isl_multi_val_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::point
+point manage(__isl_take isl_point *ptr) {
+  return point(ptr);
+}
+point manage_copy(__isl_keep isl_point *ptr) {
+  ptr = isl_point_copy(ptr);
+  return point(ptr);
+}
+
+point::point()
+    : ptr(nullptr) {}
+
+point::point(const point &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+point::point(__isl_take isl_point *ptr)
+    : ptr(ptr) {}
+
+point &point::operator=(point obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+point::~point() {
+  if (ptr)
+    isl_point_free(ptr);
+}
+
+__isl_give isl_point *point::copy() const & {
+  return isl_point_copy(ptr);
+}
+
+__isl_keep isl_point *point::get() const {
+  return ptr;
+}
+
+__isl_give isl_point *point::release() {
+  isl_point *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool point::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx point::ctx() const {
+  return isl::checked::ctx(isl_point_get_ctx(ptr));
+}
+
+isl::checked::multi_val point::multi_val() const
+{
+  auto res = isl_point_get_multi_val(get());
+  return manage(res);
+}
 
-public:
-  inline /* implicit */ val();
-  inline /* implicit */ val(const val &obj);
-  inline explicit val(ctx ctx, const std::string &str);
-  inline explicit val(ctx ctx, long i);
-  inline val &operator=(val obj);
-  inline ~val();
-  inline __isl_give isl_val *copy() const &;
-  inline __isl_give isl_val *copy() && = delete;
-  inline __isl_keep isl_val *get() const;
-  inline __isl_give isl_val *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+isl::checked::multi_val point::get_multi_val() const
+{
+  return multi_val();
+}
 
-  inline val abs() const;
-  inline boolean abs_eq(const val &v2) const;
-  inline val add(val v2) const;
-  inline val ceil() const;
-  inline int cmp_si(long i) const;
-  inline val div(val v2) const;
-  inline boolean eq(const val &v2) const;
-  inline val floor() const;
-  inline val gcd(val v2) const;
-  inline boolean ge(const val &v2) const;
-  inline boolean gt(const val &v2) const;
-  static inline val infty(ctx ctx);
-  inline val inv() const;
-  inline boolean is_divisible_by(const val &v2) const;
-  inline boolean is_infty() const;
-  inline boolean is_int() const;
-  inline boolean is_nan() const;
-  inline boolean is_neg() const;
-  inline boolean is_neginfty() const;
-  inline boolean is_negone() const;
-  inline boolean is_nonneg() const;
-  inline boolean is_nonpos() const;
-  inline boolean is_one() const;
-  inline boolean is_pos() const;
-  inline boolean is_rat() const;
-  inline boolean is_zero() const;
-  inline boolean le(const val &v2) const;
-  inline boolean lt(const val &v2) const;
-  inline val max(val v2) const;
-  inline val min(val v2) const;
-  inline val mod(val v2) const;
-  inline val mul(val v2) const;
-  static inline val nan(ctx ctx);
-  inline boolean ne(const val &v2) const;
-  inline val neg() const;
-  static inline val neginfty(ctx ctx);
-  static inline val negone(ctx ctx);
-  static inline val one(ctx ctx);
-  inline val pow2() const;
-  inline int sgn() const;
-  inline val sub(val v2) const;
-  inline val trunc() const;
-  static inline val zero(ctx ctx);
-};
+inline std::ostream &operator<<(std::ostream &os, const point &obj)
+{
+  char *str = isl_point_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
 
-// implementations for isl::aff
-aff manage(__isl_take isl_aff *ptr) {
-  return aff(ptr);
+// implementations for isl::pw_aff
+pw_aff manage(__isl_take isl_pw_aff *ptr) {
+  return pw_aff(ptr);
 }
-aff manage_copy(__isl_keep isl_aff *ptr) {
-  ptr = isl_aff_copy(ptr);
-  return aff(ptr);
+pw_aff manage_copy(__isl_keep isl_pw_aff *ptr) {
+  ptr = isl_pw_aff_copy(ptr);
+  return pw_aff(ptr);
 }
 
-aff::aff()
+pw_aff::pw_aff()
     : ptr(nullptr) {}
 
-aff::aff(const aff &obj)
+pw_aff::pw_aff(const pw_aff &obj)
     : ptr(nullptr)
 {
   ptr = obj.copy();
 }
 
-aff::aff(__isl_take isl_aff *ptr)
+pw_aff::pw_aff(__isl_take isl_pw_aff *ptr)
     : ptr(ptr) {}
 
-aff::aff(ctx ctx, const std::string &str)
+pw_aff::pw_aff(isl::checked::aff aff)
 {
-  auto res = isl_aff_read_from_str(ctx.release(), str.c_str());
+  auto res = isl_pw_aff_from_aff(aff.release());
   ptr = res;
 }
 
-aff &aff::operator=(aff obj) {
+pw_aff::pw_aff(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+pw_aff &pw_aff::operator=(pw_aff obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-aff::~aff() {
+pw_aff::~pw_aff() {
   if (ptr)
-    isl_aff_free(ptr);
+    isl_pw_aff_free(ptr);
 }
 
-__isl_give isl_aff *aff::copy() const & {
-  return isl_aff_copy(ptr);
+__isl_give isl_pw_aff *pw_aff::copy() const & {
+  return isl_pw_aff_copy(ptr);
 }
 
-__isl_keep isl_aff *aff::get() const {
+__isl_keep isl_pw_aff *pw_aff::get() const {
   return ptr;
 }
 
-__isl_give isl_aff *aff::release() {
-  isl_aff *tmp = ptr;
+__isl_give isl_pw_aff *pw_aff::release() {
+  isl_pw_aff *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool aff::is_null() const {
+bool pw_aff::is_null() const {
   return ptr == nullptr;
 }
 
-ctx aff::get_ctx() const {
-  return ctx(isl_aff_get_ctx(ptr));
+isl::checked::ctx pw_aff::ctx() const {
+  return isl::checked::ctx(isl_pw_aff_get_ctx(ptr));
 }
 
-aff aff::add(aff aff2) const
+isl::checked::pw_aff pw_aff::add(isl::checked::pw_aff pwaff2) const
 {
-  auto res = isl_aff_add(copy(), aff2.release());
+  auto res = isl_pw_aff_add(copy(), pwaff2.release());
   return manage(res);
 }
 
-aff aff::ceil() const
+isl::checked::pw_aff pw_aff::add_constant(isl::checked::val v) const
 {
-  auto res = isl_aff_ceil(copy());
+  auto res = isl_pw_aff_add_constant_val(copy(), v.release());
   return manage(res);
 }
 
-aff aff::div(aff aff2) const
+isl::checked::pw_aff pw_aff::add_constant(long v) const
 {
-  auto res = isl_aff_div(copy(), aff2.release());
+  return this->add_constant(isl::checked::val(ctx(), v));
+}
+
+isl::checked::aff pw_aff::as_aff() const
+{
+  auto res = isl_pw_aff_as_aff(copy());
   return manage(res);
 }
 
-set aff::eq_set(aff aff2) const
+isl::checked::set pw_aff::bind(isl::checked::id id) const
 {
-  auto res = isl_aff_eq_set(copy(), aff2.release());
+  auto res = isl_pw_aff_bind_id(copy(), id.release());
   return manage(res);
 }
 
-aff aff::floor() const
+isl::checked::set pw_aff::bind(const std::string &id) const
 {
-  auto res = isl_aff_floor(copy());
+  return this->bind(isl::checked::id(ctx(), id));
+}
+
+isl::checked::pw_aff pw_aff::bind_domain(isl::checked::multi_id tuple) const
+{
+  auto res = isl_pw_aff_bind_domain(copy(), tuple.release());
   return manage(res);
 }
 
-set aff::ge_set(aff aff2) const
+isl::checked::pw_aff pw_aff::bind_domain_wrapped_domain(isl::checked::multi_id tuple) const
 {
-  auto res = isl_aff_ge_set(copy(), aff2.release());
+  auto res = isl_pw_aff_bind_domain_wrapped_domain(copy(), tuple.release());
   return manage(res);
 }
 
-set aff::gt_set(aff aff2) const
+isl::checked::pw_aff pw_aff::ceil() const
 {
-  auto res = isl_aff_gt_set(copy(), aff2.release());
+  auto res = isl_pw_aff_ceil(copy());
   return manage(res);
 }
 
-set aff::le_set(aff aff2) const
+isl::checked::pw_aff pw_aff::coalesce() const
 {
-  auto res = isl_aff_le_set(copy(), aff2.release());
+  auto res = isl_pw_aff_coalesce(copy());
   return manage(res);
 }
 
-set aff::lt_set(aff aff2) const
+isl::checked::pw_aff pw_aff::cond(isl::checked::pw_aff pwaff_true, isl::checked::pw_aff pwaff_false) const
 {
-  auto res = isl_aff_lt_set(copy(), aff2.release());
+  auto res = isl_pw_aff_cond(copy(), pwaff_true.release(), pwaff_false.release());
   return manage(res);
 }
 
-aff aff::mod(val mod) const
+isl::checked::pw_aff pw_aff::div(isl::checked::pw_aff pa2) const
 {
-  auto res = isl_aff_mod_val(copy(), mod.release());
+  auto res = isl_pw_aff_div(copy(), pa2.release());
   return manage(res);
 }
 
-aff aff::mul(aff aff2) const
+isl::checked::set pw_aff::domain() const
 {
-  auto res = isl_aff_mul(copy(), aff2.release());
+  auto res = isl_pw_aff_domain(copy());
   return manage(res);
 }
 
-set aff::ne_set(aff aff2) const
+isl::checked::set pw_aff::eq_set(isl::checked::pw_aff pwaff2) const
 {
-  auto res = isl_aff_ne_set(copy(), aff2.release());
+  auto res = isl_pw_aff_eq_set(copy(), pwaff2.release());
   return manage(res);
 }
 
-aff aff::neg() const
+isl::checked::val pw_aff::eval(isl::checked::point pnt) const
 {
-  auto res = isl_aff_neg(copy());
+  auto res = isl_pw_aff_eval(copy(), pnt.release());
   return manage(res);
 }
 
-aff aff::pullback(multi_aff ma) const
+isl::checked::pw_aff pw_aff::floor() const
 {
-  auto res = isl_aff_pullback_multi_aff(copy(), ma.release());
+  auto res = isl_pw_aff_floor(copy());
   return manage(res);
 }
 
-aff aff::scale(val v) const
+isl::checked::set pw_aff::ge_set(isl::checked::pw_aff pwaff2) const
 {
-  auto res = isl_aff_scale_val(copy(), v.release());
+  auto res = isl_pw_aff_ge_set(copy(), pwaff2.release());
   return manage(res);
 }
 
-aff aff::scale_down(val v) const
+isl::checked::pw_aff pw_aff::gist(isl::checked::set context) const
 {
-  auto res = isl_aff_scale_down_val(copy(), v.release());
+  auto res = isl_pw_aff_gist(copy(), context.release());
   return manage(res);
 }
 
-aff aff::sub(aff aff2) const
+isl::checked::set pw_aff::gt_set(isl::checked::pw_aff pwaff2) const
 {
-  auto res = isl_aff_sub(copy(), aff2.release());
+  auto res = isl_pw_aff_gt_set(copy(), pwaff2.release());
   return manage(res);
 }
 
-// implementations for isl::ast_build
-ast_build manage(__isl_take isl_ast_build *ptr) {
-  return ast_build(ptr);
+isl::checked::pw_aff pw_aff::intersect_domain(isl::checked::set set) const
+{
+  auto res = isl_pw_aff_intersect_domain(copy(), set.release());
+  return manage(res);
 }
-ast_build manage_copy(__isl_keep isl_ast_build *ptr) {
-  ptr = isl_ast_build_copy(ptr);
-  return ast_build(ptr);
+
+isl::checked::pw_aff pw_aff::intersect_params(isl::checked::set set) const
+{
+  auto res = isl_pw_aff_intersect_params(copy(), set.release());
+  return manage(res);
 }
 
-ast_build::ast_build()
-    : ptr(nullptr) {}
+boolean pw_aff::isa_aff() const
+{
+  auto res = isl_pw_aff_isa_aff(get());
+  return manage(res);
+}
 
-ast_build::ast_build(const ast_build &obj)
-    : ptr(nullptr)
+isl::checked::set pw_aff::le_set(isl::checked::pw_aff pwaff2) const
 {
-  ptr = obj.copy();
+  auto res = isl_pw_aff_le_set(copy(), pwaff2.release());
+  return manage(res);
 }
 
-ast_build::ast_build(__isl_take isl_ast_build *ptr)
-    : ptr(ptr) {}
+isl::checked::set pw_aff::lt_set(isl::checked::pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_lt_set(copy(), pwaff2.release());
+  return manage(res);
+}
 
-ast_build::ast_build(ctx ctx)
+isl::checked::pw_aff pw_aff::max(isl::checked::pw_aff pwaff2) const
 {
-  auto res = isl_ast_build_alloc(ctx.release());
-  ptr = res;
+  auto res = isl_pw_aff_max(copy(), pwaff2.release());
+  return manage(res);
 }
 
-ast_build &ast_build::operator=(ast_build obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::checked::pw_aff pw_aff::min(isl::checked::pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_min(copy(), pwaff2.release());
+  return manage(res);
 }
 
-ast_build::~ast_build() {
-  if (ptr)
-    isl_ast_build_free(ptr);
+isl::checked::pw_aff pw_aff::mod(isl::checked::val mod) const
+{
+  auto res = isl_pw_aff_mod_val(copy(), mod.release());
+  return manage(res);
 }
 
-__isl_give isl_ast_build *ast_build::copy() const & {
-  return isl_ast_build_copy(ptr);
+isl::checked::pw_aff pw_aff::mod(long mod) const
+{
+  return this->mod(isl::checked::val(ctx(), mod));
 }
 
-__isl_keep isl_ast_build *ast_build::get() const {
-  return ptr;
+isl::checked::pw_aff pw_aff::mul(isl::checked::pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_mul(copy(), pwaff2.release());
+  return manage(res);
 }
 
-__isl_give isl_ast_build *ast_build::release() {
-  isl_ast_build *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::checked::set pw_aff::ne_set(isl::checked::pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_ne_set(copy(), pwaff2.release());
+  return manage(res);
 }
 
-bool ast_build::is_null() const {
-  return ptr == nullptr;
+isl::checked::pw_aff pw_aff::neg() const
+{
+  auto res = isl_pw_aff_neg(copy());
+  return manage(res);
 }
 
-ctx ast_build::get_ctx() const {
-  return ctx(isl_ast_build_get_ctx(ptr));
+isl::checked::pw_aff pw_aff::param_on_domain(isl::checked::set domain, isl::checked::id id)
+{
+  auto res = isl_pw_aff_param_on_domain_id(domain.release(), id.release());
+  return manage(res);
 }
 
-ast_expr ast_build::access_from(pw_multi_aff pma) const
+isl::checked::pw_aff pw_aff::pullback(isl::checked::multi_aff ma) const
 {
-  auto res = isl_ast_build_access_from_pw_multi_aff(get(), pma.release());
+  auto res = isl_pw_aff_pullback_multi_aff(copy(), ma.release());
   return manage(res);
 }
 
-ast_expr ast_build::access_from(multi_pw_aff mpa) const
+isl::checked::pw_aff pw_aff::pullback(isl::checked::multi_pw_aff mpa) const
 {
-  auto res = isl_ast_build_access_from_multi_pw_aff(get(), mpa.release());
+  auto res = isl_pw_aff_pullback_multi_pw_aff(copy(), mpa.release());
   return manage(res);
 }
 
-ast_expr ast_build::call_from(pw_multi_aff pma) const
+isl::checked::pw_aff pw_aff::pullback(isl::checked::pw_multi_aff pma) const
 {
-  auto res = isl_ast_build_call_from_pw_multi_aff(get(), pma.release());
+  auto res = isl_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
   return manage(res);
 }
 
-ast_expr ast_build::call_from(multi_pw_aff mpa) const
+isl::checked::pw_aff pw_aff::scale(isl::checked::val v) const
 {
-  auto res = isl_ast_build_call_from_multi_pw_aff(get(), mpa.release());
+  auto res = isl_pw_aff_scale_val(copy(), v.release());
   return manage(res);
 }
 
-ast_expr ast_build::expr_from(set set) const
+isl::checked::pw_aff pw_aff::scale(long v) const
 {
-  auto res = isl_ast_build_expr_from_set(get(), set.release());
+  return this->scale(isl::checked::val(ctx(), v));
+}
+
+isl::checked::pw_aff pw_aff::scale_down(isl::checked::val f) const
+{
+  auto res = isl_pw_aff_scale_down_val(copy(), f.release());
   return manage(res);
 }
 
-ast_expr ast_build::expr_from(pw_aff pa) const
+isl::checked::pw_aff pw_aff::scale_down(long f) const
 {
-  auto res = isl_ast_build_expr_from_pw_aff(get(), pa.release());
+  return this->scale_down(isl::checked::val(ctx(), f));
+}
+
+isl::checked::pw_aff pw_aff::sub(isl::checked::pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_sub(copy(), pwaff2.release());
   return manage(res);
 }
 
-ast_build ast_build::from_context(set set)
+isl::checked::pw_aff pw_aff::subtract_domain(isl::checked::set set) const
 {
-  auto res = isl_ast_build_from_context(set.release());
+  auto res = isl_pw_aff_subtract_domain(copy(), set.release());
   return manage(res);
 }
 
-ast_node ast_build::node_from_schedule_map(union_map schedule) const
+isl::checked::pw_aff pw_aff::tdiv_q(isl::checked::pw_aff pa2) const
 {
-  auto res = isl_ast_build_node_from_schedule_map(get(), schedule.release());
+  auto res = isl_pw_aff_tdiv_q(copy(), pa2.release());
   return manage(res);
 }
 
-// implementations for isl::ast_expr
-ast_expr manage(__isl_take isl_ast_expr *ptr) {
-  return ast_expr(ptr);
+isl::checked::pw_aff pw_aff::tdiv_r(isl::checked::pw_aff pa2) const
+{
+  auto res = isl_pw_aff_tdiv_r(copy(), pa2.release());
+  return manage(res);
 }
-ast_expr manage_copy(__isl_keep isl_ast_expr *ptr) {
-  ptr = isl_ast_expr_copy(ptr);
-  return ast_expr(ptr);
+
+isl::checked::pw_aff pw_aff::union_add(isl::checked::pw_aff pwaff2) const
+{
+  auto res = isl_pw_aff_union_add(copy(), pwaff2.release());
+  return manage(res);
 }
 
-ast_expr::ast_expr()
+inline std::ostream &operator<<(std::ostream &os, const pw_aff &obj)
+{
+  char *str = isl_pw_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::pw_aff_list
+pw_aff_list manage(__isl_take isl_pw_aff_list *ptr) {
+  return pw_aff_list(ptr);
+}
+pw_aff_list manage_copy(__isl_keep isl_pw_aff_list *ptr) {
+  ptr = isl_pw_aff_list_copy(ptr);
+  return pw_aff_list(ptr);
+}
+
+pw_aff_list::pw_aff_list()
     : ptr(nullptr) {}
 
-ast_expr::ast_expr(const ast_expr &obj)
+pw_aff_list::pw_aff_list(const pw_aff_list &obj)
     : ptr(nullptr)
 {
   ptr = obj.copy();
 }
 
-ast_expr::ast_expr(__isl_take isl_ast_expr *ptr)
+pw_aff_list::pw_aff_list(__isl_take isl_pw_aff_list *ptr)
     : ptr(ptr) {}
 
+pw_aff_list::pw_aff_list(isl::checked::ctx ctx, int n)
+{
+  auto res = isl_pw_aff_list_alloc(ctx.release(), n);
+  ptr = res;
+}
+
+pw_aff_list::pw_aff_list(isl::checked::pw_aff el)
+{
+  auto res = isl_pw_aff_list_from_pw_aff(el.release());
+  ptr = res;
+}
 
-ast_expr &ast_expr::operator=(ast_expr obj) {
+pw_aff_list &pw_aff_list::operator=(pw_aff_list obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-ast_expr::~ast_expr() {
+pw_aff_list::~pw_aff_list() {
   if (ptr)
-    isl_ast_expr_free(ptr);
+    isl_pw_aff_list_free(ptr);
 }
 
-__isl_give isl_ast_expr *ast_expr::copy() const & {
-  return isl_ast_expr_copy(ptr);
+__isl_give isl_pw_aff_list *pw_aff_list::copy() const & {
+  return isl_pw_aff_list_copy(ptr);
 }
 
-__isl_keep isl_ast_expr *ast_expr::get() const {
+__isl_keep isl_pw_aff_list *pw_aff_list::get() const {
   return ptr;
 }
 
-__isl_give isl_ast_expr *ast_expr::release() {
-  isl_ast_expr *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+__isl_give isl_pw_aff_list *pw_aff_list::release() {
+  isl_pw_aff_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool pw_aff_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx pw_aff_list::ctx() const {
+  return isl::checked::ctx(isl_pw_aff_list_get_ctx(ptr));
+}
+
+isl::checked::pw_aff_list pw_aff_list::add(isl::checked::pw_aff el) const
+{
+  auto res = isl_pw_aff_list_add(copy(), el.release());
+  return manage(res);
+}
+
+isl::checked::pw_aff_list pw_aff_list::clear() const
+{
+  auto res = isl_pw_aff_list_clear(copy());
+  return manage(res);
+}
+
+isl::checked::pw_aff_list pw_aff_list::concat(isl::checked::pw_aff_list list2) const
+{
+  auto res = isl_pw_aff_list_concat(copy(), list2.release());
+  return manage(res);
+}
+
+stat pw_aff_list::foreach(const std::function<stat(isl::checked::pw_aff)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::pw_aff)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_pw_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_pw_aff_list_foreach(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::pw_aff pw_aff_list::at(int index) const
+{
+  auto res = isl_pw_aff_list_get_at(get(), index);
+  return manage(res);
 }
 
-bool ast_expr::is_null() const {
-  return ptr == nullptr;
+isl::checked::pw_aff pw_aff_list::get_at(int index) const
+{
+  return at(index);
 }
 
-ctx ast_expr::get_ctx() const {
-  return ctx(isl_ast_expr_get_ctx(ptr));
+class size pw_aff_list::size() const
+{
+  auto res = isl_pw_aff_list_size(get());
+  return manage(res);
 }
 
-std::string ast_expr::to_C_str() const
+inline std::ostream &operator<<(std::ostream &os, const pw_aff_list &obj)
 {
-  auto res = isl_ast_expr_to_C_str(get());
-  std::string tmp(res);
-  free(res);
-  return tmp;
+  char *str = isl_pw_aff_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::ast_node
-ast_node manage(__isl_take isl_ast_node *ptr) {
-  return ast_node(ptr);
+// implementations for isl::pw_multi_aff
+pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr) {
+  return pw_multi_aff(ptr);
 }
-ast_node manage_copy(__isl_keep isl_ast_node *ptr) {
-  ptr = isl_ast_node_copy(ptr);
-  return ast_node(ptr);
+pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr) {
+  ptr = isl_pw_multi_aff_copy(ptr);
+  return pw_multi_aff(ptr);
 }
 
-ast_node::ast_node()
+pw_multi_aff::pw_multi_aff()
     : ptr(nullptr) {}
 
-ast_node::ast_node(const ast_node &obj)
+pw_multi_aff::pw_multi_aff(const pw_multi_aff &obj)
     : ptr(nullptr)
 {
   ptr = obj.copy();
 }
 
-ast_node::ast_node(__isl_take isl_ast_node *ptr)
+pw_multi_aff::pw_multi_aff(__isl_take isl_pw_multi_aff *ptr)
     : ptr(ptr) {}
 
+pw_multi_aff::pw_multi_aff(isl::checked::multi_aff ma)
+{
+  auto res = isl_pw_multi_aff_from_multi_aff(ma.release());
+  ptr = res;
+}
+
+pw_multi_aff::pw_multi_aff(isl::checked::pw_aff pa)
+{
+  auto res = isl_pw_multi_aff_from_pw_aff(pa.release());
+  ptr = res;
+}
 
-ast_node &ast_node::operator=(ast_node obj) {
+pw_multi_aff::pw_multi_aff(isl::checked::ctx ctx, const std::string &str)
+{
+  auto res = isl_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+pw_multi_aff &pw_multi_aff::operator=(pw_multi_aff obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-ast_node::~ast_node() {
+pw_multi_aff::~pw_multi_aff() {
   if (ptr)
-    isl_ast_node_free(ptr);
+    isl_pw_multi_aff_free(ptr);
 }
 
-__isl_give isl_ast_node *ast_node::copy() const & {
-  return isl_ast_node_copy(ptr);
+__isl_give isl_pw_multi_aff *pw_multi_aff::copy() const & {
+  return isl_pw_multi_aff_copy(ptr);
 }
 
-__isl_keep isl_ast_node *ast_node::get() const {
+__isl_keep isl_pw_multi_aff *pw_multi_aff::get() const {
   return ptr;
 }
 
-__isl_give isl_ast_node *ast_node::release() {
-  isl_ast_node *tmp = ptr;
+__isl_give isl_pw_multi_aff *pw_multi_aff::release() {
+  isl_pw_multi_aff *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool ast_node::is_null() const {
+bool pw_multi_aff::is_null() const {
   return ptr == nullptr;
 }
 
-ctx ast_node::get_ctx() const {
-  return ctx(isl_ast_node_get_ctx(ptr));
+isl::checked::ctx pw_multi_aff::ctx() const {
+  return isl::checked::ctx(isl_pw_multi_aff_get_ctx(ptr));
 }
 
-std::string ast_node::to_C_str() const
+isl::checked::pw_multi_aff pw_multi_aff::add(isl::checked::pw_multi_aff pma2) const
 {
-  auto res = isl_ast_node_to_C_str(get());
-  std::string tmp(res);
-  free(res);
-  return tmp;
+  auto res = isl_pw_multi_aff_add(copy(), pma2.release());
+  return manage(res);
 }
 
-// implementations for isl::basic_map
-basic_map manage(__isl_take isl_basic_map *ptr) {
-  return basic_map(ptr);
-}
-basic_map manage_copy(__isl_keep isl_basic_map *ptr) {
-  ptr = isl_basic_map_copy(ptr);
-  return basic_map(ptr);
+isl::checked::pw_multi_aff pw_multi_aff::add_constant(isl::checked::multi_val mv) const
+{
+  auto res = isl_pw_multi_aff_add_constant_multi_val(copy(), mv.release());
+  return manage(res);
 }
 
-basic_map::basic_map()
-    : ptr(nullptr) {}
+isl::checked::pw_multi_aff pw_multi_aff::add_constant(isl::checked::val v) const
+{
+  auto res = isl_pw_multi_aff_add_constant_val(copy(), v.release());
+  return manage(res);
+}
 
-basic_map::basic_map(const basic_map &obj)
-    : ptr(nullptr)
+isl::checked::pw_multi_aff pw_multi_aff::add_constant(long v) const
 {
-  ptr = obj.copy();
+  return this->add_constant(isl::checked::val(ctx(), v));
 }
 
-basic_map::basic_map(__isl_take isl_basic_map *ptr)
-    : ptr(ptr) {}
+isl::checked::multi_aff pw_multi_aff::as_multi_aff() const
+{
+  auto res = isl_pw_multi_aff_as_multi_aff(copy());
+  return manage(res);
+}
 
-basic_map::basic_map(ctx ctx, const std::string &str)
+isl::checked::pw_multi_aff pw_multi_aff::bind_domain(isl::checked::multi_id tuple) const
 {
-  auto res = isl_basic_map_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
+  auto res = isl_pw_multi_aff_bind_domain(copy(), tuple.release());
+  return manage(res);
 }
 
-basic_map &basic_map::operator=(basic_map obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::checked::pw_multi_aff pw_multi_aff::bind_domain_wrapped_domain(isl::checked::multi_id tuple) const
+{
+  auto res = isl_pw_multi_aff_bind_domain_wrapped_domain(copy(), tuple.release());
+  return manage(res);
 }
 
-basic_map::~basic_map() {
-  if (ptr)
-    isl_basic_map_free(ptr);
+isl::checked::pw_multi_aff pw_multi_aff::coalesce() const
+{
+  auto res = isl_pw_multi_aff_coalesce(copy());
+  return manage(res);
 }
 
-__isl_give isl_basic_map *basic_map::copy() const & {
-  return isl_basic_map_copy(ptr);
+isl::checked::set pw_multi_aff::domain() const
+{
+  auto res = isl_pw_multi_aff_domain(copy());
+  return manage(res);
 }
 
-__isl_keep isl_basic_map *basic_map::get() const {
-  return ptr;
+isl::checked::pw_multi_aff pw_multi_aff::flat_range_product(isl::checked::pw_multi_aff pma2) const
+{
+  auto res = isl_pw_multi_aff_flat_range_product(copy(), pma2.release());
+  return manage(res);
 }
 
-__isl_give isl_basic_map *basic_map::release() {
-  isl_basic_map *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+stat pw_multi_aff::foreach_piece(const std::function<stat(isl::checked::set, isl::checked::multi_aff)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::set, isl::checked::multi_aff)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_set *arg_0, isl_multi_aff *arg_1, void *arg_2) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_2);
+    auto ret = (data->func)(manage(arg_0), manage(arg_1));
+    return ret.release();
+  };
+  auto res = isl_pw_multi_aff_foreach_piece(get(), fn_lambda, &fn_data);
+  return manage(res);
 }
 
-bool basic_map::is_null() const {
-  return ptr == nullptr;
+isl::checked::space pw_multi_aff::space() const
+{
+  auto res = isl_pw_multi_aff_get_space(get());
+  return manage(res);
 }
 
-ctx basic_map::get_ctx() const {
-  return ctx(isl_basic_map_get_ctx(ptr));
+isl::checked::space pw_multi_aff::get_space() const
+{
+  return space();
 }
 
-basic_map basic_map::affine_hull() const
+isl::checked::pw_multi_aff pw_multi_aff::gist(isl::checked::set set) const
 {
-  auto res = isl_basic_map_affine_hull(copy());
+  auto res = isl_pw_multi_aff_gist(copy(), set.release());
   return manage(res);
 }
 
-basic_map basic_map::apply_domain(basic_map bmap2) const
+isl::checked::pw_multi_aff pw_multi_aff::intersect_domain(isl::checked::set set) const
 {
-  auto res = isl_basic_map_apply_domain(copy(), bmap2.release());
+  auto res = isl_pw_multi_aff_intersect_domain(copy(), set.release());
   return manage(res);
 }
 
-basic_map basic_map::apply_range(basic_map bmap2) const
+isl::checked::pw_multi_aff pw_multi_aff::intersect_params(isl::checked::set set) const
 {
-  auto res = isl_basic_map_apply_range(copy(), bmap2.release());
+  auto res = isl_pw_multi_aff_intersect_params(copy(), set.release());
   return manage(res);
 }
 
-basic_set basic_map::deltas() const
+boolean pw_multi_aff::isa_multi_aff() const
 {
-  auto res = isl_basic_map_deltas(copy());
+  auto res = isl_pw_multi_aff_isa_multi_aff(get());
   return manage(res);
 }
 
-basic_map basic_map::detect_equalities() const
+class size pw_multi_aff::n_piece() const
 {
-  auto res = isl_basic_map_detect_equalities(copy());
+  auto res = isl_pw_multi_aff_n_piece(get());
   return manage(res);
 }
 
-basic_map basic_map::flatten() const
+isl::checked::pw_multi_aff pw_multi_aff::product(isl::checked::pw_multi_aff pma2) const
 {
-  auto res = isl_basic_map_flatten(copy());
+  auto res = isl_pw_multi_aff_product(copy(), pma2.release());
   return manage(res);
 }
 
-basic_map basic_map::flatten_domain() const
+isl::checked::pw_multi_aff pw_multi_aff::pullback(isl::checked::multi_aff ma) const
 {
-  auto res = isl_basic_map_flatten_domain(copy());
+  auto res = isl_pw_multi_aff_pullback_multi_aff(copy(), ma.release());
   return manage(res);
 }
 
-basic_map basic_map::flatten_range() const
+isl::checked::pw_multi_aff pw_multi_aff::pullback(isl::checked::pw_multi_aff pma2) const
 {
-  auto res = isl_basic_map_flatten_range(copy());
+  auto res = isl_pw_multi_aff_pullback_pw_multi_aff(copy(), pma2.release());
   return manage(res);
 }
 
-basic_map basic_map::gist(basic_map context) const
+isl::checked::pw_multi_aff pw_multi_aff::range_factor_domain() const
 {
-  auto res = isl_basic_map_gist(copy(), context.release());
+  auto res = isl_pw_multi_aff_range_factor_domain(copy());
   return manage(res);
 }
 
-basic_map basic_map::intersect(basic_map bmap2) const
+isl::checked::pw_multi_aff pw_multi_aff::range_factor_range() const
 {
-  auto res = isl_basic_map_intersect(copy(), bmap2.release());
+  auto res = isl_pw_multi_aff_range_factor_range(copy());
   return manage(res);
 }
 
-basic_map basic_map::intersect_domain(basic_set bset) const
+isl::checked::pw_multi_aff pw_multi_aff::range_product(isl::checked::pw_multi_aff pma2) const
 {
-  auto res = isl_basic_map_intersect_domain(copy(), bset.release());
+  auto res = isl_pw_multi_aff_range_product(copy(), pma2.release());
   return manage(res);
 }
 
-basic_map basic_map::intersect_range(basic_set bset) const
+isl::checked::pw_multi_aff pw_multi_aff::scale(isl::checked::val v) const
 {
-  auto res = isl_basic_map_intersect_range(copy(), bset.release());
+  auto res = isl_pw_multi_aff_scale_val(copy(), v.release());
   return manage(res);
 }
 
-boolean basic_map::is_empty() const
+isl::checked::pw_multi_aff pw_multi_aff::scale(long v) const
 {
-  auto res = isl_basic_map_is_empty(get());
-  return manage(res);
+  return this->scale(isl::checked::val(ctx(), v));
 }
 
-boolean basic_map::is_equal(const basic_map &bmap2) const
+isl::checked::pw_multi_aff pw_multi_aff::scale_down(isl::checked::val v) const
 {
-  auto res = isl_basic_map_is_equal(get(), bmap2.get());
+  auto res = isl_pw_multi_aff_scale_down_val(copy(), v.release());
   return manage(res);
 }
 
-boolean basic_map::is_subset(const basic_map &bmap2) const
+isl::checked::pw_multi_aff pw_multi_aff::scale_down(long v) const
 {
-  auto res = isl_basic_map_is_subset(get(), bmap2.get());
-  return manage(res);
+  return this->scale_down(isl::checked::val(ctx(), v));
 }
 
-map basic_map::lexmax() const
+isl::checked::pw_multi_aff pw_multi_aff::sub(isl::checked::pw_multi_aff pma2) const
 {
-  auto res = isl_basic_map_lexmax(copy());
+  auto res = isl_pw_multi_aff_sub(copy(), pma2.release());
   return manage(res);
 }
 
-map basic_map::lexmin() const
+isl::checked::pw_multi_aff pw_multi_aff::subtract_domain(isl::checked::set set) const
 {
-  auto res = isl_basic_map_lexmin(copy());
+  auto res = isl_pw_multi_aff_subtract_domain(copy(), set.release());
   return manage(res);
 }
 
-basic_map basic_map::reverse() const
+isl::checked::pw_multi_aff pw_multi_aff::union_add(isl::checked::pw_multi_aff pma2) const
 {
-  auto res = isl_basic_map_reverse(copy());
+  auto res = isl_pw_multi_aff_union_add(copy(), pma2.release());
   return manage(res);
 }
 
-basic_map basic_map::sample() const
+isl::checked::pw_multi_aff pw_multi_aff::zero(isl::checked::space space)
 {
-  auto res = isl_basic_map_sample(copy());
+  auto res = isl_pw_multi_aff_zero(space.release());
   return manage(res);
 }
 
-map basic_map::unite(basic_map bmap2) const
+inline std::ostream &operator<<(std::ostream &os, const pw_multi_aff &obj)
 {
-  auto res = isl_basic_map_union(copy(), bmap2.release());
-  return manage(res);
+  char *str = isl_pw_multi_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::basic_set
-basic_set manage(__isl_take isl_basic_set *ptr) {
-  return basic_set(ptr);
+// implementations for isl::pw_multi_aff_list
+pw_multi_aff_list manage(__isl_take isl_pw_multi_aff_list *ptr) {
+  return pw_multi_aff_list(ptr);
 }
-basic_set manage_copy(__isl_keep isl_basic_set *ptr) {
-  ptr = isl_basic_set_copy(ptr);
-  return basic_set(ptr);
+pw_multi_aff_list manage_copy(__isl_keep isl_pw_multi_aff_list *ptr) {
+  ptr = isl_pw_multi_aff_list_copy(ptr);
+  return pw_multi_aff_list(ptr);
 }
 
-basic_set::basic_set()
+pw_multi_aff_list::pw_multi_aff_list()
     : ptr(nullptr) {}
 
-basic_set::basic_set(const basic_set &obj)
+pw_multi_aff_list::pw_multi_aff_list(const pw_multi_aff_list &obj)
     : ptr(nullptr)
 {
   ptr = obj.copy();
 }
 
-basic_set::basic_set(__isl_take isl_basic_set *ptr)
+pw_multi_aff_list::pw_multi_aff_list(__isl_take isl_pw_multi_aff_list *ptr)
     : ptr(ptr) {}
 
-basic_set::basic_set(ctx ctx, const std::string &str)
+pw_multi_aff_list::pw_multi_aff_list(isl::checked::ctx ctx, int n)
 {
-  auto res = isl_basic_set_read_from_str(ctx.release(), str.c_str());
+  auto res = isl_pw_multi_aff_list_alloc(ctx.release(), n);
   ptr = res;
 }
-basic_set::basic_set(point pnt)
+
+pw_multi_aff_list::pw_multi_aff_list(isl::checked::pw_multi_aff el)
 {
-  auto res = isl_basic_set_from_point(pnt.release());
+  auto res = isl_pw_multi_aff_list_from_pw_multi_aff(el.release());
   ptr = res;
 }
 
-basic_set &basic_set::operator=(basic_set obj) {
+pw_multi_aff_list &pw_multi_aff_list::operator=(pw_multi_aff_list obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-basic_set::~basic_set() {
+pw_multi_aff_list::~pw_multi_aff_list() {
   if (ptr)
-    isl_basic_set_free(ptr);
+    isl_pw_multi_aff_list_free(ptr);
 }
 
-__isl_give isl_basic_set *basic_set::copy() const & {
-  return isl_basic_set_copy(ptr);
+__isl_give isl_pw_multi_aff_list *pw_multi_aff_list::copy() const & {
+  return isl_pw_multi_aff_list_copy(ptr);
 }
 
-__isl_keep isl_basic_set *basic_set::get() const {
+__isl_keep isl_pw_multi_aff_list *pw_multi_aff_list::get() const {
   return ptr;
 }
 
-__isl_give isl_basic_set *basic_set::release() {
-  isl_basic_set *tmp = ptr;
+__isl_give isl_pw_multi_aff_list *pw_multi_aff_list::release() {
+  isl_pw_multi_aff_list *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool basic_set::is_null() const {
+bool pw_multi_aff_list::is_null() const {
   return ptr == nullptr;
 }
 
-ctx basic_set::get_ctx() const {
-  return ctx(isl_basic_set_get_ctx(ptr));
-}
-
-basic_set basic_set::affine_hull() const
-{
-  auto res = isl_basic_set_affine_hull(copy());
-  return manage(res);
-}
-
-basic_set basic_set::apply(basic_map bmap) const
-{
-  auto res = isl_basic_set_apply(copy(), bmap.release());
-  return manage(res);
-}
-
-basic_set basic_set::detect_equalities() const
-{
-  auto res = isl_basic_set_detect_equalities(copy());
-  return manage(res);
-}
-
-val basic_set::dim_max_val(int pos) const
-{
-  auto res = isl_basic_set_dim_max_val(copy(), pos);
-  return manage(res);
-}
-
-basic_set basic_set::flatten() const
-{
-  auto res = isl_basic_set_flatten(copy());
-  return manage(res);
-}
-
-basic_set basic_set::gist(basic_set context) const
-{
-  auto res = isl_basic_set_gist(copy(), context.release());
-  return manage(res);
-}
-
-basic_set basic_set::intersect(basic_set bset2) const
-{
-  auto res = isl_basic_set_intersect(copy(), bset2.release());
-  return manage(res);
-}
-
-basic_set basic_set::intersect_params(basic_set bset2) const
-{
-  auto res = isl_basic_set_intersect_params(copy(), bset2.release());
-  return manage(res);
-}
-
-boolean basic_set::is_empty() const
-{
-  auto res = isl_basic_set_is_empty(get());
-  return manage(res);
+isl::checked::ctx pw_multi_aff_list::ctx() const {
+  return isl::checked::ctx(isl_pw_multi_aff_list_get_ctx(ptr));
 }
 
-boolean basic_set::is_equal(const basic_set &bset2) const
+isl::checked::pw_multi_aff_list pw_multi_aff_list::add(isl::checked::pw_multi_aff el) const
 {
-  auto res = isl_basic_set_is_equal(get(), bset2.get());
+  auto res = isl_pw_multi_aff_list_add(copy(), el.release());
   return manage(res);
 }
 
-boolean basic_set::is_subset(const basic_set &bset2) const
+isl::checked::pw_multi_aff_list pw_multi_aff_list::clear() const
 {
-  auto res = isl_basic_set_is_subset(get(), bset2.get());
+  auto res = isl_pw_multi_aff_list_clear(copy());
   return manage(res);
 }
 
-boolean basic_set::is_wrapping() const
+isl::checked::pw_multi_aff_list pw_multi_aff_list::concat(isl::checked::pw_multi_aff_list list2) const
 {
-  auto res = isl_basic_set_is_wrapping(get());
+  auto res = isl_pw_multi_aff_list_concat(copy(), list2.release());
   return manage(res);
 }
 
-set basic_set::lexmax() const
+stat pw_multi_aff_list::foreach(const std::function<stat(isl::checked::pw_multi_aff)> &fn) const
 {
-  auto res = isl_basic_set_lexmax(copy());
+  struct fn_data {
+    std::function<stat(isl::checked::pw_multi_aff)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_pw_multi_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_pw_multi_aff_list_foreach(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-set basic_set::lexmin() const
+isl::checked::pw_multi_aff pw_multi_aff_list::at(int index) const
 {
-  auto res = isl_basic_set_lexmin(copy());
+  auto res = isl_pw_multi_aff_list_get_at(get(), index);
   return manage(res);
 }
 
-basic_set basic_set::sample() const
+isl::checked::pw_multi_aff pw_multi_aff_list::get_at(int index) const
 {
-  auto res = isl_basic_set_sample(copy());
-  return manage(res);
+  return at(index);
 }
 
-point basic_set::sample_point() const
+class size pw_multi_aff_list::size() const
 {
-  auto res = isl_basic_set_sample_point(copy());
+  auto res = isl_pw_multi_aff_list_size(get());
   return manage(res);
 }
 
-set basic_set::unite(basic_set bset2) const
+inline std::ostream &operator<<(std::ostream &os, const pw_multi_aff_list &obj)
 {
-  auto res = isl_basic_set_union(copy(), bset2.release());
-  return manage(res);
+  char *str = isl_pw_multi_aff_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::map
-map manage(__isl_take isl_map *ptr) {
-  return map(ptr);
-}
-map manage_copy(__isl_keep isl_map *ptr) {
-  ptr = isl_map_copy(ptr);
-  return map(ptr);
+// implementations for isl::schedule
+schedule manage(__isl_take isl_schedule *ptr) {
+  return schedule(ptr);
+}
+schedule manage_copy(__isl_keep isl_schedule *ptr) {
+  ptr = isl_schedule_copy(ptr);
+  return schedule(ptr);
 }
 
-map::map()
+schedule::schedule()
     : ptr(nullptr) {}
 
-map::map(const map &obj)
+schedule::schedule(const schedule &obj)
     : ptr(nullptr)
 {
   ptr = obj.copy();
 }
 
-map::map(__isl_take isl_map *ptr)
+schedule::schedule(__isl_take isl_schedule *ptr)
     : ptr(ptr) {}
 
-map::map(ctx ctx, const std::string &str)
-{
-  auto res = isl_map_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
-}
-map::map(basic_map bmap)
+schedule::schedule(isl::checked::ctx ctx, const std::string &str)
 {
-  auto res = isl_map_from_basic_map(bmap.release());
+  auto res = isl_schedule_read_from_str(ctx.release(), str.c_str());
   ptr = res;
 }
 
-map &map::operator=(map obj) {
+schedule &schedule::operator=(schedule obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-map::~map() {
+schedule::~schedule() {
   if (ptr)
-    isl_map_free(ptr);
+    isl_schedule_free(ptr);
 }
 
-__isl_give isl_map *map::copy() const & {
-  return isl_map_copy(ptr);
+__isl_give isl_schedule *schedule::copy() const & {
+  return isl_schedule_copy(ptr);
 }
 
-__isl_keep isl_map *map::get() const {
+__isl_keep isl_schedule *schedule::get() const {
   return ptr;
 }
 
-__isl_give isl_map *map::release() {
-  isl_map *tmp = ptr;
+__isl_give isl_schedule *schedule::release() {
+  isl_schedule *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool map::is_null() const {
+bool schedule::is_null() const {
   return ptr == nullptr;
 }
 
-ctx map::get_ctx() const {
-  return ctx(isl_map_get_ctx(ptr));
+isl::checked::ctx schedule::ctx() const {
+  return isl::checked::ctx(isl_schedule_get_ctx(ptr));
 }
 
-basic_map map::affine_hull() const
+isl::checked::schedule schedule::from_domain(isl::checked::union_set domain)
 {
-  auto res = isl_map_affine_hull(copy());
+  auto res = isl_schedule_from_domain(domain.release());
   return manage(res);
 }
 
-map map::apply_domain(map map2) const
+isl::checked::union_map schedule::map() const
 {
-  auto res = isl_map_apply_domain(copy(), map2.release());
+  auto res = isl_schedule_get_map(get());
   return manage(res);
 }
 
-map map::apply_range(map map2) const
+isl::checked::union_map schedule::get_map() const
 {
-  auto res = isl_map_apply_range(copy(), map2.release());
-  return manage(res);
+  return map();
 }
 
-map map::coalesce() const
+isl::checked::schedule_node schedule::root() const
 {
-  auto res = isl_map_coalesce(copy());
+  auto res = isl_schedule_get_root(get());
   return manage(res);
 }
 
-map map::complement() const
+isl::checked::schedule_node schedule::get_root() const
 {
-  auto res = isl_map_complement(copy());
-  return manage(res);
+  return root();
 }
 
-set map::deltas() const
+isl::checked::schedule schedule::pullback(isl::checked::union_pw_multi_aff upma) const
 {
-  auto res = isl_map_deltas(copy());
+  auto res = isl_schedule_pullback_union_pw_multi_aff(copy(), upma.release());
   return manage(res);
 }
 
-map map::detect_equalities() const
+inline std::ostream &operator<<(std::ostream &os, const schedule &obj)
 {
-  auto res = isl_map_detect_equalities(copy());
-  return manage(res);
+  char *str = isl_schedule_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-map map::flatten() const
-{
-  auto res = isl_map_flatten(copy());
-  return manage(res);
+// implementations for isl::schedule_constraints
+schedule_constraints manage(__isl_take isl_schedule_constraints *ptr) {
+  return schedule_constraints(ptr);
 }
-
-map map::flatten_domain() const
-{
-  auto res = isl_map_flatten_domain(copy());
-  return manage(res);
+schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr) {
+  ptr = isl_schedule_constraints_copy(ptr);
+  return schedule_constraints(ptr);
 }
 
-map map::flatten_range() const
-{
-  auto res = isl_map_flatten_range(copy());
-  return manage(res);
-}
+schedule_constraints::schedule_constraints()
+    : ptr(nullptr) {}
 
-stat map::foreach_basic_map(const std::function<stat(basic_map)> &fn) const
+schedule_constraints::schedule_constraints(const schedule_constraints &obj)
+    : ptr(nullptr)
 {
-  struct fn_data {
-    const std::function<stat(basic_map)> *func;
-  } fn_data = { &fn };
-  auto fn_lambda = [](isl_basic_map *arg_0, void *arg_1) -> isl_stat {
-    auto *data = static_cast<struct fn_data *>(arg_1);
-    stat ret = (*data->func)(manage(arg_0));
-    return ret.release();
-  };
-  auto res = isl_map_foreach_basic_map(get(), fn_lambda, &fn_data);
-  return manage(res);
+  ptr = obj.copy();
 }
 
-map map::gist(map context) const
+schedule_constraints::schedule_constraints(__isl_take isl_schedule_constraints *ptr)
+    : ptr(ptr) {}
+
+schedule_constraints::schedule_constraints(isl::checked::ctx ctx, const std::string &str)
 {
-  auto res = isl_map_gist(copy(), context.release());
-  return manage(res);
+  auto res = isl_schedule_constraints_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
 }
 
-map map::gist_domain(set context) const
-{
-  auto res = isl_map_gist_domain(copy(), context.release());
-  return manage(res);
+schedule_constraints &schedule_constraints::operator=(schedule_constraints obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-map map::intersect(map map2) const
-{
-  auto res = isl_map_intersect(copy(), map2.release());
-  return manage(res);
+schedule_constraints::~schedule_constraints() {
+  if (ptr)
+    isl_schedule_constraints_free(ptr);
 }
 
-map map::intersect_domain(set set) const
-{
-  auto res = isl_map_intersect_domain(copy(), set.release());
-  return manage(res);
+__isl_give isl_schedule_constraints *schedule_constraints::copy() const & {
+  return isl_schedule_constraints_copy(ptr);
 }
 
-map map::intersect_params(set params) const
-{
-  auto res = isl_map_intersect_params(copy(), params.release());
-  return manage(res);
+__isl_keep isl_schedule_constraints *schedule_constraints::get() const {
+  return ptr;
 }
 
-map map::intersect_range(set set) const
-{
-  auto res = isl_map_intersect_range(copy(), set.release());
-  return manage(res);
+__isl_give isl_schedule_constraints *schedule_constraints::release() {
+  isl_schedule_constraints *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
 }
 
-boolean map::is_bijective() const
-{
-  auto res = isl_map_is_bijective(get());
-  return manage(res);
+bool schedule_constraints::is_null() const {
+  return ptr == nullptr;
 }
 
-boolean map::is_disjoint(const map &map2) const
-{
-  auto res = isl_map_is_disjoint(get(), map2.get());
-  return manage(res);
+isl::checked::ctx schedule_constraints::ctx() const {
+  return isl::checked::ctx(isl_schedule_constraints_get_ctx(ptr));
 }
 
-boolean map::is_empty() const
+isl::checked::schedule schedule_constraints::compute_schedule() const
 {
-  auto res = isl_map_is_empty(get());
+  auto res = isl_schedule_constraints_compute_schedule(copy());
   return manage(res);
 }
 
-boolean map::is_equal(const map &map2) const
+isl::checked::union_map schedule_constraints::coincidence() const
 {
-  auto res = isl_map_is_equal(get(), map2.get());
+  auto res = isl_schedule_constraints_get_coincidence(get());
   return manage(res);
 }
 
-boolean map::is_injective() const
+isl::checked::union_map schedule_constraints::get_coincidence() const
 {
-  auto res = isl_map_is_injective(get());
-  return manage(res);
+  return coincidence();
 }
 
-boolean map::is_single_valued() const
+isl::checked::union_map schedule_constraints::conditional_validity() const
 {
-  auto res = isl_map_is_single_valued(get());
+  auto res = isl_schedule_constraints_get_conditional_validity(get());
   return manage(res);
 }
 
-boolean map::is_strict_subset(const map &map2) const
+isl::checked::union_map schedule_constraints::get_conditional_validity() const
 {
-  auto res = isl_map_is_strict_subset(get(), map2.get());
-  return manage(res);
+  return conditional_validity();
 }
 
-boolean map::is_subset(const map &map2) const
+isl::checked::union_map schedule_constraints::conditional_validity_condition() const
 {
-  auto res = isl_map_is_subset(get(), map2.get());
+  auto res = isl_schedule_constraints_get_conditional_validity_condition(get());
   return manage(res);
 }
 
-map map::lexmax() const
+isl::checked::union_map schedule_constraints::get_conditional_validity_condition() const
 {
-  auto res = isl_map_lexmax(copy());
-  return manage(res);
+  return conditional_validity_condition();
 }
 
-map map::lexmin() const
+isl::checked::set schedule_constraints::context() const
 {
-  auto res = isl_map_lexmin(copy());
+  auto res = isl_schedule_constraints_get_context(get());
   return manage(res);
 }
 
-basic_map map::polyhedral_hull() const
+isl::checked::set schedule_constraints::get_context() const
 {
-  auto res = isl_map_polyhedral_hull(copy());
-  return manage(res);
+  return context();
 }
 
-map map::reverse() const
+isl::checked::union_set schedule_constraints::domain() const
 {
-  auto res = isl_map_reverse(copy());
+  auto res = isl_schedule_constraints_get_domain(get());
   return manage(res);
 }
 
-basic_map map::sample() const
+isl::checked::union_set schedule_constraints::get_domain() const
 {
-  auto res = isl_map_sample(copy());
-  return manage(res);
+  return domain();
 }
 
-map map::subtract(map map2) const
+isl::checked::union_map schedule_constraints::proximity() const
 {
-  auto res = isl_map_subtract(copy(), map2.release());
+  auto res = isl_schedule_constraints_get_proximity(get());
   return manage(res);
 }
 
-map map::unite(map map2) const
+isl::checked::union_map schedule_constraints::get_proximity() const
 {
-  auto res = isl_map_union(copy(), map2.release());
-  return manage(res);
+  return proximity();
 }
 
-basic_map map::unshifted_simple_hull() const
+isl::checked::union_map schedule_constraints::validity() const
 {
-  auto res = isl_map_unshifted_simple_hull(copy());
+  auto res = isl_schedule_constraints_get_validity(get());
   return manage(res);
 }
 
-// implementations for isl::multi_aff
-multi_aff manage(__isl_take isl_multi_aff *ptr) {
-  return multi_aff(ptr);
-}
-multi_aff manage_copy(__isl_keep isl_multi_aff *ptr) {
-  ptr = isl_multi_aff_copy(ptr);
-  return multi_aff(ptr);
-}
-
-multi_aff::multi_aff()
-    : ptr(nullptr) {}
-
-multi_aff::multi_aff(const multi_aff &obj)
-    : ptr(nullptr)
+isl::checked::union_map schedule_constraints::get_validity() const
 {
-  ptr = obj.copy();
+  return validity();
 }
 
-multi_aff::multi_aff(__isl_take isl_multi_aff *ptr)
-    : ptr(ptr) {}
-
-multi_aff::multi_aff(aff aff)
-{
-  auto res = isl_multi_aff_from_aff(aff.release());
-  ptr = res;
-}
-multi_aff::multi_aff(ctx ctx, const std::string &str)
+isl::checked::schedule_constraints schedule_constraints::on_domain(isl::checked::union_set domain)
 {
-  auto res = isl_multi_aff_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
-}
-
-multi_aff &multi_aff::operator=(multi_aff obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
-}
-
-multi_aff::~multi_aff() {
-  if (ptr)
-    isl_multi_aff_free(ptr);
-}
-
-__isl_give isl_multi_aff *multi_aff::copy() const & {
-  return isl_multi_aff_copy(ptr);
-}
-
-__isl_keep isl_multi_aff *multi_aff::get() const {
-  return ptr;
-}
-
-__isl_give isl_multi_aff *multi_aff::release() {
-  isl_multi_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
-}
-
-bool multi_aff::is_null() const {
-  return ptr == nullptr;
+  auto res = isl_schedule_constraints_on_domain(domain.release());
+  return manage(res);
 }
 
-ctx multi_aff::get_ctx() const {
-  return ctx(isl_multi_aff_get_ctx(ptr));
+isl::checked::schedule_constraints schedule_constraints::set_coincidence(isl::checked::union_map coincidence) const
+{
+  auto res = isl_schedule_constraints_set_coincidence(copy(), coincidence.release());
+  return manage(res);
 }
 
-multi_aff multi_aff::add(multi_aff multi2) const
+isl::checked::schedule_constraints schedule_constraints::set_conditional_validity(isl::checked::union_map condition, isl::checked::union_map validity) const
 {
-  auto res = isl_multi_aff_add(copy(), multi2.release());
+  auto res = isl_schedule_constraints_set_conditional_validity(copy(), condition.release(), validity.release());
   return manage(res);
 }
 
-multi_aff multi_aff::flat_range_product(multi_aff multi2) const
+isl::checked::schedule_constraints schedule_constraints::set_context(isl::checked::set context) const
 {
-  auto res = isl_multi_aff_flat_range_product(copy(), multi2.release());
+  auto res = isl_schedule_constraints_set_context(copy(), context.release());
   return manage(res);
 }
 
-multi_aff multi_aff::product(multi_aff multi2) const
+isl::checked::schedule_constraints schedule_constraints::set_proximity(isl::checked::union_map proximity) const
 {
-  auto res = isl_multi_aff_product(copy(), multi2.release());
+  auto res = isl_schedule_constraints_set_proximity(copy(), proximity.release());
   return manage(res);
 }
 
-multi_aff multi_aff::pullback(multi_aff ma2) const
+isl::checked::schedule_constraints schedule_constraints::set_validity(isl::checked::union_map validity) const
 {
-  auto res = isl_multi_aff_pullback_multi_aff(copy(), ma2.release());
+  auto res = isl_schedule_constraints_set_validity(copy(), validity.release());
   return manage(res);
 }
 
-multi_aff multi_aff::range_product(multi_aff multi2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_constraints &obj)
 {
-  auto res = isl_multi_aff_range_product(copy(), multi2.release());
-  return manage(res);
+  char *str = isl_schedule_constraints_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::multi_pw_aff
-multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr) {
-  return multi_pw_aff(ptr);
+// implementations for isl::schedule_node
+schedule_node manage(__isl_take isl_schedule_node *ptr) {
+  return schedule_node(ptr);
 }
-multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr) {
-  ptr = isl_multi_pw_aff_copy(ptr);
-  return multi_pw_aff(ptr);
+schedule_node manage_copy(__isl_keep isl_schedule_node *ptr) {
+  ptr = isl_schedule_node_copy(ptr);
+  return schedule_node(ptr);
 }
 
-multi_pw_aff::multi_pw_aff()
+schedule_node::schedule_node()
     : ptr(nullptr) {}
 
-multi_pw_aff::multi_pw_aff(const multi_pw_aff &obj)
+schedule_node::schedule_node(const schedule_node &obj)
     : ptr(nullptr)
 {
   ptr = obj.copy();
 }
 
-multi_pw_aff::multi_pw_aff(__isl_take isl_multi_pw_aff *ptr)
-    : ptr(ptr) {}
-
-multi_pw_aff::multi_pw_aff(multi_aff ma)
-{
-  auto res = isl_multi_pw_aff_from_multi_aff(ma.release());
-  ptr = res;
-}
-multi_pw_aff::multi_pw_aff(pw_aff pa)
-{
-  auto res = isl_multi_pw_aff_from_pw_aff(pa.release());
-  ptr = res;
-}
-multi_pw_aff::multi_pw_aff(pw_multi_aff pma)
-{
-  auto res = isl_multi_pw_aff_from_pw_multi_aff(pma.release());
-  ptr = res;
-}
-multi_pw_aff::multi_pw_aff(ctx ctx, const std::string &str)
-{
-  auto res = isl_multi_pw_aff_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
-}
+schedule_node::schedule_node(__isl_take isl_schedule_node *ptr)
+    : ptr(ptr) {}
 
-multi_pw_aff &multi_pw_aff::operator=(multi_pw_aff obj) {
+schedule_node &schedule_node::operator=(schedule_node obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-multi_pw_aff::~multi_pw_aff() {
+schedule_node::~schedule_node() {
   if (ptr)
-    isl_multi_pw_aff_free(ptr);
+    isl_schedule_node_free(ptr);
 }
 
-__isl_give isl_multi_pw_aff *multi_pw_aff::copy() const & {
-  return isl_multi_pw_aff_copy(ptr);
+__isl_give isl_schedule_node *schedule_node::copy() const & {
+  return isl_schedule_node_copy(ptr);
 }
 
-__isl_keep isl_multi_pw_aff *multi_pw_aff::get() const {
+__isl_keep isl_schedule_node *schedule_node::get() const {
   return ptr;
 }
 
-__isl_give isl_multi_pw_aff *multi_pw_aff::release() {
-  isl_multi_pw_aff *tmp = ptr;
+__isl_give isl_schedule_node *schedule_node::release() {
+  isl_schedule_node *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool multi_pw_aff::is_null() const {
+bool schedule_node::is_null() const {
   return ptr == nullptr;
 }
 
-ctx multi_pw_aff::get_ctx() const {
-  return ctx(isl_multi_pw_aff_get_ctx(ptr));
+template <typename T, typename>
+boolean schedule_node::isa_type(T subtype) const
+{
+  if (is_null())
+    return boolean();
+  return isl_schedule_node_get_type(get()) == subtype;
+}
+template <class T>
+boolean schedule_node::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T schedule_node::as() const
+{
+ if (isa<T>().is_false())
+    isl_die(ctx().get(), isl_error_invalid, "not an object of the requested subtype", return T());
+  return T(copy());
+}
+
+isl::checked::ctx schedule_node::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-multi_pw_aff multi_pw_aff::add(multi_pw_aff multi2) const
+isl::checked::schedule_node schedule_node::ancestor(int generation) const
 {
-  auto res = isl_multi_pw_aff_add(copy(), multi2.release());
+  auto res = isl_schedule_node_ancestor(copy(), generation);
   return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::flat_range_product(multi_pw_aff multi2) const
+isl::checked::schedule_node schedule_node::child(int pos) const
 {
-  auto res = isl_multi_pw_aff_flat_range_product(copy(), multi2.release());
+  auto res = isl_schedule_node_child(copy(), pos);
   return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::product(multi_pw_aff multi2) const
+boolean schedule_node::every_descendant(const std::function<boolean(isl::checked::schedule_node)> &test) const
 {
-  auto res = isl_multi_pw_aff_product(copy(), multi2.release());
+  struct test_data {
+    std::function<boolean(isl::checked::schedule_node)> func;
+  } test_data = { test };
+  auto test_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct test_data *>(arg_1);
+    auto ret = (data->func)(manage_copy(arg_0));
+    return ret.release();
+  };
+  auto res = isl_schedule_node_every_descendant(get(), test_lambda, &test_data);
   return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::pullback(multi_aff ma) const
+isl::checked::schedule_node schedule_node::first_child() const
 {
-  auto res = isl_multi_pw_aff_pullback_multi_aff(copy(), ma.release());
+  auto res = isl_schedule_node_first_child(copy());
   return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::pullback(pw_multi_aff pma) const
+stat schedule_node::foreach_ancestor_top_down(const std::function<stat(isl::checked::schedule_node)> &fn) const
 {
-  auto res = isl_multi_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  struct fn_data {
+    std::function<stat(isl::checked::schedule_node)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage_copy(arg_0));
+    return ret.release();
+  };
+  auto res = isl_schedule_node_foreach_ancestor_top_down(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::pullback(multi_pw_aff mpa2) const
+stat schedule_node::foreach_descendant_top_down(const std::function<boolean(isl::checked::schedule_node)> &fn) const
 {
-  auto res = isl_multi_pw_aff_pullback_multi_pw_aff(copy(), mpa2.release());
+  struct fn_data {
+    std::function<boolean(isl::checked::schedule_node)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage_copy(arg_0));
+    return ret.release();
+  };
+  auto res = isl_schedule_node_foreach_descendant_top_down(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::range_product(multi_pw_aff multi2) const
+isl::checked::schedule_node schedule_node::from_domain(isl::checked::union_set domain)
 {
-  auto res = isl_multi_pw_aff_range_product(copy(), multi2.release());
+  auto res = isl_schedule_node_from_domain(domain.release());
   return manage(res);
 }
 
-// implementations for isl::multi_union_pw_aff
-multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr) {
-  return multi_union_pw_aff(ptr);
+isl::checked::schedule_node schedule_node::from_extension(isl::checked::union_map extension)
+{
+  auto res = isl_schedule_node_from_extension(extension.release());
+  return manage(res);
 }
-multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr) {
-  ptr = isl_multi_union_pw_aff_copy(ptr);
-  return multi_union_pw_aff(ptr);
+
+class size schedule_node::ancestor_child_position(const isl::checked::schedule_node &ancestor) const
+{
+  auto res = isl_schedule_node_get_ancestor_child_position(get(), ancestor.get());
+  return manage(res);
 }
 
-multi_union_pw_aff::multi_union_pw_aff()
-    : ptr(nullptr) {}
+class size schedule_node::get_ancestor_child_position(const isl::checked::schedule_node &ancestor) const
+{
+  return ancestor_child_position(ancestor);
+}
 
-multi_union_pw_aff::multi_union_pw_aff(const multi_union_pw_aff &obj)
-    : ptr(nullptr)
+class size schedule_node::child_position() const
 {
-  ptr = obj.copy();
+  auto res = isl_schedule_node_get_child_position(get());
+  return manage(res);
 }
 
-multi_union_pw_aff::multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr)
-    : ptr(ptr) {}
+class size schedule_node::get_child_position() const
+{
+  return child_position();
+}
 
-multi_union_pw_aff::multi_union_pw_aff(union_pw_aff upa)
+isl::checked::multi_union_pw_aff schedule_node::prefix_schedule_multi_union_pw_aff() const
 {
-  auto res = isl_multi_union_pw_aff_from_union_pw_aff(upa.release());
-  ptr = res;
+  auto res = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(get());
+  return manage(res);
 }
-multi_union_pw_aff::multi_union_pw_aff(multi_pw_aff mpa)
+
+isl::checked::multi_union_pw_aff schedule_node::get_prefix_schedule_multi_union_pw_aff() const
 {
-  auto res = isl_multi_union_pw_aff_from_multi_pw_aff(mpa.release());
-  ptr = res;
+  return prefix_schedule_multi_union_pw_aff();
 }
-multi_union_pw_aff::multi_union_pw_aff(ctx ctx, const std::string &str)
+
+isl::checked::union_map schedule_node::prefix_schedule_union_map() const
 {
-  auto res = isl_multi_union_pw_aff_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
+  auto res = isl_schedule_node_get_prefix_schedule_union_map(get());
+  return manage(res);
 }
 
-multi_union_pw_aff &multi_union_pw_aff::operator=(multi_union_pw_aff obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::checked::union_map schedule_node::get_prefix_schedule_union_map() const
+{
+  return prefix_schedule_union_map();
 }
 
-multi_union_pw_aff::~multi_union_pw_aff() {
-  if (ptr)
-    isl_multi_union_pw_aff_free(ptr);
+isl::checked::union_pw_multi_aff schedule_node::prefix_schedule_union_pw_multi_aff() const
+{
+  auto res = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(get());
+  return manage(res);
 }
 
-__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::copy() const & {
-  return isl_multi_union_pw_aff_copy(ptr);
+isl::checked::union_pw_multi_aff schedule_node::get_prefix_schedule_union_pw_multi_aff() const
+{
+  return prefix_schedule_union_pw_multi_aff();
 }
 
-__isl_keep isl_multi_union_pw_aff *multi_union_pw_aff::get() const {
-  return ptr;
+isl::checked::schedule schedule_node::schedule() const
+{
+  auto res = isl_schedule_node_get_schedule(get());
+  return manage(res);
 }
 
-__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::release() {
-  isl_multi_union_pw_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::checked::schedule schedule_node::get_schedule() const
+{
+  return schedule();
 }
 
-bool multi_union_pw_aff::is_null() const {
-  return ptr == nullptr;
+isl::checked::schedule_node schedule_node::shared_ancestor(const isl::checked::schedule_node &node2) const
+{
+  auto res = isl_schedule_node_get_shared_ancestor(get(), node2.get());
+  return manage(res);
 }
 
-ctx multi_union_pw_aff::get_ctx() const {
-  return ctx(isl_multi_union_pw_aff_get_ctx(ptr));
+isl::checked::schedule_node schedule_node::get_shared_ancestor(const isl::checked::schedule_node &node2) const
+{
+  return shared_ancestor(node2);
 }
 
-multi_union_pw_aff multi_union_pw_aff::add(multi_union_pw_aff multi2) const
+class size schedule_node::tree_depth() const
 {
-  auto res = isl_multi_union_pw_aff_add(copy(), multi2.release());
+  auto res = isl_schedule_node_get_tree_depth(get());
   return manage(res);
 }
 
-multi_union_pw_aff multi_union_pw_aff::flat_range_product(multi_union_pw_aff multi2) const
+class size schedule_node::get_tree_depth() const
 {
-  auto res = isl_multi_union_pw_aff_flat_range_product(copy(), multi2.release());
-  return manage(res);
+  return tree_depth();
 }
 
-multi_union_pw_aff multi_union_pw_aff::pullback(union_pw_multi_aff upma) const
+isl::checked::schedule_node schedule_node::graft_after(isl::checked::schedule_node graft) const
 {
-  auto res = isl_multi_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  auto res = isl_schedule_node_graft_after(copy(), graft.release());
   return manage(res);
 }
 
-multi_union_pw_aff multi_union_pw_aff::range_product(multi_union_pw_aff multi2) const
+isl::checked::schedule_node schedule_node::graft_before(isl::checked::schedule_node graft) const
 {
-  auto res = isl_multi_union_pw_aff_range_product(copy(), multi2.release());
+  auto res = isl_schedule_node_graft_before(copy(), graft.release());
   return manage(res);
 }
 
-multi_union_pw_aff multi_union_pw_aff::union_add(multi_union_pw_aff mupa2) const
+boolean schedule_node::has_children() const
 {
-  auto res = isl_multi_union_pw_aff_union_add(copy(), mupa2.release());
+  auto res = isl_schedule_node_has_children(get());
   return manage(res);
 }
 
-// implementations for isl::multi_val
-multi_val manage(__isl_take isl_multi_val *ptr) {
-  return multi_val(ptr);
-}
-multi_val manage_copy(__isl_keep isl_multi_val *ptr) {
-  ptr = isl_multi_val_copy(ptr);
-  return multi_val(ptr);
+boolean schedule_node::has_next_sibling() const
+{
+  auto res = isl_schedule_node_has_next_sibling(get());
+  return manage(res);
 }
 
-multi_val::multi_val()
-    : ptr(nullptr) {}
-
-multi_val::multi_val(const multi_val &obj)
-    : ptr(nullptr)
+boolean schedule_node::has_parent() const
 {
-  ptr = obj.copy();
+  auto res = isl_schedule_node_has_parent(get());
+  return manage(res);
 }
 
-multi_val::multi_val(__isl_take isl_multi_val *ptr)
-    : ptr(ptr) {}
-
-
-multi_val &multi_val::operator=(multi_val obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+boolean schedule_node::has_previous_sibling() const
+{
+  auto res = isl_schedule_node_has_previous_sibling(get());
+  return manage(res);
 }
 
-multi_val::~multi_val() {
-  if (ptr)
-    isl_multi_val_free(ptr);
+isl::checked::schedule_node schedule_node::insert_context(isl::checked::set context) const
+{
+  auto res = isl_schedule_node_insert_context(copy(), context.release());
+  return manage(res);
 }
 
-__isl_give isl_multi_val *multi_val::copy() const & {
-  return isl_multi_val_copy(ptr);
+isl::checked::schedule_node schedule_node::insert_filter(isl::checked::union_set filter) const
+{
+  auto res = isl_schedule_node_insert_filter(copy(), filter.release());
+  return manage(res);
 }
 
-__isl_keep isl_multi_val *multi_val::get() const {
-  return ptr;
+isl::checked::schedule_node schedule_node::insert_guard(isl::checked::set context) const
+{
+  auto res = isl_schedule_node_insert_guard(copy(), context.release());
+  return manage(res);
 }
 
-__isl_give isl_multi_val *multi_val::release() {
-  isl_multi_val *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::checked::schedule_node schedule_node::insert_mark(isl::checked::id mark) const
+{
+  auto res = isl_schedule_node_insert_mark(copy(), mark.release());
+  return manage(res);
 }
 
-bool multi_val::is_null() const {
-  return ptr == nullptr;
+isl::checked::schedule_node schedule_node::insert_mark(const std::string &mark) const
+{
+  return this->insert_mark(isl::checked::id(ctx(), mark));
 }
 
-ctx multi_val::get_ctx() const {
-  return ctx(isl_multi_val_get_ctx(ptr));
+isl::checked::schedule_node schedule_node::insert_partial_schedule(isl::checked::multi_union_pw_aff schedule) const
+{
+  auto res = isl_schedule_node_insert_partial_schedule(copy(), schedule.release());
+  return manage(res);
 }
 
-multi_val multi_val::add(multi_val multi2) const
+isl::checked::schedule_node schedule_node::insert_sequence(isl::checked::union_set_list filters) const
 {
-  auto res = isl_multi_val_add(copy(), multi2.release());
+  auto res = isl_schedule_node_insert_sequence(copy(), filters.release());
   return manage(res);
 }
 
-multi_val multi_val::flat_range_product(multi_val multi2) const
+isl::checked::schedule_node schedule_node::insert_set(isl::checked::union_set_list filters) const
 {
-  auto res = isl_multi_val_flat_range_product(copy(), multi2.release());
+  auto res = isl_schedule_node_insert_set(copy(), filters.release());
   return manage(res);
 }
 
-multi_val multi_val::product(multi_val multi2) const
+boolean schedule_node::is_equal(const isl::checked::schedule_node &node2) const
 {
-  auto res = isl_multi_val_product(copy(), multi2.release());
+  auto res = isl_schedule_node_is_equal(get(), node2.get());
   return manage(res);
 }
 
-multi_val multi_val::range_product(multi_val multi2) const
+boolean schedule_node::is_subtree_anchored() const
 {
-  auto res = isl_multi_val_range_product(copy(), multi2.release());
+  auto res = isl_schedule_node_is_subtree_anchored(get());
   return manage(res);
 }
 
-// implementations for isl::point
-point manage(__isl_take isl_point *ptr) {
-  return point(ptr);
-}
-point manage_copy(__isl_keep isl_point *ptr) {
-  ptr = isl_point_copy(ptr);
-  return point(ptr);
+isl::checked::schedule_node schedule_node::map_descendant_bottom_up(const std::function<isl::checked::schedule_node(isl::checked::schedule_node)> &fn) const
+{
+  struct fn_data {
+    std::function<isl::checked::schedule_node(isl::checked::schedule_node)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_schedule_node * {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_schedule_node_map_descendant_bottom_up(copy(), fn_lambda, &fn_data);
+  return manage(res);
 }
 
-point::point()
-    : ptr(nullptr) {}
-
-point::point(const point &obj)
-    : ptr(nullptr)
+class size schedule_node::n_children() const
 {
-  ptr = obj.copy();
+  auto res = isl_schedule_node_n_children(get());
+  return manage(res);
 }
 
-point::point(__isl_take isl_point *ptr)
-    : ptr(ptr) {}
-
-
-point &point::operator=(point obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::checked::schedule_node schedule_node::next_sibling() const
+{
+  auto res = isl_schedule_node_next_sibling(copy());
+  return manage(res);
 }
 
-point::~point() {
-  if (ptr)
-    isl_point_free(ptr);
+isl::checked::schedule_node schedule_node::order_after(isl::checked::union_set filter) const
+{
+  auto res = isl_schedule_node_order_after(copy(), filter.release());
+  return manage(res);
 }
 
-__isl_give isl_point *point::copy() const & {
-  return isl_point_copy(ptr);
+isl::checked::schedule_node schedule_node::order_before(isl::checked::union_set filter) const
+{
+  auto res = isl_schedule_node_order_before(copy(), filter.release());
+  return manage(res);
 }
 
-__isl_keep isl_point *point::get() const {
-  return ptr;
+isl::checked::schedule_node schedule_node::parent() const
+{
+  auto res = isl_schedule_node_parent(copy());
+  return manage(res);
 }
 
-__isl_give isl_point *point::release() {
-  isl_point *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::checked::schedule_node schedule_node::previous_sibling() const
+{
+  auto res = isl_schedule_node_previous_sibling(copy());
+  return manage(res);
 }
 
-bool point::is_null() const {
-  return ptr == nullptr;
+isl::checked::schedule_node schedule_node::root() const
+{
+  auto res = isl_schedule_node_root(copy());
+  return manage(res);
 }
 
-ctx point::get_ctx() const {
-  return ctx(isl_point_get_ctx(ptr));
+inline std::ostream &operator<<(std::ostream &os, const schedule_node &obj)
+{
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
+// implementations for isl::schedule_node_band
+schedule_node_band::schedule_node_band()
+    : schedule_node() {}
 
-// implementations for isl::pw_aff
-pw_aff manage(__isl_take isl_pw_aff *ptr) {
-  return pw_aff(ptr);
-}
-pw_aff manage_copy(__isl_keep isl_pw_aff *ptr) {
-  ptr = isl_pw_aff_copy(ptr);
-  return pw_aff(ptr);
+schedule_node_band::schedule_node_band(const schedule_node_band &obj)
+    : schedule_node(obj)
+{
 }
 
-pw_aff::pw_aff()
-    : ptr(nullptr) {}
+schedule_node_band::schedule_node_band(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
 
-pw_aff::pw_aff(const pw_aff &obj)
-    : ptr(nullptr)
-{
-  ptr = obj.copy();
+schedule_node_band &schedule_node_band::operator=(schedule_node_band obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-pw_aff::pw_aff(__isl_take isl_pw_aff *ptr)
-    : ptr(ptr) {}
-
-pw_aff::pw_aff(aff aff)
-{
-  auto res = isl_pw_aff_from_aff(aff.release());
-  ptr = res;
+isl::checked::ctx schedule_node_band::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
 }
-pw_aff::pw_aff(ctx ctx, const std::string &str)
+
+isl::checked::union_set schedule_node_band::ast_build_options() const
 {
-  auto res = isl_pw_aff_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
+  auto res = isl_schedule_node_band_get_ast_build_options(get());
+  return manage(res);
 }
 
-pw_aff &pw_aff::operator=(pw_aff obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::checked::union_set schedule_node_band::get_ast_build_options() const
+{
+  return ast_build_options();
 }
 
-pw_aff::~pw_aff() {
-  if (ptr)
-    isl_pw_aff_free(ptr);
+isl::checked::set schedule_node_band::ast_isolate_option() const
+{
+  auto res = isl_schedule_node_band_get_ast_isolate_option(get());
+  return manage(res);
 }
 
-__isl_give isl_pw_aff *pw_aff::copy() const & {
-  return isl_pw_aff_copy(ptr);
+isl::checked::set schedule_node_band::get_ast_isolate_option() const
+{
+  return ast_isolate_option();
 }
 
-__isl_keep isl_pw_aff *pw_aff::get() const {
-  return ptr;
+isl::checked::multi_union_pw_aff schedule_node_band::partial_schedule() const
+{
+  auto res = isl_schedule_node_band_get_partial_schedule(get());
+  return manage(res);
 }
 
-__isl_give isl_pw_aff *pw_aff::release() {
-  isl_pw_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::checked::multi_union_pw_aff schedule_node_band::get_partial_schedule() const
+{
+  return partial_schedule();
 }
 
-bool pw_aff::is_null() const {
-  return ptr == nullptr;
+boolean schedule_node_band::permutable() const
+{
+  auto res = isl_schedule_node_band_get_permutable(get());
+  return manage(res);
 }
 
-ctx pw_aff::get_ctx() const {
-  return ctx(isl_pw_aff_get_ctx(ptr));
+boolean schedule_node_band::get_permutable() const
+{
+  return permutable();
 }
 
-pw_aff pw_aff::add(pw_aff pwaff2) const
+boolean schedule_node_band::member_get_coincident(int pos) const
 {
-  auto res = isl_pw_aff_add(copy(), pwaff2.release());
+  auto res = isl_schedule_node_band_member_get_coincident(get(), pos);
   return manage(res);
 }
 
-pw_aff pw_aff::ceil() const
+schedule_node_band schedule_node_band::member_set_coincident(int pos, int coincident) const
 {
-  auto res = isl_pw_aff_ceil(copy());
-  return manage(res);
+  auto res = isl_schedule_node_band_member_set_coincident(copy(), pos, coincident);
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::cond(pw_aff pwaff_true, pw_aff pwaff_false) const
+schedule_node_band schedule_node_band::mod(isl::checked::multi_val mv) const
 {
-  auto res = isl_pw_aff_cond(copy(), pwaff_true.release(), pwaff_false.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_mod(copy(), mv.release());
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::div(pw_aff pa2) const
+class size schedule_node_band::n_member() const
 {
-  auto res = isl_pw_aff_div(copy(), pa2.release());
+  auto res = isl_schedule_node_band_n_member(get());
   return manage(res);
 }
 
-set pw_aff::eq_set(pw_aff pwaff2) const
+schedule_node_band schedule_node_band::scale(isl::checked::multi_val mv) const
 {
-  auto res = isl_pw_aff_eq_set(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_scale(copy(), mv.release());
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::floor() const
+schedule_node_band schedule_node_band::scale_down(isl::checked::multi_val mv) const
 {
-  auto res = isl_pw_aff_floor(copy());
-  return manage(res);
+  auto res = isl_schedule_node_band_scale_down(copy(), mv.release());
+  return manage(res).as<schedule_node_band>();
 }
 
-set pw_aff::ge_set(pw_aff pwaff2) const
+schedule_node_band schedule_node_band::set_ast_build_options(isl::checked::union_set options) const
 {
-  auto res = isl_pw_aff_ge_set(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_set_ast_build_options(copy(), options.release());
+  return manage(res).as<schedule_node_band>();
 }
 
-set pw_aff::gt_set(pw_aff pwaff2) const
+schedule_node_band schedule_node_band::set_permutable(int permutable) const
 {
-  auto res = isl_pw_aff_gt_set(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_set_permutable(copy(), permutable);
+  return manage(res).as<schedule_node_band>();
 }
 
-set pw_aff::le_set(pw_aff pwaff2) const
+schedule_node_band schedule_node_band::shift(isl::checked::multi_union_pw_aff shift) const
 {
-  auto res = isl_pw_aff_le_set(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_shift(copy(), shift.release());
+  return manage(res).as<schedule_node_band>();
 }
 
-set pw_aff::lt_set(pw_aff pwaff2) const
+schedule_node_band schedule_node_band::split(int pos) const
 {
-  auto res = isl_pw_aff_lt_set(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_split(copy(), pos);
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::max(pw_aff pwaff2) const
+schedule_node_band schedule_node_band::tile(isl::checked::multi_val sizes) const
 {
-  auto res = isl_pw_aff_max(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_tile(copy(), sizes.release());
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::min(pw_aff pwaff2) const
+
+schedule_node_band schedule_node_band::member_set_ast_loop_default(int pos) const
 {
-  auto res = isl_pw_aff_min(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_default);
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::mod(val mod) const
+
+schedule_node_band schedule_node_band::member_set_ast_loop_atomic(int pos) const
 {
-  auto res = isl_pw_aff_mod_val(copy(), mod.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_atomic);
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::mul(pw_aff pwaff2) const
+
+schedule_node_band schedule_node_band::member_set_ast_loop_unroll(int pos) const
 {
-  auto res = isl_pw_aff_mul(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_unroll);
+  return manage(res).as<schedule_node_band>();
 }
 
-set pw_aff::ne_set(pw_aff pwaff2) const
+
+schedule_node_band schedule_node_band::member_set_ast_loop_separate(int pos) const
 {
-  auto res = isl_pw_aff_ne_set(copy(), pwaff2.release());
-  return manage(res);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_separate);
+  return manage(res).as<schedule_node_band>();
 }
 
-pw_aff pw_aff::neg() const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_band &obj)
 {
-  auto res = isl_pw_aff_neg(copy());
-  return manage(res);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-pw_aff pw_aff::pullback(multi_aff ma) const
+// implementations for isl::schedule_node_context
+schedule_node_context::schedule_node_context()
+    : schedule_node() {}
+
+schedule_node_context::schedule_node_context(const schedule_node_context &obj)
+    : schedule_node(obj)
 {
-  auto res = isl_pw_aff_pullback_multi_aff(copy(), ma.release());
-  return manage(res);
 }
 
-pw_aff pw_aff::pullback(pw_multi_aff pma) const
+schedule_node_context::schedule_node_context(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_context &schedule_node_context::operator=(schedule_node_context obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx schedule_node_context::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+isl::checked::set schedule_node_context::context() const
 {
-  auto res = isl_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  auto res = isl_schedule_node_context_get_context(get());
   return manage(res);
 }
 
-pw_aff pw_aff::pullback(multi_pw_aff mpa) const
+isl::checked::set schedule_node_context::get_context() const
 {
-  auto res = isl_pw_aff_pullback_multi_pw_aff(copy(), mpa.release());
-  return manage(res);
+  return context();
 }
 
-pw_aff pw_aff::scale(val v) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_context &obj)
 {
-  auto res = isl_pw_aff_scale_val(copy(), v.release());
-  return manage(res);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-pw_aff pw_aff::scale_down(val f) const
+// implementations for isl::schedule_node_domain
+schedule_node_domain::schedule_node_domain()
+    : schedule_node() {}
+
+schedule_node_domain::schedule_node_domain(const schedule_node_domain &obj)
+    : schedule_node(obj)
 {
-  auto res = isl_pw_aff_scale_down_val(copy(), f.release());
-  return manage(res);
 }
 
-pw_aff pw_aff::sub(pw_aff pwaff2) const
+schedule_node_domain::schedule_node_domain(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_domain &schedule_node_domain::operator=(schedule_node_domain obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx schedule_node_domain::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+isl::checked::union_set schedule_node_domain::domain() const
 {
-  auto res = isl_pw_aff_sub(copy(), pwaff2.release());
+  auto res = isl_schedule_node_domain_get_domain(get());
   return manage(res);
 }
 
-pw_aff pw_aff::tdiv_q(pw_aff pa2) const
+isl::checked::union_set schedule_node_domain::get_domain() const
 {
-  auto res = isl_pw_aff_tdiv_q(copy(), pa2.release());
-  return manage(res);
+  return domain();
 }
 
-pw_aff pw_aff::tdiv_r(pw_aff pa2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_domain &obj)
 {
-  auto res = isl_pw_aff_tdiv_r(copy(), pa2.release());
-  return manage(res);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-pw_aff pw_aff::union_add(pw_aff pwaff2) const
+// implementations for isl::schedule_node_expansion
+schedule_node_expansion::schedule_node_expansion()
+    : schedule_node() {}
+
+schedule_node_expansion::schedule_node_expansion(const schedule_node_expansion &obj)
+    : schedule_node(obj)
 {
-  auto res = isl_pw_aff_union_add(copy(), pwaff2.release());
-  return manage(res);
 }
 
-// implementations for isl::pw_multi_aff
-pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr) {
-  return pw_multi_aff(ptr);
+schedule_node_expansion::schedule_node_expansion(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_expansion &schedule_node_expansion::operator=(schedule_node_expansion obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
-pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr) {
-  ptr = isl_pw_multi_aff_copy(ptr);
-  return pw_multi_aff(ptr);
+
+isl::checked::ctx schedule_node_expansion::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-pw_multi_aff::pw_multi_aff()
-    : ptr(nullptr) {}
+isl::checked::union_pw_multi_aff schedule_node_expansion::contraction() const
+{
+  auto res = isl_schedule_node_expansion_get_contraction(get());
+  return manage(res);
+}
 
-pw_multi_aff::pw_multi_aff(const pw_multi_aff &obj)
-    : ptr(nullptr)
+isl::checked::union_pw_multi_aff schedule_node_expansion::get_contraction() const
 {
-  ptr = obj.copy();
+  return contraction();
 }
 
-pw_multi_aff::pw_multi_aff(__isl_take isl_pw_multi_aff *ptr)
-    : ptr(ptr) {}
+isl::checked::union_map schedule_node_expansion::expansion() const
+{
+  auto res = isl_schedule_node_expansion_get_expansion(get());
+  return manage(res);
+}
 
-pw_multi_aff::pw_multi_aff(multi_aff ma)
+isl::checked::union_map schedule_node_expansion::get_expansion() const
 {
-  auto res = isl_pw_multi_aff_from_multi_aff(ma.release());
-  ptr = res;
+  return expansion();
 }
-pw_multi_aff::pw_multi_aff(pw_aff pa)
+
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_expansion &obj)
 {
-  auto res = isl_pw_multi_aff_from_pw_aff(pa.release());
-  ptr = res;
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
-pw_multi_aff::pw_multi_aff(ctx ctx, const std::string &str)
+
+// implementations for isl::schedule_node_extension
+schedule_node_extension::schedule_node_extension()
+    : schedule_node() {}
+
+schedule_node_extension::schedule_node_extension(const schedule_node_extension &obj)
+    : schedule_node(obj)
 {
-  auto res = isl_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
 }
 
-pw_multi_aff &pw_multi_aff::operator=(pw_multi_aff obj) {
+schedule_node_extension::schedule_node_extension(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_extension &schedule_node_extension::operator=(schedule_node_extension obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-pw_multi_aff::~pw_multi_aff() {
-  if (ptr)
-    isl_pw_multi_aff_free(ptr);
+isl::checked::ctx schedule_node_extension::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-__isl_give isl_pw_multi_aff *pw_multi_aff::copy() const & {
-  return isl_pw_multi_aff_copy(ptr);
+isl::checked::union_map schedule_node_extension::extension() const
+{
+  auto res = isl_schedule_node_extension_get_extension(get());
+  return manage(res);
 }
 
-__isl_keep isl_pw_multi_aff *pw_multi_aff::get() const {
-  return ptr;
+isl::checked::union_map schedule_node_extension::get_extension() const
+{
+  return extension();
 }
 
-__isl_give isl_pw_multi_aff *pw_multi_aff::release() {
-  isl_pw_multi_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_extension &obj)
+{
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-bool pw_multi_aff::is_null() const {
-  return ptr == nullptr;
+// implementations for isl::schedule_node_filter
+schedule_node_filter::schedule_node_filter()
+    : schedule_node() {}
+
+schedule_node_filter::schedule_node_filter(const schedule_node_filter &obj)
+    : schedule_node(obj)
+{
+}
+
+schedule_node_filter::schedule_node_filter(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_filter &schedule_node_filter::operator=(schedule_node_filter obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-ctx pw_multi_aff::get_ctx() const {
-  return ctx(isl_pw_multi_aff_get_ctx(ptr));
+isl::checked::ctx schedule_node_filter::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-pw_multi_aff pw_multi_aff::add(pw_multi_aff pma2) const
+isl::checked::union_set schedule_node_filter::filter() const
 {
-  auto res = isl_pw_multi_aff_add(copy(), pma2.release());
+  auto res = isl_schedule_node_filter_get_filter(get());
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::flat_range_product(pw_multi_aff pma2) const
+isl::checked::union_set schedule_node_filter::get_filter() const
 {
-  auto res = isl_pw_multi_aff_flat_range_product(copy(), pma2.release());
-  return manage(res);
+  return filter();
 }
 
-pw_multi_aff pw_multi_aff::product(pw_multi_aff pma2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_filter &obj)
 {
-  auto res = isl_pw_multi_aff_product(copy(), pma2.release());
-  return manage(res);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-pw_multi_aff pw_multi_aff::pullback(multi_aff ma) const
+// implementations for isl::schedule_node_guard
+schedule_node_guard::schedule_node_guard()
+    : schedule_node() {}
+
+schedule_node_guard::schedule_node_guard(const schedule_node_guard &obj)
+    : schedule_node(obj)
 {
-  auto res = isl_pw_multi_aff_pullback_multi_aff(copy(), ma.release());
-  return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::pullback(pw_multi_aff pma2) const
+schedule_node_guard::schedule_node_guard(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_guard &schedule_node_guard::operator=(schedule_node_guard obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx schedule_node_guard::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+isl::checked::set schedule_node_guard::guard() const
 {
-  auto res = isl_pw_multi_aff_pullback_pw_multi_aff(copy(), pma2.release());
+  auto res = isl_schedule_node_guard_get_guard(get());
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::range_product(pw_multi_aff pma2) const
+isl::checked::set schedule_node_guard::get_guard() const
 {
-  auto res = isl_pw_multi_aff_range_product(copy(), pma2.release());
-  return manage(res);
+  return guard();
 }
 
-pw_multi_aff pw_multi_aff::union_add(pw_multi_aff pma2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_guard &obj)
 {
-  auto res = isl_pw_multi_aff_union_add(copy(), pma2.release());
-  return manage(res);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::schedule
-schedule manage(__isl_take isl_schedule *ptr) {
-  return schedule(ptr);
+// implementations for isl::schedule_node_leaf
+schedule_node_leaf::schedule_node_leaf()
+    : schedule_node() {}
+
+schedule_node_leaf::schedule_node_leaf(const schedule_node_leaf &obj)
+    : schedule_node(obj)
+{
 }
-schedule manage_copy(__isl_keep isl_schedule *ptr) {
-  ptr = isl_schedule_copy(ptr);
-  return schedule(ptr);
+
+schedule_node_leaf::schedule_node_leaf(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_leaf &schedule_node_leaf::operator=(schedule_node_leaf obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-schedule::schedule()
-    : ptr(nullptr) {}
+isl::checked::ctx schedule_node_leaf::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
+}
 
-schedule::schedule(const schedule &obj)
-    : ptr(nullptr)
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_leaf &obj)
 {
-  ptr = obj.copy();
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-schedule::schedule(__isl_take isl_schedule *ptr)
-    : ptr(ptr) {}
+// implementations for isl::schedule_node_mark
+schedule_node_mark::schedule_node_mark()
+    : schedule_node() {}
 
-schedule::schedule(ctx ctx, const std::string &str)
+schedule_node_mark::schedule_node_mark(const schedule_node_mark &obj)
+    : schedule_node(obj)
 {
-  auto res = isl_schedule_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
 }
 
-schedule &schedule::operator=(schedule obj) {
+schedule_node_mark::schedule_node_mark(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_mark &schedule_node_mark::operator=(schedule_node_mark obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-schedule::~schedule() {
-  if (ptr)
-    isl_schedule_free(ptr);
+isl::checked::ctx schedule_node_mark::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-__isl_give isl_schedule *schedule::copy() const & {
-  return isl_schedule_copy(ptr);
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_mark &obj)
+{
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-__isl_keep isl_schedule *schedule::get() const {
-  return ptr;
-}
+// implementations for isl::schedule_node_sequence
+schedule_node_sequence::schedule_node_sequence()
+    : schedule_node() {}
 
-__isl_give isl_schedule *schedule::release() {
-  isl_schedule *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+schedule_node_sequence::schedule_node_sequence(const schedule_node_sequence &obj)
+    : schedule_node(obj)
+{
 }
 
-bool schedule::is_null() const {
-  return ptr == nullptr;
+schedule_node_sequence::schedule_node_sequence(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_sequence &schedule_node_sequence::operator=(schedule_node_sequence obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-ctx schedule::get_ctx() const {
-  return ctx(isl_schedule_get_ctx(ptr));
+isl::checked::ctx schedule_node_sequence::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-union_map schedule::get_map() const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_sequence &obj)
 {
-  auto res = isl_schedule_get_map(get());
-  return manage(res);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-schedule_node schedule::get_root() const
+// implementations for isl::schedule_node_set
+schedule_node_set::schedule_node_set()
+    : schedule_node() {}
+
+schedule_node_set::schedule_node_set(const schedule_node_set &obj)
+    : schedule_node(obj)
 {
-  auto res = isl_schedule_get_root(get());
-  return manage(res);
 }
 
-schedule schedule::pullback(union_pw_multi_aff upma) const
+schedule_node_set::schedule_node_set(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_set &schedule_node_set::operator=(schedule_node_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::checked::ctx schedule_node_set::ctx() const {
+  return isl::checked::ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_set &obj)
 {
-  auto res = isl_schedule_pullback_union_pw_multi_aff(copy(), upma.release());
-  return manage(res);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::schedule_constraints
-schedule_constraints manage(__isl_take isl_schedule_constraints *ptr) {
-  return schedule_constraints(ptr);
+// implementations for isl::set
+set manage(__isl_take isl_set *ptr) {
+  return set(ptr);
 }
-schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr) {
-  ptr = isl_schedule_constraints_copy(ptr);
-  return schedule_constraints(ptr);
+set manage_copy(__isl_keep isl_set *ptr) {
+  ptr = isl_set_copy(ptr);
+  return set(ptr);
 }
 
-schedule_constraints::schedule_constraints()
+set::set()
     : ptr(nullptr) {}
 
-schedule_constraints::schedule_constraints(const schedule_constraints &obj)
-    : ptr(nullptr)
+set::set(const set &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+set::set(__isl_take isl_set *ptr)
+    : ptr(ptr) {}
+
+set::set(isl::checked::basic_set bset)
 {
-  ptr = obj.copy();
+  auto res = isl_set_from_basic_set(bset.release());
+  ptr = res;
 }
 
-schedule_constraints::schedule_constraints(__isl_take isl_schedule_constraints *ptr)
-    : ptr(ptr) {}
+set::set(isl::checked::point pnt)
+{
+  auto res = isl_set_from_point(pnt.release());
+  ptr = res;
+}
 
-schedule_constraints::schedule_constraints(ctx ctx, const std::string &str)
+set::set(isl::checked::ctx ctx, const std::string &str)
 {
-  auto res = isl_schedule_constraints_read_from_str(ctx.release(), str.c_str());
+  auto res = isl_set_read_from_str(ctx.release(), str.c_str());
   ptr = res;
 }
 
-schedule_constraints &schedule_constraints::operator=(schedule_constraints obj) {
+set &set::operator=(set obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-schedule_constraints::~schedule_constraints() {
+set::~set() {
   if (ptr)
-    isl_schedule_constraints_free(ptr);
+    isl_set_free(ptr);
 }
 
-__isl_give isl_schedule_constraints *schedule_constraints::copy() const & {
-  return isl_schedule_constraints_copy(ptr);
+__isl_give isl_set *set::copy() const & {
+  return isl_set_copy(ptr);
 }
 
-__isl_keep isl_schedule_constraints *schedule_constraints::get() const {
+__isl_keep isl_set *set::get() const {
   return ptr;
 }
 
-__isl_give isl_schedule_constraints *schedule_constraints::release() {
-  isl_schedule_constraints *tmp = ptr;
+__isl_give isl_set *set::release() {
+  isl_set *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool schedule_constraints::is_null() const {
+bool set::is_null() const {
   return ptr == nullptr;
 }
 
-ctx schedule_constraints::get_ctx() const {
-  return ctx(isl_schedule_constraints_get_ctx(ptr));
+isl::checked::ctx set::ctx() const {
+  return isl::checked::ctx(isl_set_get_ctx(ptr));
 }
 
-schedule schedule_constraints::compute_schedule() const
+isl::checked::basic_set set::affine_hull() const
 {
-  auto res = isl_schedule_constraints_compute_schedule(copy());
+  auto res = isl_set_affine_hull(copy());
   return manage(res);
 }
 
-union_map schedule_constraints::get_coincidence() const
+isl::checked::set set::apply(isl::checked::map map) const
 {
-  auto res = isl_schedule_constraints_get_coincidence(get());
+  auto res = isl_set_apply(copy(), map.release());
   return manage(res);
 }
 
-union_map schedule_constraints::get_conditional_validity() const
+isl::checked::set set::bind(isl::checked::multi_id tuple) const
 {
-  auto res = isl_schedule_constraints_get_conditional_validity(get());
+  auto res = isl_set_bind(copy(), tuple.release());
   return manage(res);
 }
 
-union_map schedule_constraints::get_conditional_validity_condition() const
+isl::checked::set set::coalesce() const
 {
-  auto res = isl_schedule_constraints_get_conditional_validity_condition(get());
+  auto res = isl_set_coalesce(copy());
   return manage(res);
 }
 
-set schedule_constraints::get_context() const
+isl::checked::set set::complement() const
 {
-  auto res = isl_schedule_constraints_get_context(get());
+  auto res = isl_set_complement(copy());
   return manage(res);
 }
 
-union_set schedule_constraints::get_domain() const
+isl::checked::set set::detect_equalities() const
 {
-  auto res = isl_schedule_constraints_get_domain(get());
+  auto res = isl_set_detect_equalities(copy());
   return manage(res);
 }
 
-union_map schedule_constraints::get_proximity() const
+isl::checked::set set::empty(isl::checked::space space)
 {
-  auto res = isl_schedule_constraints_get_proximity(get());
+  auto res = isl_set_empty(space.release());
   return manage(res);
 }
 
-union_map schedule_constraints::get_validity() const
+isl::checked::set set::flatten() const
 {
-  auto res = isl_schedule_constraints_get_validity(get());
+  auto res = isl_set_flatten(copy());
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::on_domain(union_set domain)
+stat set::foreach_basic_set(const std::function<stat(isl::checked::basic_set)> &fn) const
 {
-  auto res = isl_schedule_constraints_on_domain(domain.release());
+  struct fn_data {
+    std::function<stat(isl::checked::basic_set)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_basic_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_set_foreach_basic_set(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_coincidence(union_map coincidence) const
+stat set::foreach_point(const std::function<stat(isl::checked::point)> &fn) const
 {
-  auto res = isl_schedule_constraints_set_coincidence(copy(), coincidence.release());
+  struct fn_data {
+    std::function<stat(isl::checked::point)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_point *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_set_foreach_point(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_conditional_validity(union_map condition, union_map validity) const
+isl::checked::multi_val set::plain_multi_val_if_fixed() const
 {
-  auto res = isl_schedule_constraints_set_conditional_validity(copy(), condition.release(), validity.release());
+  auto res = isl_set_get_plain_multi_val_if_fixed(get());
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_context(set context) const
+isl::checked::multi_val set::get_plain_multi_val_if_fixed() const
 {
-  auto res = isl_schedule_constraints_set_context(copy(), context.release());
-  return manage(res);
+  return plain_multi_val_if_fixed();
 }
 
-schedule_constraints schedule_constraints::set_proximity(union_map proximity) const
+isl::checked::fixed_box set::simple_fixed_box_hull() const
 {
-  auto res = isl_schedule_constraints_set_proximity(copy(), proximity.release());
+  auto res = isl_set_get_simple_fixed_box_hull(get());
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_validity(union_map validity) const
+isl::checked::fixed_box set::get_simple_fixed_box_hull() const
 {
-  auto res = isl_schedule_constraints_set_validity(copy(), validity.release());
-  return manage(res);
+  return simple_fixed_box_hull();
 }
 
-// implementations for isl::schedule_node
-schedule_node manage(__isl_take isl_schedule_node *ptr) {
-  return schedule_node(ptr);
-}
-schedule_node manage_copy(__isl_keep isl_schedule_node *ptr) {
-  ptr = isl_schedule_node_copy(ptr);
-  return schedule_node(ptr);
+isl::checked::space set::space() const
+{
+  auto res = isl_set_get_space(get());
+  return manage(res);
 }
 
-schedule_node::schedule_node()
-    : ptr(nullptr) {}
-
-schedule_node::schedule_node(const schedule_node &obj)
-    : ptr(nullptr)
+isl::checked::space set::get_space() const
 {
-  ptr = obj.copy();
+  return space();
 }
 
-schedule_node::schedule_node(__isl_take isl_schedule_node *ptr)
-    : ptr(ptr) {}
+isl::checked::val set::stride(int pos) const
+{
+  auto res = isl_set_get_stride(get(), pos);
+  return manage(res);
+}
 
+isl::checked::val set::get_stride(int pos) const
+{
+  return stride(pos);
+}
 
-schedule_node &schedule_node::operator=(schedule_node obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::checked::set set::gist(isl::checked::set context) const
+{
+  auto res = isl_set_gist(copy(), context.release());
+  return manage(res);
 }
 
-schedule_node::~schedule_node() {
-  if (ptr)
-    isl_schedule_node_free(ptr);
+isl::checked::map set::identity() const
+{
+  auto res = isl_set_identity(copy());
+  return manage(res);
 }
 
-__isl_give isl_schedule_node *schedule_node::copy() const & {
-  return isl_schedule_node_copy(ptr);
+isl::checked::pw_aff set::indicator_function() const
+{
+  auto res = isl_set_indicator_function(copy());
+  return manage(res);
 }
 
-__isl_keep isl_schedule_node *schedule_node::get() const {
-  return ptr;
+isl::checked::set set::intersect(isl::checked::set set2) const
+{
+  auto res = isl_set_intersect(copy(), set2.release());
+  return manage(res);
 }
 
-__isl_give isl_schedule_node *schedule_node::release() {
-  isl_schedule_node *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::checked::set set::intersect_params(isl::checked::set params) const
+{
+  auto res = isl_set_intersect_params(copy(), params.release());
+  return manage(res);
 }
 
-bool schedule_node::is_null() const {
-  return ptr == nullptr;
+boolean set::is_disjoint(const isl::checked::set &set2) const
+{
+  auto res = isl_set_is_disjoint(get(), set2.get());
+  return manage(res);
 }
 
-ctx schedule_node::get_ctx() const {
-  return ctx(isl_schedule_node_get_ctx(ptr));
+boolean set::is_empty() const
+{
+  auto res = isl_set_is_empty(get());
+  return manage(res);
 }
 
-boolean schedule_node::band_member_get_coincident(int pos) const
+boolean set::is_equal(const isl::checked::set &set2) const
 {
-  auto res = isl_schedule_node_band_member_get_coincident(get(), pos);
+  auto res = isl_set_is_equal(get(), set2.get());
   return manage(res);
 }
 
-schedule_node schedule_node::band_member_set_coincident(int pos, int coincident) const
+boolean set::is_singleton() const
 {
-  auto res = isl_schedule_node_band_member_set_coincident(copy(), pos, coincident);
+  auto res = isl_set_is_singleton(get());
   return manage(res);
 }
 
-schedule_node schedule_node::child(int pos) const
+boolean set::is_strict_subset(const isl::checked::set &set2) const
 {
-  auto res = isl_schedule_node_child(copy(), pos);
+  auto res = isl_set_is_strict_subset(get(), set2.get());
   return manage(res);
 }
 
-multi_union_pw_aff schedule_node::get_prefix_schedule_multi_union_pw_aff() const
+boolean set::is_subset(const isl::checked::set &set2) const
 {
-  auto res = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(get());
+  auto res = isl_set_is_subset(get(), set2.get());
   return manage(res);
 }
 
-union_map schedule_node::get_prefix_schedule_union_map() const
+boolean set::is_wrapping() const
 {
-  auto res = isl_schedule_node_get_prefix_schedule_union_map(get());
+  auto res = isl_set_is_wrapping(get());
   return manage(res);
 }
 
-union_pw_multi_aff schedule_node::get_prefix_schedule_union_pw_multi_aff() const
+isl::checked::set set::lexmax() const
 {
-  auto res = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(get());
+  auto res = isl_set_lexmax(copy());
   return manage(res);
 }
 
-schedule schedule_node::get_schedule() const
+isl::checked::pw_multi_aff set::lexmax_pw_multi_aff() const
 {
-  auto res = isl_schedule_node_get_schedule(get());
+  auto res = isl_set_lexmax_pw_multi_aff(copy());
   return manage(res);
 }
 
-schedule_node schedule_node::parent() const
+isl::checked::set set::lexmin() const
 {
-  auto res = isl_schedule_node_parent(copy());
+  auto res = isl_set_lexmin(copy());
   return manage(res);
 }
 
-// implementations for isl::set
-set manage(__isl_take isl_set *ptr) {
-  return set(ptr);
+isl::checked::pw_multi_aff set::lexmin_pw_multi_aff() const
+{
+  auto res = isl_set_lexmin_pw_multi_aff(copy());
+  return manage(res);
 }
-set manage_copy(__isl_keep isl_set *ptr) {
-  ptr = isl_set_copy(ptr);
-  return set(ptr);
+
+isl::checked::set set::lower_bound(isl::checked::multi_pw_aff lower) const
+{
+  auto res = isl_set_lower_bound_multi_pw_aff(copy(), lower.release());
+  return manage(res);
 }
 
-set::set()
-    : ptr(nullptr) {}
+isl::checked::set set::lower_bound(isl::checked::multi_val lower) const
+{
+  auto res = isl_set_lower_bound_multi_val(copy(), lower.release());
+  return manage(res);
+}
 
-set::set(const set &obj)
-    : ptr(nullptr)
+isl::checked::val set::max_val(const isl::checked::aff &obj) const
 {
-  ptr = obj.copy();
+  auto res = isl_set_max_val(get(), obj.get());
+  return manage(res);
 }
 
-set::set(__isl_take isl_set *ptr)
-    : ptr(ptr) {}
+isl::checked::val set::min_val(const isl::checked::aff &obj) const
+{
+  auto res = isl_set_min_val(get(), obj.get());
+  return manage(res);
+}
 
-set::set(ctx ctx, const std::string &str)
+isl::checked::set set::params() const
 {
-  auto res = isl_set_read_from_str(ctx.release(), str.c_str());
-  ptr = res;
+  auto res = isl_set_params(copy());
+  return manage(res);
 }
-set::set(basic_set bset)
+
+isl::checked::basic_set set::polyhedral_hull() const
 {
-  auto res = isl_set_from_basic_set(bset.release());
-  ptr = res;
+  auto res = isl_set_polyhedral_hull(copy());
+  return manage(res);
 }
-set::set(point pnt)
+
+isl::checked::set set::preimage(isl::checked::multi_aff ma) const
 {
-  auto res = isl_set_from_point(pnt.release());
-  ptr = res;
+  auto res = isl_set_preimage_multi_aff(copy(), ma.release());
+  return manage(res);
 }
 
-set &set::operator=(set obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::checked::set set::preimage(isl::checked::multi_pw_aff mpa) const
+{
+  auto res = isl_set_preimage_multi_pw_aff(copy(), mpa.release());
+  return manage(res);
 }
 
-set::~set() {
-  if (ptr)
-    isl_set_free(ptr);
+isl::checked::set set::preimage(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_set_preimage_pw_multi_aff(copy(), pma.release());
+  return manage(res);
 }
 
-__isl_give isl_set *set::copy() const & {
-  return isl_set_copy(ptr);
+isl::checked::set set::product(isl::checked::set set2) const
+{
+  auto res = isl_set_product(copy(), set2.release());
+  return manage(res);
 }
 
-__isl_keep isl_set *set::get() const {
-  return ptr;
+isl::checked::set set::project_out_all_params() const
+{
+  auto res = isl_set_project_out_all_params(copy());
+  return manage(res);
 }
 
-__isl_give isl_set *set::release() {
-  isl_set *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::checked::set set::project_out_param(isl::checked::id id) const
+{
+  auto res = isl_set_project_out_param_id(copy(), id.release());
+  return manage(res);
 }
 
-bool set::is_null() const {
-  return ptr == nullptr;
+isl::checked::set set::project_out_param(const std::string &id) const
+{
+  return this->project_out_param(isl::checked::id(ctx(), id));
 }
 
-ctx set::get_ctx() const {
-  return ctx(isl_set_get_ctx(ptr));
+isl::checked::set set::project_out_param(isl::checked::id_list list) const
+{
+  auto res = isl_set_project_out_param_id_list(copy(), list.release());
+  return manage(res);
 }
 
-basic_set set::affine_hull() const
+isl::checked::basic_set set::sample() const
 {
-  auto res = isl_set_affine_hull(copy());
+  auto res = isl_set_sample(copy());
   return manage(res);
 }
 
-set set::apply(map map) const
+isl::checked::point set::sample_point() const
 {
-  auto res = isl_set_apply(copy(), map.release());
+  auto res = isl_set_sample_point(copy());
   return manage(res);
 }
 
-set set::coalesce() const
+isl::checked::set set::subtract(isl::checked::set set2) const
 {
-  auto res = isl_set_coalesce(copy());
+  auto res = isl_set_subtract(copy(), set2.release());
   return manage(res);
 }
 
-set set::complement() const
+isl::checked::set set::unbind_params(isl::checked::multi_id tuple) const
 {
-  auto res = isl_set_complement(copy());
+  auto res = isl_set_unbind_params(copy(), tuple.release());
   return manage(res);
 }
 
-set set::detect_equalities() const
+isl::checked::map set::unbind_params_insert_domain(isl::checked::multi_id domain) const
 {
-  auto res = isl_set_detect_equalities(copy());
+  auto res = isl_set_unbind_params_insert_domain(copy(), domain.release());
   return manage(res);
 }
 
-set set::flatten() const
+isl::checked::set set::unite(isl::checked::set set2) const
 {
-  auto res = isl_set_flatten(copy());
+  auto res = isl_set_union(copy(), set2.release());
   return manage(res);
 }
 
-stat set::foreach_basic_set(const std::function<stat(basic_set)> &fn) const
+isl::checked::set set::universe(isl::checked::space space)
 {
-  struct fn_data {
-    const std::function<stat(basic_set)> *func;
-  } fn_data = { &fn };
-  auto fn_lambda = [](isl_basic_set *arg_0, void *arg_1) -> isl_stat {
-    auto *data = static_cast<struct fn_data *>(arg_1);
-    stat ret = (*data->func)(manage(arg_0));
-    return ret.release();
-  };
-  auto res = isl_set_foreach_basic_set(get(), fn_lambda, &fn_data);
+  auto res = isl_set_universe(space.release());
   return manage(res);
 }
 
-val set::get_stride(int pos) const
+isl::checked::basic_set set::unshifted_simple_hull() const
 {
-  auto res = isl_set_get_stride(get(), pos);
+  auto res = isl_set_unshifted_simple_hull(copy());
   return manage(res);
 }
 
-set set::gist(set context) const
+isl::checked::map set::unwrap() const
 {
-  auto res = isl_set_gist(copy(), context.release());
+  auto res = isl_set_unwrap(copy());
   return manage(res);
 }
 
-map set::identity() const
+isl::checked::set set::upper_bound(isl::checked::multi_pw_aff upper) const
 {
-  auto res = isl_set_identity(copy());
+  auto res = isl_set_upper_bound_multi_pw_aff(copy(), upper.release());
   return manage(res);
 }
 
-set set::intersect(set set2) const
+isl::checked::set set::upper_bound(isl::checked::multi_val upper) const
 {
-  auto res = isl_set_intersect(copy(), set2.release());
+  auto res = isl_set_upper_bound_multi_val(copy(), upper.release());
   return manage(res);
 }
 
-set set::intersect_params(set params) const
-{
-  auto res = isl_set_intersect_params(copy(), params.release());
-  return manage(res);
+inline std::ostream &operator<<(std::ostream &os, const set &obj)
+{
+  char *str = isl_set_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::space
+space manage(__isl_take isl_space *ptr) {
+  return space(ptr);
+}
+space manage_copy(__isl_keep isl_space *ptr) {
+  ptr = isl_space_copy(ptr);
+  return space(ptr);
+}
+
+space::space()
+    : ptr(nullptr) {}
+
+space::space(const space &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+space::space(__isl_take isl_space *ptr)
+    : ptr(ptr) {}
+
+space &space::operator=(space obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+space::~space() {
+  if (ptr)
+    isl_space_free(ptr);
+}
+
+__isl_give isl_space *space::copy() const & {
+  return isl_space_copy(ptr);
+}
+
+__isl_keep isl_space *space::get() const {
+  return ptr;
+}
+
+__isl_give isl_space *space::release() {
+  isl_space *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
 }
 
-boolean set::is_disjoint(const set &set2) const
-{
-  auto res = isl_set_is_disjoint(get(), set2.get());
-  return manage(res);
+bool space::is_null() const {
+  return ptr == nullptr;
 }
 
-boolean set::is_empty() const
+isl::checked::ctx space::ctx() const {
+  return isl::checked::ctx(isl_space_get_ctx(ptr));
+}
+
+isl::checked::space space::add_named_tuple(isl::checked::id tuple_id, unsigned int dim) const
 {
-  auto res = isl_set_is_empty(get());
+  auto res = isl_space_add_named_tuple_id_ui(copy(), tuple_id.release(), dim);
   return manage(res);
 }
 
-boolean set::is_equal(const set &set2) const
+isl::checked::space space::add_named_tuple(const std::string &tuple_id, unsigned int dim) const
 {
-  auto res = isl_set_is_equal(get(), set2.get());
-  return manage(res);
+  return this->add_named_tuple(isl::checked::id(ctx(), tuple_id), dim);
 }
 
-boolean set::is_strict_subset(const set &set2) const
+isl::checked::space space::add_unnamed_tuple(unsigned int dim) const
 {
-  auto res = isl_set_is_strict_subset(get(), set2.get());
+  auto res = isl_space_add_unnamed_tuple_ui(copy(), dim);
   return manage(res);
 }
 
-boolean set::is_subset(const set &set2) const
+isl::checked::space space::domain() const
 {
-  auto res = isl_set_is_subset(get(), set2.get());
+  auto res = isl_space_domain(copy());
   return manage(res);
 }
 
-boolean set::is_wrapping() const
+isl::checked::space space::flatten_domain() const
 {
-  auto res = isl_set_is_wrapping(get());
+  auto res = isl_space_flatten_domain(copy());
   return manage(res);
 }
 
-set set::lexmax() const
+isl::checked::space space::flatten_range() const
 {
-  auto res = isl_set_lexmax(copy());
+  auto res = isl_space_flatten_range(copy());
   return manage(res);
 }
 
-set set::lexmin() const
+boolean space::is_equal(const isl::checked::space &space2) const
 {
-  auto res = isl_set_lexmin(copy());
+  auto res = isl_space_is_equal(get(), space2.get());
   return manage(res);
 }
 
-val set::max_val(const aff &obj) const
+boolean space::is_wrapping() const
 {
-  auto res = isl_set_max_val(get(), obj.get());
+  auto res = isl_space_is_wrapping(get());
   return manage(res);
 }
 
-val set::min_val(const aff &obj) const
+isl::checked::space space::map_from_set() const
 {
-  auto res = isl_set_min_val(get(), obj.get());
+  auto res = isl_space_map_from_set(copy());
   return manage(res);
 }
 
-basic_set set::polyhedral_hull() const
+isl::checked::space space::params() const
 {
-  auto res = isl_set_polyhedral_hull(copy());
+  auto res = isl_space_params(copy());
   return manage(res);
 }
 
-basic_set set::sample() const
+isl::checked::space space::range() const
 {
-  auto res = isl_set_sample(copy());
+  auto res = isl_space_range(copy());
   return manage(res);
 }
 
-point set::sample_point() const
+isl::checked::space space::unit(isl::checked::ctx ctx)
 {
-  auto res = isl_set_sample_point(copy());
+  auto res = isl_space_unit(ctx.release());
   return manage(res);
 }
 
-set set::subtract(set set2) const
+isl::checked::space space::unwrap() const
 {
-  auto res = isl_set_subtract(copy(), set2.release());
+  auto res = isl_space_unwrap(copy());
   return manage(res);
 }
 
-set set::unite(set set2) const
+isl::checked::space space::wrap() const
 {
-  auto res = isl_set_union(copy(), set2.release());
+  auto res = isl_space_wrap(copy());
   return manage(res);
 }
 
-basic_set set::unshifted_simple_hull() const
+inline std::ostream &operator<<(std::ostream &os, const space &obj)
 {
-  auto res = isl_set_unshifted_simple_hull(copy());
-  return manage(res);
+  char *str = isl_space_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
 // implementations for isl::union_access_info
@@ -3569,7 +10492,7 @@ union_access_info::union_access_info(const union_access_info &obj)
 union_access_info::union_access_info(__isl_take isl_union_access_info *ptr)
     : ptr(ptr) {}
 
-union_access_info::union_access_info(union_map sink)
+union_access_info::union_access_info(isl::checked::union_map sink)
 {
   auto res = isl_union_access_info_from_sink(sink.release());
   ptr = res;
@@ -3603,46 +10526,58 @@ bool union_access_info::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_access_info::get_ctx() const {
-  return ctx(isl_union_access_info_get_ctx(ptr));
+isl::checked::ctx union_access_info::ctx() const {
+  return isl::checked::ctx(isl_union_access_info_get_ctx(ptr));
 }
 
-union_flow union_access_info::compute_flow() const
+isl::checked::union_flow union_access_info::compute_flow() const
 {
   auto res = isl_union_access_info_compute_flow(copy());
   return manage(res);
 }
 
-union_access_info union_access_info::set_kill(union_map kill) const
+isl::checked::union_access_info union_access_info::set_kill(isl::checked::union_map kill) const
 {
   auto res = isl_union_access_info_set_kill(copy(), kill.release());
   return manage(res);
 }
 
-union_access_info union_access_info::set_may_source(union_map may_source) const
+isl::checked::union_access_info union_access_info::set_may_source(isl::checked::union_map may_source) const
 {
   auto res = isl_union_access_info_set_may_source(copy(), may_source.release());
   return manage(res);
 }
 
-union_access_info union_access_info::set_must_source(union_map must_source) const
+isl::checked::union_access_info union_access_info::set_must_source(isl::checked::union_map must_source) const
 {
   auto res = isl_union_access_info_set_must_source(copy(), must_source.release());
   return manage(res);
 }
 
-union_access_info union_access_info::set_schedule(schedule schedule) const
+isl::checked::union_access_info union_access_info::set_schedule(isl::checked::schedule schedule) const
 {
   auto res = isl_union_access_info_set_schedule(copy(), schedule.release());
   return manage(res);
 }
 
-union_access_info union_access_info::set_schedule_map(union_map schedule_map) const
+isl::checked::union_access_info union_access_info::set_schedule_map(isl::checked::union_map schedule_map) const
 {
   auto res = isl_union_access_info_set_schedule_map(copy(), schedule_map.release());
   return manage(res);
 }
 
+inline std::ostream &operator<<(std::ostream &os, const union_access_info &obj)
+{
+  char *str = isl_union_access_info_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
 // implementations for isl::union_flow
 union_flow manage(__isl_take isl_union_flow *ptr) {
   return union_flow(ptr);
@@ -3664,7 +10599,6 @@ union_flow::union_flow(const union_flow &obj)
 union_flow::union_flow(__isl_take isl_union_flow *ptr)
     : ptr(ptr) {}
 
-
 union_flow &union_flow::operator=(union_flow obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
@@ -3693,46 +10627,88 @@ bool union_flow::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_flow::get_ctx() const {
-  return ctx(isl_union_flow_get_ctx(ptr));
+isl::checked::ctx union_flow::ctx() const {
+  return isl::checked::ctx(isl_union_flow_get_ctx(ptr));
 }
 
-union_map union_flow::get_full_may_dependence() const
+isl::checked::union_map union_flow::full_may_dependence() const
 {
   auto res = isl_union_flow_get_full_may_dependence(get());
   return manage(res);
 }
 
-union_map union_flow::get_full_must_dependence() const
+isl::checked::union_map union_flow::get_full_may_dependence() const
+{
+  return full_may_dependence();
+}
+
+isl::checked::union_map union_flow::full_must_dependence() const
 {
   auto res = isl_union_flow_get_full_must_dependence(get());
   return manage(res);
 }
 
-union_map union_flow::get_may_dependence() const
+isl::checked::union_map union_flow::get_full_must_dependence() const
+{
+  return full_must_dependence();
+}
+
+isl::checked::union_map union_flow::may_dependence() const
 {
   auto res = isl_union_flow_get_may_dependence(get());
   return manage(res);
 }
 
-union_map union_flow::get_may_no_source() const
+isl::checked::union_map union_flow::get_may_dependence() const
+{
+  return may_dependence();
+}
+
+isl::checked::union_map union_flow::may_no_source() const
 {
   auto res = isl_union_flow_get_may_no_source(get());
   return manage(res);
 }
 
-union_map union_flow::get_must_dependence() const
+isl::checked::union_map union_flow::get_may_no_source() const
+{
+  return may_no_source();
+}
+
+isl::checked::union_map union_flow::must_dependence() const
 {
   auto res = isl_union_flow_get_must_dependence(get());
   return manage(res);
 }
 
-union_map union_flow::get_must_no_source() const
+isl::checked::union_map union_flow::get_must_dependence() const
+{
+  return must_dependence();
+}
+
+isl::checked::union_map union_flow::must_no_source() const
 {
   auto res = isl_union_flow_get_must_no_source(get());
   return manage(res);
 }
 
+isl::checked::union_map union_flow::get_must_no_source() const
+{
+  return must_no_source();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const union_flow &obj)
+{
+  char *str = isl_union_flow_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
 // implementations for isl::union_map
 union_map manage(__isl_take isl_union_map *ptr) {
   return union_map(ptr);
@@ -3754,17 +10730,19 @@ union_map::union_map(const union_map &obj)
 union_map::union_map(__isl_take isl_union_map *ptr)
     : ptr(ptr) {}
 
-union_map::union_map(basic_map bmap)
+union_map::union_map(isl::checked::basic_map bmap)
 {
   auto res = isl_union_map_from_basic_map(bmap.release());
   ptr = res;
 }
-union_map::union_map(map map)
+
+union_map::union_map(isl::checked::map map)
 {
   auto res = isl_union_map_from_map(map.release());
   ptr = res;
 }
-union_map::union_map(ctx ctx, const std::string &str)
+
+union_map::union_map(isl::checked::ctx ctx, const std::string &str)
 {
   auto res = isl_union_map_read_from_str(ctx.release(), str.c_str());
   ptr = res;
@@ -3798,430 +10776,783 @@ bool union_map::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_map::get_ctx() const {
-  return ctx(isl_union_map_get_ctx(ptr));
+isl::checked::ctx union_map::ctx() const {
+  return isl::checked::ctx(isl_union_map_get_ctx(ptr));
 }
 
-union_map union_map::affine_hull() const
+isl::checked::union_map union_map::affine_hull() const
 {
   auto res = isl_union_map_affine_hull(copy());
   return manage(res);
 }
 
-union_map union_map::apply_domain(union_map umap2) const
+isl::checked::union_map union_map::apply_domain(isl::checked::union_map umap2) const
 {
   auto res = isl_union_map_apply_domain(copy(), umap2.release());
   return manage(res);
 }
 
-union_map union_map::apply_range(union_map umap2) const
+isl::checked::union_map union_map::apply_range(isl::checked::union_map umap2) const
 {
   auto res = isl_union_map_apply_range(copy(), umap2.release());
   return manage(res);
 }
 
-union_map union_map::coalesce() const
+isl::checked::union_set union_map::bind_range(isl::checked::multi_id tuple) const
+{
+  auto res = isl_union_map_bind_range(copy(), tuple.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::coalesce() const
 {
   auto res = isl_union_map_coalesce(copy());
   return manage(res);
 }
 
-union_map union_map::compute_divs() const
+isl::checked::union_map union_map::compute_divs() const
 {
   auto res = isl_union_map_compute_divs(copy());
   return manage(res);
 }
 
-union_set union_map::deltas() const
+isl::checked::union_map union_map::curry() const
+{
+  auto res = isl_union_map_curry(copy());
+  return manage(res);
+}
+
+isl::checked::union_set union_map::deltas() const
 {
   auto res = isl_union_map_deltas(copy());
   return manage(res);
 }
 
-union_map union_map::detect_equalities() const
+isl::checked::union_map union_map::detect_equalities() const
 {
   auto res = isl_union_map_detect_equalities(copy());
   return manage(res);
 }
 
-union_set union_map::domain() const
+isl::checked::union_set union_map::domain() const
 {
   auto res = isl_union_map_domain(copy());
   return manage(res);
 }
 
-union_map union_map::domain_factor_domain() const
+isl::checked::union_map union_map::domain_factor_domain() const
 {
   auto res = isl_union_map_domain_factor_domain(copy());
   return manage(res);
 }
 
-union_map union_map::domain_factor_range() const
+isl::checked::union_map union_map::domain_factor_range() const
 {
   auto res = isl_union_map_domain_factor_range(copy());
   return manage(res);
 }
 
-union_map union_map::domain_map() const
+isl::checked::union_map union_map::domain_map() const
 {
   auto res = isl_union_map_domain_map(copy());
   return manage(res);
 }
 
-union_pw_multi_aff union_map::domain_map_union_pw_multi_aff() const
+isl::checked::union_pw_multi_aff union_map::domain_map_union_pw_multi_aff() const
 {
   auto res = isl_union_map_domain_map_union_pw_multi_aff(copy());
   return manage(res);
 }
 
-union_map union_map::domain_product(union_map umap2) const
+isl::checked::union_map union_map::domain_product(isl::checked::union_map umap2) const
 {
   auto res = isl_union_map_domain_product(copy(), umap2.release());
   return manage(res);
 }
 
-union_map union_map::eq_at(multi_union_pw_aff mupa) const
+isl::checked::union_map union_map::empty(isl::checked::ctx ctx)
+{
+  auto res = isl_union_map_empty_ctx(ctx.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::eq_at(isl::checked::multi_union_pw_aff mupa) const
 {
   auto res = isl_union_map_eq_at_multi_union_pw_aff(copy(), mupa.release());
   return manage(res);
 }
 
-union_map union_map::factor_domain() const
+boolean union_map::every_map(const std::function<boolean(isl::checked::map)> &test) const
+{
+  struct test_data {
+    std::function<boolean(isl::checked::map)> func;
+  } test_data = { test };
+  auto test_lambda = [](isl_map *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct test_data *>(arg_1);
+    auto ret = (data->func)(manage_copy(arg_0));
+    return ret.release();
+  };
+  auto res = isl_union_map_every_map(get(), test_lambda, &test_data);
+  return manage(res);
+}
+
+isl::checked::map union_map::extract_map(isl::checked::space space) const
+{
+  auto res = isl_union_map_extract_map(get(), space.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::factor_domain() const
 {
   auto res = isl_union_map_factor_domain(copy());
   return manage(res);
 }
 
-union_map union_map::factor_range() const
+isl::checked::union_map union_map::factor_range() const
 {
   auto res = isl_union_map_factor_range(copy());
   return manage(res);
 }
 
-union_map union_map::fixed_power(val exp) const
+isl::checked::union_map union_map::fixed_power(isl::checked::val exp) const
 {
   auto res = isl_union_map_fixed_power_val(copy(), exp.release());
   return manage(res);
 }
 
-stat union_map::foreach_map(const std::function<stat(map)> &fn) const
+isl::checked::union_map union_map::fixed_power(long exp) const
+{
+  return this->fixed_power(isl::checked::val(ctx(), exp));
+}
+
+stat union_map::foreach_map(const std::function<stat(isl::checked::map)> &fn) const
 {
   struct fn_data {
-    const std::function<stat(map)> *func;
-  } fn_data = { &fn };
+    std::function<stat(isl::checked::map)> func;
+  } fn_data = { fn };
   auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
     auto *data = static_cast<struct fn_data *>(arg_1);
-    stat ret = (*data->func)(manage(arg_0));
+    auto ret = (data->func)(manage(arg_0));
     return ret.release();
   };
   auto res = isl_union_map_foreach_map(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-union_map union_map::from(union_pw_multi_aff upma)
+isl::checked::union_map union_map::from(isl::checked::multi_union_pw_aff mupa)
 {
-  auto res = isl_union_map_from_union_pw_multi_aff(upma.release());
+  auto res = isl_union_map_from_multi_union_pw_aff(mupa.release());
   return manage(res);
 }
 
-union_map union_map::from(multi_union_pw_aff mupa)
+isl::checked::union_map union_map::from(isl::checked::union_pw_multi_aff upma)
 {
-  auto res = isl_union_map_from_multi_union_pw_aff(mupa.release());
+  auto res = isl_union_map_from_union_pw_multi_aff(upma.release());
   return manage(res);
 }
 
-union_map union_map::from_domain(union_set uset)
+isl::checked::union_map union_map::from_domain(isl::checked::union_set uset)
 {
   auto res = isl_union_map_from_domain(uset.release());
   return manage(res);
 }
 
-union_map union_map::from_domain_and_range(union_set domain, union_set range)
+isl::checked::union_map union_map::from_domain_and_range(isl::checked::union_set domain, isl::checked::union_set range)
 {
   auto res = isl_union_map_from_domain_and_range(domain.release(), range.release());
   return manage(res);
 }
 
-union_map union_map::from_range(union_set uset)
+isl::checked::union_map union_map::from_range(isl::checked::union_set uset)
+{
+  auto res = isl_union_map_from_range(uset.release());
+  return manage(res);
+}
+
+isl::checked::space union_map::space() const
+{
+  auto res = isl_union_map_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space union_map::get_space() const
+{
+  return space();
+}
+
+isl::checked::union_map union_map::gist(isl::checked::union_map context) const
+{
+  auto res = isl_union_map_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::gist_domain(isl::checked::union_set uset) const
+{
+  auto res = isl_union_map_gist_domain(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::gist_params(isl::checked::set set) const
+{
+  auto res = isl_union_map_gist_params(copy(), set.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::gist_range(isl::checked::union_set uset) const
+{
+  auto res = isl_union_map_gist_range(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::intersect(isl::checked::union_map umap2) const
+{
+  auto res = isl_union_map_intersect(copy(), umap2.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::intersect_domain(isl::checked::union_set uset) const
+{
+  auto res = isl_union_map_intersect_domain(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::intersect_params(isl::checked::set set) const
+{
+  auto res = isl_union_map_intersect_params(copy(), set.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::intersect_range(isl::checked::union_set uset) const
+{
+  auto res = isl_union_map_intersect_range(copy(), uset.release());
+  return manage(res);
+}
+
+boolean union_map::is_bijective() const
+{
+  auto res = isl_union_map_is_bijective(get());
+  return manage(res);
+}
+
+boolean union_map::is_disjoint(const isl::checked::union_map &umap2) const
+{
+  auto res = isl_union_map_is_disjoint(get(), umap2.get());
+  return manage(res);
+}
+
+boolean union_map::is_empty() const
+{
+  auto res = isl_union_map_is_empty(get());
+  return manage(res);
+}
+
+boolean union_map::is_equal(const isl::checked::union_map &umap2) const
+{
+  auto res = isl_union_map_is_equal(get(), umap2.get());
+  return manage(res);
+}
+
+boolean union_map::is_injective() const
+{
+  auto res = isl_union_map_is_injective(get());
+  return manage(res);
+}
+
+boolean union_map::is_single_valued() const
+{
+  auto res = isl_union_map_is_single_valued(get());
+  return manage(res);
+}
+
+boolean union_map::is_strict_subset(const isl::checked::union_map &umap2) const
+{
+  auto res = isl_union_map_is_strict_subset(get(), umap2.get());
+  return manage(res);
+}
+
+boolean union_map::is_subset(const isl::checked::union_map &umap2) const
+{
+  auto res = isl_union_map_is_subset(get(), umap2.get());
+  return manage(res);
+}
+
+boolean union_map::isa_map() const
+{
+  auto res = isl_union_map_isa_map(get());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::lexmax() const
+{
+  auto res = isl_union_map_lexmax(copy());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::lexmin() const
+{
+  auto res = isl_union_map_lexmin(copy());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::polyhedral_hull() const
+{
+  auto res = isl_union_map_polyhedral_hull(copy());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::preimage_domain(isl::checked::multi_aff ma) const
+{
+  auto res = isl_union_map_preimage_domain_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::preimage_domain(isl::checked::multi_pw_aff mpa) const
+{
+  auto res = isl_union_map_preimage_domain_multi_pw_aff(copy(), mpa.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::preimage_domain(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_union_map_preimage_domain_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::preimage_domain(isl::checked::union_pw_multi_aff upma) const
+{
+  auto res = isl_union_map_preimage_domain_union_pw_multi_aff(copy(), upma.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::preimage_range(isl::checked::multi_aff ma) const
+{
+  auto res = isl_union_map_preimage_range_multi_aff(copy(), ma.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::preimage_range(isl::checked::pw_multi_aff pma) const
+{
+  auto res = isl_union_map_preimage_range_pw_multi_aff(copy(), pma.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::preimage_range(isl::checked::union_pw_multi_aff upma) const
+{
+  auto res = isl_union_map_preimage_range_union_pw_multi_aff(copy(), upma.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::product(isl::checked::union_map umap2) const
+{
+  auto res = isl_union_map_product(copy(), umap2.release());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::project_out_all_params() const
+{
+  auto res = isl_union_map_project_out_all_params(copy());
+  return manage(res);
+}
+
+isl::checked::union_set union_map::range() const
+{
+  auto res = isl_union_map_range(copy());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::range_factor_domain() const
+{
+  auto res = isl_union_map_range_factor_domain(copy());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::range_factor_range() const
+{
+  auto res = isl_union_map_range_factor_range(copy());
+  return manage(res);
+}
+
+isl::checked::union_map union_map::range_map() const
 {
-  auto res = isl_union_map_from_range(uset.release());
+  auto res = isl_union_map_range_map(copy());
   return manage(res);
 }
 
-union_map union_map::gist(union_map context) const
+isl::checked::union_map union_map::range_product(isl::checked::union_map umap2) const
 {
-  auto res = isl_union_map_gist(copy(), context.release());
+  auto res = isl_union_map_range_product(copy(), umap2.release());
   return manage(res);
 }
 
-union_map union_map::gist_domain(union_set uset) const
+isl::checked::union_map union_map::range_reverse() const
 {
-  auto res = isl_union_map_gist_domain(copy(), uset.release());
+  auto res = isl_union_map_range_reverse(copy());
   return manage(res);
 }
 
-union_map union_map::gist_params(set set) const
+isl::checked::union_map union_map::reverse() const
 {
-  auto res = isl_union_map_gist_params(copy(), set.release());
+  auto res = isl_union_map_reverse(copy());
   return manage(res);
 }
 
-union_map union_map::gist_range(union_set uset) const
+isl::checked::union_map union_map::subtract(isl::checked::union_map umap2) const
 {
-  auto res = isl_union_map_gist_range(copy(), uset.release());
+  auto res = isl_union_map_subtract(copy(), umap2.release());
   return manage(res);
 }
 
-union_map union_map::intersect(union_map umap2) const
+isl::checked::union_map union_map::subtract_domain(isl::checked::union_set dom) const
 {
-  auto res = isl_union_map_intersect(copy(), umap2.release());
+  auto res = isl_union_map_subtract_domain(copy(), dom.release());
   return manage(res);
 }
 
-union_map union_map::intersect_domain(union_set uset) const
+isl::checked::union_map union_map::subtract_range(isl::checked::union_set dom) const
 {
-  auto res = isl_union_map_intersect_domain(copy(), uset.release());
+  auto res = isl_union_map_subtract_range(copy(), dom.release());
   return manage(res);
 }
 
-union_map union_map::intersect_params(set set) const
+isl::checked::union_map union_map::uncurry() const
 {
-  auto res = isl_union_map_intersect_params(copy(), set.release());
+  auto res = isl_union_map_uncurry(copy());
   return manage(res);
 }
 
-union_map union_map::intersect_range(union_set uset) const
+isl::checked::union_map union_map::unite(isl::checked::union_map umap2) const
 {
-  auto res = isl_union_map_intersect_range(copy(), uset.release());
+  auto res = isl_union_map_union(copy(), umap2.release());
   return manage(res);
 }
 
-boolean union_map::is_bijective() const
+isl::checked::union_map union_map::universe() const
 {
-  auto res = isl_union_map_is_bijective(get());
+  auto res = isl_union_map_universe(copy());
   return manage(res);
 }
 
-boolean union_map::is_empty() const
+isl::checked::union_set union_map::wrap() const
 {
-  auto res = isl_union_map_is_empty(get());
+  auto res = isl_union_map_wrap(copy());
   return manage(res);
 }
 
-boolean union_map::is_equal(const union_map &umap2) const
+isl::checked::union_map union_map::zip() const
 {
-  auto res = isl_union_map_is_equal(get(), umap2.get());
+  auto res = isl_union_map_zip(copy());
   return manage(res);
 }
 
-boolean union_map::is_injective() const
+inline std::ostream &operator<<(std::ostream &os, const union_map &obj)
 {
-  auto res = isl_union_map_is_injective(get());
-  return manage(res);
+  char *str = isl_union_map_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-boolean union_map::is_single_valued() const
+// implementations for isl::union_pw_aff
+union_pw_aff manage(__isl_take isl_union_pw_aff *ptr) {
+  return union_pw_aff(ptr);
+}
+union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr) {
+  ptr = isl_union_pw_aff_copy(ptr);
+  return union_pw_aff(ptr);
+}
+
+union_pw_aff::union_pw_aff()
+    : ptr(nullptr) {}
+
+union_pw_aff::union_pw_aff(const union_pw_aff &obj)
+    : ptr(nullptr)
 {
-  auto res = isl_union_map_is_single_valued(get());
-  return manage(res);
+  ptr = obj.copy();
 }
 
-boolean union_map::is_strict_subset(const union_map &umap2) const
+union_pw_aff::union_pw_aff(__isl_take isl_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+union_pw_aff::union_pw_aff(isl::checked::pw_aff pa)
 {
-  auto res = isl_union_map_is_strict_subset(get(), umap2.get());
-  return manage(res);
+  auto res = isl_union_pw_aff_from_pw_aff(pa.release());
+  ptr = res;
 }
 
-boolean union_map::is_subset(const union_map &umap2) const
+union_pw_aff::union_pw_aff(isl::checked::ctx ctx, const std::string &str)
 {
-  auto res = isl_union_map_is_subset(get(), umap2.get());
-  return manage(res);
+  auto res = isl_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  ptr = res;
+}
+
+union_pw_aff &union_pw_aff::operator=(union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_pw_aff::~union_pw_aff() {
+  if (ptr)
+    isl_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::copy() const & {
+  return isl_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_union_pw_aff *union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::release() {
+  isl_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
 }
 
-union_map union_map::lexmax() const
+bool union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx union_pw_aff::ctx() const {
+  return isl::checked::ctx(isl_union_pw_aff_get_ctx(ptr));
+}
+
+isl::checked::union_pw_aff union_pw_aff::add(isl::checked::union_pw_aff upa2) const
 {
-  auto res = isl_union_map_lexmax(copy());
+  auto res = isl_union_pw_aff_add(copy(), upa2.release());
   return manage(res);
 }
 
-union_map union_map::lexmin() const
+isl::checked::union_set union_pw_aff::bind(isl::checked::id id) const
 {
-  auto res = isl_union_map_lexmin(copy());
+  auto res = isl_union_pw_aff_bind_id(copy(), id.release());
   return manage(res);
 }
 
-union_map union_map::polyhedral_hull() const
+isl::checked::union_set union_pw_aff::bind(const std::string &id) const
 {
-  auto res = isl_union_map_polyhedral_hull(copy());
-  return manage(res);
+  return this->bind(isl::checked::id(ctx(), id));
 }
 
-union_map union_map::product(union_map umap2) const
+isl::checked::union_pw_aff union_pw_aff::coalesce() const
 {
-  auto res = isl_union_map_product(copy(), umap2.release());
+  auto res = isl_union_pw_aff_coalesce(copy());
   return manage(res);
 }
 
-union_map union_map::project_out_all_params() const
+isl::checked::union_set union_pw_aff::domain() const
 {
-  auto res = isl_union_map_project_out_all_params(copy());
+  auto res = isl_union_pw_aff_domain(copy());
   return manage(res);
 }
 
-union_set union_map::range() const
+isl::checked::space union_pw_aff::space() const
 {
-  auto res = isl_union_map_range(copy());
+  auto res = isl_union_pw_aff_get_space(get());
   return manage(res);
 }
 
-union_map union_map::range_factor_domain() const
+isl::checked::space union_pw_aff::get_space() const
 {
-  auto res = isl_union_map_range_factor_domain(copy());
-  return manage(res);
+  return space();
 }
 
-union_map union_map::range_factor_range() const
+isl::checked::union_pw_aff union_pw_aff::gist(isl::checked::union_set context) const
 {
-  auto res = isl_union_map_range_factor_range(copy());
+  auto res = isl_union_pw_aff_gist(copy(), context.release());
   return manage(res);
 }
 
-union_map union_map::range_map() const
+isl::checked::union_pw_aff union_pw_aff::intersect_domain(isl::checked::union_set uset) const
 {
-  auto res = isl_union_map_range_map(copy());
+  auto res = isl_union_pw_aff_intersect_domain(copy(), uset.release());
   return manage(res);
 }
 
-union_map union_map::range_product(union_map umap2) const
+isl::checked::union_pw_aff union_pw_aff::intersect_domain_wrapped_domain(isl::checked::union_set uset) const
 {
-  auto res = isl_union_map_range_product(copy(), umap2.release());
+  auto res = isl_union_pw_aff_intersect_domain_wrapped_domain(copy(), uset.release());
   return manage(res);
 }
 
-union_map union_map::reverse() const
+isl::checked::union_pw_aff union_pw_aff::intersect_domain_wrapped_range(isl::checked::union_set uset) const
 {
-  auto res = isl_union_map_reverse(copy());
+  auto res = isl_union_pw_aff_intersect_domain_wrapped_range(copy(), uset.release());
   return manage(res);
 }
 
-union_map union_map::subtract(union_map umap2) const
+isl::checked::union_pw_aff union_pw_aff::intersect_params(isl::checked::set set) const
 {
-  auto res = isl_union_map_subtract(copy(), umap2.release());
+  auto res = isl_union_pw_aff_intersect_params(copy(), set.release());
   return manage(res);
 }
 
-union_map union_map::subtract_domain(union_set dom) const
+isl::checked::union_pw_aff union_pw_aff::pullback(isl::checked::union_pw_multi_aff upma) const
 {
-  auto res = isl_union_map_subtract_domain(copy(), dom.release());
+  auto res = isl_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
   return manage(res);
 }
 
-union_map union_map::subtract_range(union_set dom) const
+isl::checked::union_pw_aff union_pw_aff::sub(isl::checked::union_pw_aff upa2) const
 {
-  auto res = isl_union_map_subtract_range(copy(), dom.release());
+  auto res = isl_union_pw_aff_sub(copy(), upa2.release());
   return manage(res);
 }
 
-union_map union_map::unite(union_map umap2) const
+isl::checked::union_pw_aff union_pw_aff::subtract_domain(isl::checked::union_set uset) const
 {
-  auto res = isl_union_map_union(copy(), umap2.release());
+  auto res = isl_union_pw_aff_subtract_domain(copy(), uset.release());
   return manage(res);
 }
 
-union_set union_map::wrap() const
+isl::checked::union_pw_aff union_pw_aff::union_add(isl::checked::union_pw_aff upa2) const
 {
-  auto res = isl_union_map_wrap(copy());
+  auto res = isl_union_pw_aff_union_add(copy(), upa2.release());
   return manage(res);
 }
 
-union_map union_map::zip() const
+inline std::ostream &operator<<(std::ostream &os, const union_pw_aff &obj)
 {
-  auto res = isl_union_map_zip(copy());
-  return manage(res);
+  char *str = isl_union_pw_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::union_pw_aff
-union_pw_aff manage(__isl_take isl_union_pw_aff *ptr) {
-  return union_pw_aff(ptr);
+// implementations for isl::union_pw_aff_list
+union_pw_aff_list manage(__isl_take isl_union_pw_aff_list *ptr) {
+  return union_pw_aff_list(ptr);
 }
-union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr) {
-  ptr = isl_union_pw_aff_copy(ptr);
-  return union_pw_aff(ptr);
+union_pw_aff_list manage_copy(__isl_keep isl_union_pw_aff_list *ptr) {
+  ptr = isl_union_pw_aff_list_copy(ptr);
+  return union_pw_aff_list(ptr);
 }
 
-union_pw_aff::union_pw_aff()
+union_pw_aff_list::union_pw_aff_list()
     : ptr(nullptr) {}
 
-union_pw_aff::union_pw_aff(const union_pw_aff &obj)
+union_pw_aff_list::union_pw_aff_list(const union_pw_aff_list &obj)
     : ptr(nullptr)
 {
   ptr = obj.copy();
 }
 
-union_pw_aff::union_pw_aff(__isl_take isl_union_pw_aff *ptr)
+union_pw_aff_list::union_pw_aff_list(__isl_take isl_union_pw_aff_list *ptr)
     : ptr(ptr) {}
 
-union_pw_aff::union_pw_aff(pw_aff pa)
+union_pw_aff_list::union_pw_aff_list(isl::checked::ctx ctx, int n)
 {
-  auto res = isl_union_pw_aff_from_pw_aff(pa.release());
+  auto res = isl_union_pw_aff_list_alloc(ctx.release(), n);
   ptr = res;
 }
-union_pw_aff::union_pw_aff(ctx ctx, const std::string &str)
+
+union_pw_aff_list::union_pw_aff_list(isl::checked::union_pw_aff el)
 {
-  auto res = isl_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  auto res = isl_union_pw_aff_list_from_union_pw_aff(el.release());
   ptr = res;
 }
 
-union_pw_aff &union_pw_aff::operator=(union_pw_aff obj) {
+union_pw_aff_list &union_pw_aff_list::operator=(union_pw_aff_list obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-union_pw_aff::~union_pw_aff() {
+union_pw_aff_list::~union_pw_aff_list() {
   if (ptr)
-    isl_union_pw_aff_free(ptr);
+    isl_union_pw_aff_list_free(ptr);
 }
 
-__isl_give isl_union_pw_aff *union_pw_aff::copy() const & {
-  return isl_union_pw_aff_copy(ptr);
+__isl_give isl_union_pw_aff_list *union_pw_aff_list::copy() const & {
+  return isl_union_pw_aff_list_copy(ptr);
 }
 
-__isl_keep isl_union_pw_aff *union_pw_aff::get() const {
+__isl_keep isl_union_pw_aff_list *union_pw_aff_list::get() const {
   return ptr;
 }
 
-__isl_give isl_union_pw_aff *union_pw_aff::release() {
-  isl_union_pw_aff *tmp = ptr;
+__isl_give isl_union_pw_aff_list *union_pw_aff_list::release() {
+  isl_union_pw_aff_list *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool union_pw_aff::is_null() const {
+bool union_pw_aff_list::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_pw_aff::get_ctx() const {
-  return ctx(isl_union_pw_aff_get_ctx(ptr));
+isl::checked::ctx union_pw_aff_list::ctx() const {
+  return isl::checked::ctx(isl_union_pw_aff_list_get_ctx(ptr));
 }
 
-union_pw_aff union_pw_aff::add(union_pw_aff upa2) const
+isl::checked::union_pw_aff_list union_pw_aff_list::add(isl::checked::union_pw_aff el) const
 {
-  auto res = isl_union_pw_aff_add(copy(), upa2.release());
+  auto res = isl_union_pw_aff_list_add(copy(), el.release());
   return manage(res);
 }
 
-union_pw_aff union_pw_aff::pullback(union_pw_multi_aff upma) const
+isl::checked::union_pw_aff_list union_pw_aff_list::clear() const
 {
-  auto res = isl_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  auto res = isl_union_pw_aff_list_clear(copy());
   return manage(res);
 }
 
-union_pw_aff union_pw_aff::union_add(union_pw_aff upa2) const
+isl::checked::union_pw_aff_list union_pw_aff_list::concat(isl::checked::union_pw_aff_list list2) const
 {
-  auto res = isl_union_pw_aff_union_add(copy(), upa2.release());
+  auto res = isl_union_pw_aff_list_concat(copy(), list2.release());
+  return manage(res);
+}
+
+stat union_pw_aff_list::foreach(const std::function<stat(isl::checked::union_pw_aff)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::union_pw_aff)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_union_pw_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_union_pw_aff_list_foreach(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::union_pw_aff union_pw_aff_list::at(int index) const
+{
+  auto res = isl_union_pw_aff_list_get_at(get(), index);
+  return manage(res);
+}
+
+isl::checked::union_pw_aff union_pw_aff_list::get_at(int index) const
+{
+  return at(index);
+}
+
+class size union_pw_aff_list::size() const
+{
+  auto res = isl_union_pw_aff_list_size(get());
   return manage(res);
 }
 
+inline std::ostream &operator<<(std::ostream &os, const union_pw_aff_list &obj)
+{
+  char *str = isl_union_pw_aff_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
 // implementations for isl::union_pw_multi_aff
 union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr) {
   return union_pw_multi_aff(ptr);
@@ -4243,19 +11574,21 @@ union_pw_multi_aff::union_pw_multi_aff(const union_pw_multi_aff &obj)
 union_pw_multi_aff::union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr)
     : ptr(ptr) {}
 
-union_pw_multi_aff::union_pw_multi_aff(pw_multi_aff pma)
+union_pw_multi_aff::union_pw_multi_aff(isl::checked::pw_multi_aff pma)
 {
   auto res = isl_union_pw_multi_aff_from_pw_multi_aff(pma.release());
   ptr = res;
 }
-union_pw_multi_aff::union_pw_multi_aff(ctx ctx, const std::string &str)
+
+union_pw_multi_aff::union_pw_multi_aff(isl::checked::union_pw_aff upa)
 {
-  auto res = isl_union_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  auto res = isl_union_pw_multi_aff_from_union_pw_aff(upa.release());
   ptr = res;
 }
-union_pw_multi_aff::union_pw_multi_aff(union_pw_aff upa)
+
+union_pw_multi_aff::union_pw_multi_aff(isl::checked::ctx ctx, const std::string &str)
 {
-  auto res = isl_union_pw_multi_aff_from_union_pw_aff(upa.release());
+  auto res = isl_union_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
   ptr = res;
 }
 
@@ -4287,34 +11620,147 @@ bool union_pw_multi_aff::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_pw_multi_aff::get_ctx() const {
-  return ctx(isl_union_pw_multi_aff_get_ctx(ptr));
+isl::checked::ctx union_pw_multi_aff::ctx() const {
+  return isl::checked::ctx(isl_union_pw_multi_aff_get_ctx(ptr));
 }
 
-union_pw_multi_aff union_pw_multi_aff::add(union_pw_multi_aff upma2) const
+isl::checked::union_pw_multi_aff union_pw_multi_aff::add(isl::checked::union_pw_multi_aff upma2) const
 {
   auto res = isl_union_pw_multi_aff_add(copy(), upma2.release());
   return manage(res);
 }
 
-union_pw_multi_aff union_pw_multi_aff::flat_range_product(union_pw_multi_aff upma2) const
+isl::checked::pw_multi_aff union_pw_multi_aff::as_pw_multi_aff() const
+{
+  auto res = isl_union_pw_multi_aff_as_pw_multi_aff(copy());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::coalesce() const
+{
+  auto res = isl_union_pw_multi_aff_coalesce(copy());
+  return manage(res);
+}
+
+isl::checked::union_set union_pw_multi_aff::domain() const
+{
+  auto res = isl_union_pw_multi_aff_domain(copy());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::empty(isl::checked::ctx ctx)
+{
+  auto res = isl_union_pw_multi_aff_empty_ctx(ctx.release());
+  return manage(res);
+}
+
+isl::checked::pw_multi_aff union_pw_multi_aff::extract_pw_multi_aff(isl::checked::space space) const
+{
+  auto res = isl_union_pw_multi_aff_extract_pw_multi_aff(get(), space.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::flat_range_product(isl::checked::union_pw_multi_aff upma2) const
 {
   auto res = isl_union_pw_multi_aff_flat_range_product(copy(), upma2.release());
   return manage(res);
 }
 
-union_pw_multi_aff union_pw_multi_aff::pullback(union_pw_multi_aff upma2) const
+isl::checked::space union_pw_multi_aff::space() const
+{
+  auto res = isl_union_pw_multi_aff_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space union_pw_multi_aff::get_space() const
+{
+  return space();
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::gist(isl::checked::union_set context) const
+{
+  auto res = isl_union_pw_multi_aff_gist(copy(), context.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::intersect_domain(isl::checked::union_set uset) const
+{
+  auto res = isl_union_pw_multi_aff_intersect_domain(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::intersect_domain_wrapped_domain(isl::checked::union_set uset) const
+{
+  auto res = isl_union_pw_multi_aff_intersect_domain_wrapped_domain(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::intersect_domain_wrapped_range(isl::checked::union_set uset) const
+{
+  auto res = isl_union_pw_multi_aff_intersect_domain_wrapped_range(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::intersect_params(isl::checked::set set) const
+{
+  auto res = isl_union_pw_multi_aff_intersect_params(copy(), set.release());
+  return manage(res);
+}
+
+boolean union_pw_multi_aff::isa_pw_multi_aff() const
+{
+  auto res = isl_union_pw_multi_aff_isa_pw_multi_aff(get());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::pullback(isl::checked::union_pw_multi_aff upma2) const
 {
   auto res = isl_union_pw_multi_aff_pullback_union_pw_multi_aff(copy(), upma2.release());
   return manage(res);
 }
 
-union_pw_multi_aff union_pw_multi_aff::union_add(union_pw_multi_aff upma2) const
+isl::checked::union_pw_multi_aff union_pw_multi_aff::range_factor_domain() const
+{
+  auto res = isl_union_pw_multi_aff_range_factor_domain(copy());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::range_factor_range() const
+{
+  auto res = isl_union_pw_multi_aff_range_factor_range(copy());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::sub(isl::checked::union_pw_multi_aff upma2) const
+{
+  auto res = isl_union_pw_multi_aff_sub(copy(), upma2.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::subtract_domain(isl::checked::union_set uset) const
+{
+  auto res = isl_union_pw_multi_aff_subtract_domain(copy(), uset.release());
+  return manage(res);
+}
+
+isl::checked::union_pw_multi_aff union_pw_multi_aff::union_add(isl::checked::union_pw_multi_aff upma2) const
 {
   auto res = isl_union_pw_multi_aff_union_add(copy(), upma2.release());
   return manage(res);
 }
 
+inline std::ostream &operator<<(std::ostream &os, const union_pw_multi_aff &obj)
+{
+  char *str = isl_union_pw_multi_aff_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
 // implementations for isl::union_set
 union_set manage(__isl_take isl_union_set *ptr) {
   return union_set(ptr);
@@ -4336,22 +11782,25 @@ union_set::union_set(const union_set &obj)
 union_set::union_set(__isl_take isl_union_set *ptr)
     : ptr(ptr) {}
 
-union_set::union_set(basic_set bset)
+union_set::union_set(isl::checked::basic_set bset)
 {
   auto res = isl_union_set_from_basic_set(bset.release());
   ptr = res;
 }
-union_set::union_set(set set)
+
+union_set::union_set(isl::checked::point pnt)
 {
-  auto res = isl_union_set_from_set(set.release());
+  auto res = isl_union_set_from_point(pnt.release());
   ptr = res;
 }
-union_set::union_set(point pnt)
+
+union_set::union_set(isl::checked::set set)
 {
-  auto res = isl_union_set_from_point(pnt.release());
+  auto res = isl_union_set_from_set(set.release());
   ptr = res;
 }
-union_set::union_set(ctx ctx, const std::string &str)
+
+union_set::union_set(isl::checked::ctx ctx, const std::string &str)
 {
   auto res = isl_union_set_read_from_str(ctx.release(), str.c_str());
   ptr = res;
@@ -4385,182 +11834,375 @@ bool union_set::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_set::get_ctx() const {
-  return ctx(isl_union_set_get_ctx(ptr));
+isl::checked::ctx union_set::ctx() const {
+  return isl::checked::ctx(isl_union_set_get_ctx(ptr));
 }
 
-union_set union_set::affine_hull() const
+isl::checked::union_set union_set::affine_hull() const
 {
   auto res = isl_union_set_affine_hull(copy());
   return manage(res);
 }
 
-union_set union_set::apply(union_map umap) const
+isl::checked::union_set union_set::apply(isl::checked::union_map umap) const
+{
+  auto res = isl_union_set_apply(copy(), umap.release());
+  return manage(res);
+}
+
+isl::checked::union_set union_set::coalesce() const
+{
+  auto res = isl_union_set_coalesce(copy());
+  return manage(res);
+}
+
+isl::checked::union_set union_set::compute_divs() const
+{
+  auto res = isl_union_set_compute_divs(copy());
+  return manage(res);
+}
+
+isl::checked::union_set union_set::detect_equalities() const
 {
-  auto res = isl_union_set_apply(copy(), umap.release());
+  auto res = isl_union_set_detect_equalities(copy());
   return manage(res);
 }
 
-union_set union_set::coalesce() const
+isl::checked::union_set union_set::empty(isl::checked::ctx ctx)
 {
-  auto res = isl_union_set_coalesce(copy());
+  auto res = isl_union_set_empty_ctx(ctx.release());
   return manage(res);
 }
 
-union_set union_set::compute_divs() const
+boolean union_set::every_set(const std::function<boolean(isl::checked::set)> &test) const
 {
-  auto res = isl_union_set_compute_divs(copy());
+  struct test_data {
+    std::function<boolean(isl::checked::set)> func;
+  } test_data = { test };
+  auto test_lambda = [](isl_set *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct test_data *>(arg_1);
+    auto ret = (data->func)(manage_copy(arg_0));
+    return ret.release();
+  };
+  auto res = isl_union_set_every_set(get(), test_lambda, &test_data);
   return manage(res);
 }
 
-union_set union_set::detect_equalities() const
+isl::checked::set union_set::extract_set(isl::checked::space space) const
 {
-  auto res = isl_union_set_detect_equalities(copy());
+  auto res = isl_union_set_extract_set(get(), space.release());
   return manage(res);
 }
 
-stat union_set::foreach_point(const std::function<stat(point)> &fn) const
+stat union_set::foreach_point(const std::function<stat(isl::checked::point)> &fn) const
 {
   struct fn_data {
-    const std::function<stat(point)> *func;
-  } fn_data = { &fn };
+    std::function<stat(isl::checked::point)> func;
+  } fn_data = { fn };
   auto fn_lambda = [](isl_point *arg_0, void *arg_1) -> isl_stat {
     auto *data = static_cast<struct fn_data *>(arg_1);
-    stat ret = (*data->func)(manage(arg_0));
+    auto ret = (data->func)(manage(arg_0));
     return ret.release();
   };
   auto res = isl_union_set_foreach_point(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-stat union_set::foreach_set(const std::function<stat(set)> &fn) const
+stat union_set::foreach_set(const std::function<stat(isl::checked::set)> &fn) const
 {
   struct fn_data {
-    const std::function<stat(set)> *func;
-  } fn_data = { &fn };
+    std::function<stat(isl::checked::set)> func;
+  } fn_data = { fn };
   auto fn_lambda = [](isl_set *arg_0, void *arg_1) -> isl_stat {
     auto *data = static_cast<struct fn_data *>(arg_1);
-    stat ret = (*data->func)(manage(arg_0));
+    auto ret = (data->func)(manage(arg_0));
     return ret.release();
   };
   auto res = isl_union_set_foreach_set(get(), fn_lambda, &fn_data);
   return manage(res);
 }
 
-union_set union_set::gist(union_set context) const
+isl::checked::space union_set::space() const
+{
+  auto res = isl_union_set_get_space(get());
+  return manage(res);
+}
+
+isl::checked::space union_set::get_space() const
+{
+  return space();
+}
+
+isl::checked::union_set union_set::gist(isl::checked::union_set context) const
 {
   auto res = isl_union_set_gist(copy(), context.release());
   return manage(res);
 }
 
-union_set union_set::gist_params(set set) const
+isl::checked::union_set union_set::gist_params(isl::checked::set set) const
 {
   auto res = isl_union_set_gist_params(copy(), set.release());
   return manage(res);
 }
 
-union_map union_set::identity() const
+isl::checked::union_map union_set::identity() const
 {
   auto res = isl_union_set_identity(copy());
   return manage(res);
 }
 
-union_set union_set::intersect(union_set uset2) const
+isl::checked::union_set union_set::intersect(isl::checked::union_set uset2) const
 {
   auto res = isl_union_set_intersect(copy(), uset2.release());
   return manage(res);
 }
 
-union_set union_set::intersect_params(set set) const
+isl::checked::union_set union_set::intersect_params(isl::checked::set set) const
 {
   auto res = isl_union_set_intersect_params(copy(), set.release());
   return manage(res);
 }
 
+boolean union_set::is_disjoint(const isl::checked::union_set &uset2) const
+{
+  auto res = isl_union_set_is_disjoint(get(), uset2.get());
+  return manage(res);
+}
+
 boolean union_set::is_empty() const
 {
   auto res = isl_union_set_is_empty(get());
   return manage(res);
 }
 
-boolean union_set::is_equal(const union_set &uset2) const
+boolean union_set::is_equal(const isl::checked::union_set &uset2) const
 {
   auto res = isl_union_set_is_equal(get(), uset2.get());
   return manage(res);
 }
 
-boolean union_set::is_strict_subset(const union_set &uset2) const
+boolean union_set::is_strict_subset(const isl::checked::union_set &uset2) const
 {
   auto res = isl_union_set_is_strict_subset(get(), uset2.get());
   return manage(res);
 }
 
-boolean union_set::is_subset(const union_set &uset2) const
+boolean union_set::is_subset(const isl::checked::union_set &uset2) const
 {
   auto res = isl_union_set_is_subset(get(), uset2.get());
   return manage(res);
 }
 
-union_set union_set::lexmax() const
+boolean union_set::isa_set() const
+{
+  auto res = isl_union_set_isa_set(get());
+  return manage(res);
+}
+
+isl::checked::union_set union_set::lexmax() const
 {
   auto res = isl_union_set_lexmax(copy());
   return manage(res);
 }
 
-union_set union_set::lexmin() const
+isl::checked::union_set union_set::lexmin() const
 {
   auto res = isl_union_set_lexmin(copy());
   return manage(res);
 }
 
-union_set union_set::polyhedral_hull() const
+isl::checked::union_set union_set::polyhedral_hull() const
 {
   auto res = isl_union_set_polyhedral_hull(copy());
   return manage(res);
 }
 
-union_set union_set::preimage(multi_aff ma) const
+isl::checked::union_set union_set::preimage(isl::checked::multi_aff ma) const
 {
   auto res = isl_union_set_preimage_multi_aff(copy(), ma.release());
   return manage(res);
 }
 
-union_set union_set::preimage(pw_multi_aff pma) const
+isl::checked::union_set union_set::preimage(isl::checked::pw_multi_aff pma) const
 {
   auto res = isl_union_set_preimage_pw_multi_aff(copy(), pma.release());
   return manage(res);
 }
 
-union_set union_set::preimage(union_pw_multi_aff upma) const
+isl::checked::union_set union_set::preimage(isl::checked::union_pw_multi_aff upma) const
 {
   auto res = isl_union_set_preimage_union_pw_multi_aff(copy(), upma.release());
   return manage(res);
 }
 
-point union_set::sample_point() const
+isl::checked::point union_set::sample_point() const
 {
   auto res = isl_union_set_sample_point(copy());
   return manage(res);
 }
 
-union_set union_set::subtract(union_set uset2) const
+isl::checked::union_set union_set::subtract(isl::checked::union_set uset2) const
 {
   auto res = isl_union_set_subtract(copy(), uset2.release());
   return manage(res);
 }
 
-union_set union_set::unite(union_set uset2) const
+isl::checked::union_set union_set::unite(isl::checked::union_set uset2) const
 {
   auto res = isl_union_set_union(copy(), uset2.release());
   return manage(res);
 }
 
-union_map union_set::unwrap() const
+isl::checked::union_set union_set::universe() const
+{
+  auto res = isl_union_set_universe(copy());
+  return manage(res);
+}
+
+isl::checked::union_map union_set::unwrap() const
 {
   auto res = isl_union_set_unwrap(copy());
   return manage(res);
 }
 
+inline std::ostream &operator<<(std::ostream &os, const union_set &obj)
+{
+  char *str = isl_union_set_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::union_set_list
+union_set_list manage(__isl_take isl_union_set_list *ptr) {
+  return union_set_list(ptr);
+}
+union_set_list manage_copy(__isl_keep isl_union_set_list *ptr) {
+  ptr = isl_union_set_list_copy(ptr);
+  return union_set_list(ptr);
+}
+
+union_set_list::union_set_list()
+    : ptr(nullptr) {}
+
+union_set_list::union_set_list(const union_set_list &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+union_set_list::union_set_list(__isl_take isl_union_set_list *ptr)
+    : ptr(ptr) {}
+
+union_set_list::union_set_list(isl::checked::ctx ctx, int n)
+{
+  auto res = isl_union_set_list_alloc(ctx.release(), n);
+  ptr = res;
+}
+
+union_set_list::union_set_list(isl::checked::union_set el)
+{
+  auto res = isl_union_set_list_from_union_set(el.release());
+  ptr = res;
+}
+
+union_set_list &union_set_list::operator=(union_set_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_set_list::~union_set_list() {
+  if (ptr)
+    isl_union_set_list_free(ptr);
+}
+
+__isl_give isl_union_set_list *union_set_list::copy() const & {
+  return isl_union_set_list_copy(ptr);
+}
+
+__isl_keep isl_union_set_list *union_set_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_set_list *union_set_list::release() {
+  isl_union_set_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_set_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx union_set_list::ctx() const {
+  return isl::checked::ctx(isl_union_set_list_get_ctx(ptr));
+}
+
+isl::checked::union_set_list union_set_list::add(isl::checked::union_set el) const
+{
+  auto res = isl_union_set_list_add(copy(), el.release());
+  return manage(res);
+}
+
+isl::checked::union_set_list union_set_list::clear() const
+{
+  auto res = isl_union_set_list_clear(copy());
+  return manage(res);
+}
+
+isl::checked::union_set_list union_set_list::concat(isl::checked::union_set_list list2) const
+{
+  auto res = isl_union_set_list_concat(copy(), list2.release());
+  return manage(res);
+}
+
+stat union_set_list::foreach(const std::function<stat(isl::checked::union_set)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::union_set)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_union_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_union_set_list_foreach(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::union_set union_set_list::at(int index) const
+{
+  auto res = isl_union_set_list_get_at(get(), index);
+  return manage(res);
+}
+
+isl::checked::union_set union_set_list::get_at(int index) const
+{
+  return at(index);
+}
+
+class size union_set_list::size() const
+{
+  auto res = isl_union_set_list_size(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const union_set_list &obj)
+{
+  char *str = isl_union_set_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
 // implementations for isl::val
 val manage(__isl_take isl_val *ptr) {
   return val(ptr);
@@ -4582,14 +12224,15 @@ val::val(const val &obj)
 val::val(__isl_take isl_val *ptr)
     : ptr(ptr) {}
 
-val::val(ctx ctx, const std::string &str)
+val::val(isl::checked::ctx ctx, long i)
 {
-  auto res = isl_val_read_from_str(ctx.release(), str.c_str());
+  auto res = isl_val_int_from_si(ctx.release(), i);
   ptr = res;
 }
-val::val(ctx ctx, long i)
+
+val::val(isl::checked::ctx ctx, const std::string &str)
 {
-  auto res = isl_val_int_from_si(ctx.release(), i);
+  auto res = isl_val_read_from_str(ctx.release(), str.c_str());
   ptr = res;
 }
 
@@ -4621,29 +12264,39 @@ bool val::is_null() const {
   return ptr == nullptr;
 }
 
-ctx val::get_ctx() const {
-  return ctx(isl_val_get_ctx(ptr));
+isl::checked::ctx val::ctx() const {
+  return isl::checked::ctx(isl_val_get_ctx(ptr));
 }
 
-val val::abs() const
+isl::checked::val val::abs() const
 {
   auto res = isl_val_abs(copy());
   return manage(res);
 }
 
-boolean val::abs_eq(const val &v2) const
+boolean val::abs_eq(const isl::checked::val &v2) const
 {
   auto res = isl_val_abs_eq(get(), v2.get());
   return manage(res);
 }
 
-val val::add(val v2) const
+boolean val::abs_eq(long v2) const
+{
+  return this->abs_eq(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::add(isl::checked::val v2) const
 {
   auto res = isl_val_add(copy(), v2.release());
   return manage(res);
 }
 
-val val::ceil() const
+isl::checked::val val::add(long v2) const
+{
+  return this->add(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::ceil() const
 {
   auto res = isl_val_ceil(copy());
   return manage(res);
@@ -4655,60 +12308,112 @@ int val::cmp_si(long i) const
   return res;
 }
 
-val val::div(val v2) const
+isl::checked::val val::div(isl::checked::val v2) const
 {
   auto res = isl_val_div(copy(), v2.release());
   return manage(res);
 }
 
-boolean val::eq(const val &v2) const
+isl::checked::val val::div(long v2) const
+{
+  return this->div(isl::checked::val(ctx(), v2));
+}
+
+boolean val::eq(const isl::checked::val &v2) const
 {
   auto res = isl_val_eq(get(), v2.get());
   return manage(res);
 }
 
-val val::floor() const
+boolean val::eq(long v2) const
+{
+  return this->eq(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::floor() const
 {
   auto res = isl_val_floor(copy());
   return manage(res);
 }
 
-val val::gcd(val v2) const
+isl::checked::val val::gcd(isl::checked::val v2) const
 {
   auto res = isl_val_gcd(copy(), v2.release());
   return manage(res);
 }
 
-boolean val::ge(const val &v2) const
+isl::checked::val val::gcd(long v2) const
+{
+  return this->gcd(isl::checked::val(ctx(), v2));
+}
+
+boolean val::ge(const isl::checked::val &v2) const
 {
   auto res = isl_val_ge(get(), v2.get());
   return manage(res);
 }
 
-boolean val::gt(const val &v2) const
+boolean val::ge(long v2) const
+{
+  return this->ge(isl::checked::val(ctx(), v2));
+}
+
+long val::den_si() const
+{
+  auto res = isl_val_get_den_si(get());
+  return res;
+}
+
+long val::get_den_si() const
+{
+  return den_si();
+}
+
+long val::num_si() const
+{
+  auto res = isl_val_get_num_si(get());
+  return res;
+}
+
+long val::get_num_si() const
+{
+  return num_si();
+}
+
+boolean val::gt(const isl::checked::val &v2) const
 {
   auto res = isl_val_gt(get(), v2.get());
   return manage(res);
 }
 
-val val::infty(ctx ctx)
+boolean val::gt(long v2) const
+{
+  return this->gt(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::infty(isl::checked::ctx ctx)
 {
   auto res = isl_val_infty(ctx.release());
   return manage(res);
 }
 
-val val::inv() const
+isl::checked::val val::inv() const
 {
   auto res = isl_val_inv(copy());
   return manage(res);
 }
 
-boolean val::is_divisible_by(const val &v2) const
+boolean val::is_divisible_by(const isl::checked::val &v2) const
 {
   auto res = isl_val_is_divisible_by(get(), v2.get());
   return manage(res);
 }
 
+boolean val::is_divisible_by(long v2) const
+{
+  return this->is_divisible_by(isl::checked::val(ctx(), v2));
+}
+
 boolean val::is_infty() const
 {
   auto res = isl_val_is_infty(get());
@@ -4781,79 +12486,114 @@ boolean val::is_zero() const
   return manage(res);
 }
 
-boolean val::le(const val &v2) const
+boolean val::le(const isl::checked::val &v2) const
 {
   auto res = isl_val_le(get(), v2.get());
   return manage(res);
 }
 
-boolean val::lt(const val &v2) const
+boolean val::le(long v2) const
+{
+  return this->le(isl::checked::val(ctx(), v2));
+}
+
+boolean val::lt(const isl::checked::val &v2) const
 {
   auto res = isl_val_lt(get(), v2.get());
   return manage(res);
 }
 
-val val::max(val v2) const
+boolean val::lt(long v2) const
+{
+  return this->lt(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::max(isl::checked::val v2) const
 {
   auto res = isl_val_max(copy(), v2.release());
   return manage(res);
 }
 
-val val::min(val v2) const
+isl::checked::val val::max(long v2) const
+{
+  return this->max(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::min(isl::checked::val v2) const
 {
   auto res = isl_val_min(copy(), v2.release());
   return manage(res);
 }
 
-val val::mod(val v2) const
+isl::checked::val val::min(long v2) const
+{
+  return this->min(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::mod(isl::checked::val v2) const
 {
   auto res = isl_val_mod(copy(), v2.release());
   return manage(res);
 }
 
-val val::mul(val v2) const
+isl::checked::val val::mod(long v2) const
+{
+  return this->mod(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::mul(isl::checked::val v2) const
 {
   auto res = isl_val_mul(copy(), v2.release());
   return manage(res);
 }
 
-val val::nan(ctx ctx)
+isl::checked::val val::mul(long v2) const
+{
+  return this->mul(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::nan(isl::checked::ctx ctx)
 {
   auto res = isl_val_nan(ctx.release());
   return manage(res);
 }
 
-boolean val::ne(const val &v2) const
+boolean val::ne(const isl::checked::val &v2) const
 {
   auto res = isl_val_ne(get(), v2.get());
   return manage(res);
 }
 
-val val::neg() const
+boolean val::ne(long v2) const
+{
+  return this->ne(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::neg() const
 {
   auto res = isl_val_neg(copy());
   return manage(res);
 }
 
-val val::neginfty(ctx ctx)
+isl::checked::val val::neginfty(isl::checked::ctx ctx)
 {
   auto res = isl_val_neginfty(ctx.release());
   return manage(res);
 }
 
-val val::negone(ctx ctx)
+isl::checked::val val::negone(isl::checked::ctx ctx)
 {
   auto res = isl_val_negone(ctx.release());
   return manage(res);
 }
 
-val val::one(ctx ctx)
+isl::checked::val val::one(isl::checked::ctx ctx)
 {
   auto res = isl_val_one(ctx.release());
   return manage(res);
 }
 
-val val::pow2() const
+isl::checked::val val::pow2() const
 {
   auto res = isl_val_pow2(copy());
   return manage(res);
@@ -4865,23 +12605,171 @@ int val::sgn() const
   return res;
 }
 
-val val::sub(val v2) const
+isl::checked::val val::sub(isl::checked::val v2) const
 {
   auto res = isl_val_sub(copy(), v2.release());
   return manage(res);
 }
 
-val val::trunc() const
+isl::checked::val val::sub(long v2) const
+{
+  return this->sub(isl::checked::val(ctx(), v2));
+}
+
+isl::checked::val val::trunc() const
 {
   auto res = isl_val_trunc(copy());
   return manage(res);
 }
 
-val val::zero(ctx ctx)
+isl::checked::val val::zero(isl::checked::ctx ctx)
 {
   auto res = isl_val_zero(ctx.release());
   return manage(res);
 }
+
+inline std::ostream &operator<<(std::ostream &os, const val &obj)
+{
+  char *str = isl_val_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::val_list
+val_list manage(__isl_take isl_val_list *ptr) {
+  return val_list(ptr);
+}
+val_list manage_copy(__isl_keep isl_val_list *ptr) {
+  ptr = isl_val_list_copy(ptr);
+  return val_list(ptr);
+}
+
+val_list::val_list()
+    : ptr(nullptr) {}
+
+val_list::val_list(const val_list &obj)
+    : ptr(nullptr)
+{
+  ptr = obj.copy();
+}
+
+val_list::val_list(__isl_take isl_val_list *ptr)
+    : ptr(ptr) {}
+
+val_list::val_list(isl::checked::ctx ctx, int n)
+{
+  auto res = isl_val_list_alloc(ctx.release(), n);
+  ptr = res;
+}
+
+val_list::val_list(isl::checked::val el)
+{
+  auto res = isl_val_list_from_val(el.release());
+  ptr = res;
+}
+
+val_list &val_list::operator=(val_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+val_list::~val_list() {
+  if (ptr)
+    isl_val_list_free(ptr);
+}
+
+__isl_give isl_val_list *val_list::copy() const & {
+  return isl_val_list_copy(ptr);
+}
+
+__isl_keep isl_val_list *val_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_val_list *val_list::release() {
+  isl_val_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool val_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::checked::ctx val_list::ctx() const {
+  return isl::checked::ctx(isl_val_list_get_ctx(ptr));
+}
+
+isl::checked::val_list val_list::add(isl::checked::val el) const
+{
+  auto res = isl_val_list_add(copy(), el.release());
+  return manage(res);
+}
+
+isl::checked::val_list val_list::add(long el) const
+{
+  return this->add(isl::checked::val(ctx(), el));
+}
+
+isl::checked::val_list val_list::clear() const
+{
+  auto res = isl_val_list_clear(copy());
+  return manage(res);
+}
+
+isl::checked::val_list val_list::concat(isl::checked::val_list list2) const
+{
+  auto res = isl_val_list_concat(copy(), list2.release());
+  return manage(res);
+}
+
+stat val_list::foreach(const std::function<stat(isl::checked::val)> &fn) const
+{
+  struct fn_data {
+    std::function<stat(isl::checked::val)> func;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_val *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    auto ret = (data->func)(manage(arg_0));
+    return ret.release();
+  };
+  auto res = isl_val_list_foreach(get(), fn_lambda, &fn_data);
+  return manage(res);
+}
+
+isl::checked::val val_list::at(int index) const
+{
+  auto res = isl_val_list_get_at(get(), index);
+  return manage(res);
+}
+
+isl::checked::val val_list::get_at(int index) const
+{
+  return at(index);
+}
+
+class size val_list::size() const
+{
+  auto res = isl_val_list_size(get());
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const val_list &obj)
+{
+  char *str = isl_val_list_to_str(obj.get());
+  if (!str) {
+    os.setstate(std::ios_base::badbit);
+    return os;
+  }
+  os << str;
+  free(str);
+  return os;
+}
 } // namespace checked
 } // namespace isl
 

diff  --git a/polly/lib/External/isl/include/isl/cpp.h b/polly/lib/External/isl/include/isl/cpp.h
index de0da10c2259..41af093a1c11 100644
--- a/polly/lib/External/isl/include/isl/cpp.h
+++ b/polly/lib/External/isl/include/isl/cpp.h
@@ -8,6 +8,8 @@
 #ifndef ISL_CPP
 #define ISL_CPP
 
+#include <isl/id.h>
+#include <isl/space.h>
 #include <isl/val.h>
 #include <isl/aff.h>
 #include <isl/set.h>
@@ -19,22 +21,26 @@
 #include <isl/schedule.h>
 #include <isl/schedule_node.h>
 #include <isl/ast_build.h>
+#include <isl/fixed_box.h>
 
 #include <isl/ctx.h>
 #include <isl/options.h>
 
 #include <functional>
 #include <memory>
+#include <ostream>
 #include <stdexcept>
 #include <string>
+#include <type_traits>
 
 /* ISL_USE_EXCEPTIONS should be defined to 1 if exceptions are available.
  * gcc and clang define __cpp_exceptions; MSVC and xlC define _CPPUNWIND.
+ * Older versions of gcc (e.g., 4.9) only define __EXCEPTIONS.
  * If exceptions are not available, any error condition will result
  * in an abort.
  */
 #ifndef ISL_USE_EXCEPTIONS
-#if defined(__cpp_exceptions) || defined(_CPPUNWIND)
+#if defined(__cpp_exceptions) || defined(_CPPUNWIND) || defined(__EXCEPTIONS)
 #define ISL_USE_EXCEPTIONS	1
 #else
 #define ISL_USE_EXCEPTIONS	0
@@ -101,10 +107,10 @@ class exception : public std::exception {
 	 * will be included in the exception thrown from inside the bindings.
 	 */
 	static constexpr auto on_error = ISL_ON_ERROR_CONTINUE;
-	/* Wrapper for throwing an exception on NULL input.
+	/* Wrapper for throwing an exception with the given message.
 	 */
-	static void throw_NULL_input(const char *file, int line) {
-		throw_error(isl_error_invalid, "NULL input", file, line);
+	static void throw_invalid(const char *msg, const char *file, int line) {
+		throw_error(isl_error_invalid, msg, file, line);
 	}
 	static inline void throw_last_error(ctx ctx);
 };
@@ -225,11 +231,11 @@ class exception {
 	 * In the case exceptions are not available, isl should abort.
 	 */
 	static constexpr auto on_error = ISL_ON_ERROR_ABORT;
-	/* Wrapper for throwing an exception on NULL input.
+	/* Wrapper for throwing an exception with the given message.
 	 * In the case exceptions are not available, print an error and abort.
 	 */
-	static void throw_NULL_input(const char *file, int line) {
-		fprintf(stderr, "%s:%d: NULL input\n", file, line);
+	static void throw_invalid(const char *msg, const char *file, int line) {
+		fprintf(stderr, "%s:%d: %s\n", file, line, msg);
 		abort();
 	}
 	/* Throw an exception corresponding to the last
@@ -267,30 +273,87 @@ namespace isl {
 
 // forward declarations
 class aff;
+class aff_list;
 class ast_build;
 class ast_expr;
+class ast_expr_id;
+class ast_expr_int;
+class ast_expr_op;
+class ast_expr_op_access;
+class ast_expr_op_add;
+class ast_expr_op_address_of;
+class ast_expr_op_and;
+class ast_expr_op_and_then;
+class ast_expr_op_call;
+class ast_expr_op_cond;
+class ast_expr_op_div;
+class ast_expr_op_eq;
+class ast_expr_op_fdiv_q;
+class ast_expr_op_ge;
+class ast_expr_op_gt;
+class ast_expr_op_le;
+class ast_expr_op_lt;
+class ast_expr_op_max;
+class ast_expr_op_member;
+class ast_expr_op_min;
+class ast_expr_op_minus;
+class ast_expr_op_mul;
+class ast_expr_op_or;
+class ast_expr_op_or_else;
+class ast_expr_op_pdiv_q;
+class ast_expr_op_pdiv_r;
+class ast_expr_op_select;
+class ast_expr_op_sub;
+class ast_expr_op_zdiv_r;
 class ast_node;
+class ast_node_block;
+class ast_node_for;
+class ast_node_if;
+class ast_node_list;
+class ast_node_mark;
+class ast_node_user;
 class basic_map;
 class basic_set;
+class fixed_box;
+class id;
+class id_list;
 class map;
 class multi_aff;
+class multi_id;
 class multi_pw_aff;
 class multi_union_pw_aff;
 class multi_val;
 class point;
 class pw_aff;
+class pw_aff_list;
 class pw_multi_aff;
+class pw_multi_aff_list;
 class schedule;
 class schedule_constraints;
 class schedule_node;
+class schedule_node_band;
+class schedule_node_context;
+class schedule_node_domain;
+class schedule_node_expansion;
+class schedule_node_extension;
+class schedule_node_filter;
+class schedule_node_guard;
+class schedule_node_leaf;
+class schedule_node_mark;
+class schedule_node_sequence;
+class schedule_node_set;
 class set;
+class space;
 class union_access_info;
 class union_flow;
 class union_map;
 class union_pw_aff;
+class union_pw_aff_list;
 class union_pw_multi_aff;
 class union_set;
+class union_set_list;
 class val;
+class val_list;
 
 // declarations for isl::aff
 inline aff manage(__isl_take isl_aff *ptr);
@@ -300,6 +363,7 @@ class aff {
   friend inline aff manage(__isl_take isl_aff *ptr);
   friend inline aff manage_copy(__isl_keep isl_aff *ptr);
 
+protected:
   isl_aff *ptr = nullptr;
 
   inline explicit aff(__isl_take isl_aff *ptr);
@@ -307,7 +371,7 @@ class aff {
 public:
   inline /* implicit */ aff();
   inline /* implicit */ aff(const aff &obj);
-  inline explicit aff(ctx ctx, const std::string &str);
+  inline explicit aff(isl::ctx ctx, const std::string &str);
   inline aff &operator=(aff obj);
   inline ~aff();
   inline __isl_give isl_aff *copy() const &;
@@ -315,25 +379,71 @@ class aff {
   inline __isl_keep isl_aff *get() const;
   inline __isl_give isl_aff *release();
   inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline aff add(aff aff2) const;
-  inline aff ceil() const;
-  inline aff div(aff aff2) const;
-  inline set eq_set(aff aff2) const;
-  inline aff floor() const;
-  inline set ge_set(aff aff2) const;
-  inline set gt_set(aff aff2) const;
-  inline set le_set(aff aff2) const;
-  inline set lt_set(aff aff2) const;
-  inline aff mod(val mod) const;
-  inline aff mul(aff aff2) const;
-  inline set ne_set(aff aff2) const;
-  inline aff neg() const;
-  inline aff pullback(multi_aff ma) const;
-  inline aff scale(val v) const;
-  inline aff scale_down(val v) const;
-  inline aff sub(aff aff2) const;
+  inline isl::ctx ctx() const;
+
+  inline isl::aff add(isl::aff aff2) const;
+  inline isl::aff add_constant(isl::val v) const;
+  inline isl::aff add_constant(long v) const;
+  inline isl::basic_set bind(isl::id id) const;
+  inline isl::basic_set bind(const std::string &id) const;
+  inline isl::aff ceil() const;
+  inline isl::aff div(isl::aff aff2) const;
+  inline isl::set eq_set(isl::aff aff2) const;
+  inline isl::val eval(isl::point pnt) const;
+  inline isl::aff floor() const;
+  inline isl::set ge_set(isl::aff aff2) const;
+  inline isl::aff gist(isl::set context) const;
+  inline isl::set gt_set(isl::aff aff2) const;
+  inline isl::set le_set(isl::aff aff2) const;
+  inline isl::set lt_set(isl::aff aff2) const;
+  inline isl::aff mod(isl::val mod) const;
+  inline isl::aff mod(long mod) const;
+  inline isl::aff mul(isl::aff aff2) const;
+  inline isl::set ne_set(isl::aff aff2) const;
+  inline isl::aff neg() const;
+  inline isl::aff pullback(isl::multi_aff ma) const;
+  inline isl::aff scale(isl::val v) const;
+  inline isl::aff scale(long v) const;
+  inline isl::aff scale_down(isl::val v) const;
+  inline isl::aff scale_down(long v) const;
+  inline isl::aff sub(isl::aff aff2) const;
+  inline isl::aff unbind_params_insert_domain(isl::multi_id domain) const;
+};
+
+// declarations for isl::aff_list
+inline aff_list manage(__isl_take isl_aff_list *ptr);
+inline aff_list manage_copy(__isl_keep isl_aff_list *ptr);
+
+class aff_list {
+  friend inline aff_list manage(__isl_take isl_aff_list *ptr);
+  friend inline aff_list manage_copy(__isl_keep isl_aff_list *ptr);
+
+protected:
+  isl_aff_list *ptr = nullptr;
+
+  inline explicit aff_list(__isl_take isl_aff_list *ptr);
+
+public:
+  inline /* implicit */ aff_list();
+  inline /* implicit */ aff_list(const aff_list &obj);
+  inline explicit aff_list(isl::ctx ctx, int n);
+  inline explicit aff_list(isl::aff el);
+  inline aff_list &operator=(aff_list obj);
+  inline ~aff_list();
+  inline __isl_give isl_aff_list *copy() const &;
+  inline __isl_give isl_aff_list *copy() && = delete;
+  inline __isl_keep isl_aff_list *get() const;
+  inline __isl_give isl_aff_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::aff_list add(isl::aff el) const;
+  inline isl::aff_list clear() const;
+  inline isl::aff_list concat(isl::aff_list list2) const;
+  inline void foreach(const std::function<void(isl::aff)> &fn) const;
+  inline isl::aff at(int index) const;
+  inline isl::aff get_at(int index) const;
+  inline unsigned size() const;
 };
 
 // declarations for isl::ast_build
@@ -344,6 +454,7 @@ class ast_build {
   friend inline ast_build manage(__isl_take isl_ast_build *ptr);
   friend inline ast_build manage_copy(__isl_keep isl_ast_build *ptr);
 
+protected:
   isl_ast_build *ptr = nullptr;
 
   inline explicit ast_build(__isl_take isl_ast_build *ptr);
@@ -351,7 +462,7 @@ class ast_build {
 public:
   inline /* implicit */ ast_build();
   inline /* implicit */ ast_build(const ast_build &obj);
-  inline explicit ast_build(ctx ctx);
+  inline explicit ast_build(isl::ctx ctx);
   inline ast_build &operator=(ast_build obj);
   inline ~ast_build();
   inline __isl_give isl_ast_build *copy() const &;
@@ -359,16 +470,30 @@ class ast_build {
   inline __isl_keep isl_ast_build *get() const;
   inline __isl_give isl_ast_build *release();
   inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline ast_expr access_from(pw_multi_aff pma) const;
-  inline ast_expr access_from(multi_pw_aff mpa) const;
-  inline ast_expr call_from(pw_multi_aff pma) const;
-  inline ast_expr call_from(multi_pw_aff mpa) const;
-  inline ast_expr expr_from(set set) const;
-  inline ast_expr expr_from(pw_aff pa) const;
-  static inline ast_build from_context(set set);
-  inline ast_node node_from_schedule_map(union_map schedule) const;
+  inline isl::ctx ctx() const;
+
+private:
+  inline ast_build &copy_callbacks(const ast_build &obj);
+  struct at_each_domain_data {
+    std::function<isl::ast_node(isl::ast_node, isl::ast_build)> func;
+    std::exception_ptr eptr;
+  };
+  std::shared_ptr<at_each_domain_data> at_each_domain_data;
+  static inline isl_ast_node *at_each_domain(isl_ast_node *arg_0, isl_ast_build *arg_1, void *arg_2);
+  inline void set_at_each_domain_data(const std::function<isl::ast_node(isl::ast_node, isl::ast_build)> &fn);
+public:
+  inline isl::ast_build set_at_each_domain(const std::function<isl::ast_node(isl::ast_node, isl::ast_build)> &fn) const;
+  inline isl::ast_expr access_from(isl::multi_pw_aff mpa) const;
+  inline isl::ast_expr access_from(isl::pw_multi_aff pma) const;
+  inline isl::ast_expr call_from(isl::multi_pw_aff mpa) const;
+  inline isl::ast_expr call_from(isl::pw_multi_aff pma) const;
+  inline isl::ast_expr expr_from(isl::pw_aff pa) const;
+  inline isl::ast_expr expr_from(isl::set set) const;
+  static inline isl::ast_build from_context(isl::set set);
+  inline isl::union_map schedule() const;
+  inline isl::union_map get_schedule() const;
+  inline isl::ast_node node_from(isl::schedule schedule) const;
+  inline isl::ast_node node_from_schedule_map(isl::union_map schedule) const;
 };
 
 // declarations for isl::ast_expr
@@ -379,6 +504,7 @@ class ast_expr {
   friend inline ast_expr manage(__isl_take isl_ast_expr *ptr);
   friend inline ast_expr manage_copy(__isl_keep isl_ast_expr *ptr);
 
+protected:
   isl_ast_expr *ptr = nullptr;
 
   inline explicit ast_expr(__isl_take isl_ast_expr *ptr);
@@ -393,6230 +519,16319 @@ class ast_expr {
   inline __isl_keep isl_ast_expr *get() const;
   inline __isl_give isl_ast_expr *release();
   inline bool is_null() const;
-  inline ctx get_ctx() const;
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_ast_expr_get_type(NULL)),
+                  const T>::value>::type>
+  inline bool isa_type(T subtype) const;
+public:
+  template <class T> inline bool isa() const;
+  template <class T> inline T as() const;
+  inline isl::ctx ctx() const;
 
   inline std::string to_C_str() const;
 };
 
-// declarations for isl::ast_node
-inline ast_node manage(__isl_take isl_ast_node *ptr);
-inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
-
-class ast_node {
-  friend inline ast_node manage(__isl_take isl_ast_node *ptr);
-  friend inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+// declarations for isl::ast_expr_id
 
-  isl_ast_node *ptr = nullptr;
+class ast_expr_id : public ast_expr {
+  template <class T>
+  friend bool ast_expr::isa() const;
+  friend ast_expr_id ast_expr::as<ast_expr_id>() const;
+  static const auto type = isl_ast_expr_id;
 
-  inline explicit ast_node(__isl_take isl_ast_node *ptr);
+protected:
+  inline explicit ast_expr_id(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ ast_node();
-  inline /* implicit */ ast_node(const ast_node &obj);
-  inline ast_node &operator=(ast_node obj);
-  inline ~ast_node();
-  inline __isl_give isl_ast_node *copy() const &;
-  inline __isl_give isl_ast_node *copy() && = delete;
-  inline __isl_keep isl_ast_node *get() const;
-  inline __isl_give isl_ast_node *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_id();
+  inline /* implicit */ ast_expr_id(const ast_expr_id &obj);
+  inline ast_expr_id &operator=(ast_expr_id obj);
+  inline isl::ctx ctx() const;
 
-  inline std::string to_C_str() const;
+  inline isl::id id() const;
+  inline isl::id get_id() const;
 };
 
-// declarations for isl::basic_map
-inline basic_map manage(__isl_take isl_basic_map *ptr);
-inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
-
-class basic_map {
-  friend inline basic_map manage(__isl_take isl_basic_map *ptr);
-  friend inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+// declarations for isl::ast_expr_int
 
-  isl_basic_map *ptr = nullptr;
+class ast_expr_int : public ast_expr {
+  template <class T>
+  friend bool ast_expr::isa() const;
+  friend ast_expr_int ast_expr::as<ast_expr_int>() const;
+  static const auto type = isl_ast_expr_int;
 
-  inline explicit basic_map(__isl_take isl_basic_map *ptr);
+protected:
+  inline explicit ast_expr_int(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ basic_map();
-  inline /* implicit */ basic_map(const basic_map &obj);
-  inline explicit basic_map(ctx ctx, const std::string &str);
-  inline basic_map &operator=(basic_map obj);
-  inline ~basic_map();
-  inline __isl_give isl_basic_map *copy() const &;
-  inline __isl_give isl_basic_map *copy() && = delete;
-  inline __isl_keep isl_basic_map *get() const;
-  inline __isl_give isl_basic_map *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_map affine_hull() const;
-  inline basic_map apply_domain(basic_map bmap2) const;
-  inline basic_map apply_range(basic_map bmap2) const;
-  inline basic_set deltas() const;
-  inline basic_map detect_equalities() const;
-  inline basic_map flatten() const;
-  inline basic_map flatten_domain() const;
-  inline basic_map flatten_range() const;
-  inline basic_map gist(basic_map context) const;
-  inline basic_map intersect(basic_map bmap2) const;
-  inline basic_map intersect_domain(basic_set bset) const;
-  inline basic_map intersect_range(basic_set bset) const;
-  inline bool is_empty() const;
-  inline bool is_equal(const basic_map &bmap2) const;
-  inline bool is_subset(const basic_map &bmap2) const;
-  inline map lexmax() const;
-  inline map lexmin() const;
-  inline basic_map reverse() const;
-  inline basic_map sample() const;
-  inline map unite(basic_map bmap2) const;
-};
+  inline /* implicit */ ast_expr_int();
+  inline /* implicit */ ast_expr_int(const ast_expr_int &obj);
+  inline ast_expr_int &operator=(ast_expr_int obj);
+  inline isl::ctx ctx() const;
 
-// declarations for isl::basic_set
-inline basic_set manage(__isl_take isl_basic_set *ptr);
-inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+  inline isl::val val() const;
+  inline isl::val get_val() const;
+};
 
-class basic_set {
-  friend inline basic_set manage(__isl_take isl_basic_set *ptr);
-  friend inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+// declarations for isl::ast_expr_op
 
-  isl_basic_set *ptr = nullptr;
+class ast_expr_op : public ast_expr {
+  template <class T>
+  friend bool ast_expr::isa() const;
+  friend ast_expr_op ast_expr::as<ast_expr_op>() const;
+  static const auto type = isl_ast_expr_op;
 
-  inline explicit basic_set(__isl_take isl_basic_set *ptr);
+protected:
+  inline explicit ast_expr_op(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ basic_set();
-  inline /* implicit */ basic_set(const basic_set &obj);
-  inline explicit basic_set(ctx ctx, const std::string &str);
-  inline /* implicit */ basic_set(point pnt);
-  inline basic_set &operator=(basic_set obj);
-  inline ~basic_set();
-  inline __isl_give isl_basic_set *copy() const &;
-  inline __isl_give isl_basic_set *copy() && = delete;
-  inline __isl_keep isl_basic_set *get() const;
-  inline __isl_give isl_basic_set *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_set affine_hull() const;
-  inline basic_set apply(basic_map bmap) const;
-  inline basic_set detect_equalities() const;
-  inline val dim_max_val(int pos) const;
-  inline basic_set flatten() const;
-  inline basic_set gist(basic_set context) const;
-  inline basic_set intersect(basic_set bset2) const;
-  inline basic_set intersect_params(basic_set bset2) const;
-  inline bool is_empty() const;
-  inline bool is_equal(const basic_set &bset2) const;
-  inline bool is_subset(const basic_set &bset2) const;
-  inline bool is_wrapping() const;
-  inline set lexmax() const;
-  inline set lexmin() const;
-  inline basic_set sample() const;
-  inline point sample_point() const;
-  inline set unite(basic_set bset2) const;
+  inline /* implicit */ ast_expr_op();
+  inline /* implicit */ ast_expr_op(const ast_expr_op &obj);
+  inline ast_expr_op &operator=(ast_expr_op obj);
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_ast_expr_op_get_type(NULL)),
+                  const T>::value>::type>
+  inline bool isa_type(T subtype) const;
+public:
+  template <class T> inline bool isa() const;
+  template <class T> inline T as() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::ast_expr arg(int pos) const;
+  inline isl::ast_expr get_arg(int pos) const;
+  inline unsigned n_arg() const;
+  inline unsigned get_n_arg() const;
 };
 
-// declarations for isl::map
-inline map manage(__isl_take isl_map *ptr);
-inline map manage_copy(__isl_keep isl_map *ptr);
-
-class map {
-  friend inline map manage(__isl_take isl_map *ptr);
-  friend inline map manage_copy(__isl_keep isl_map *ptr);
+// declarations for isl::ast_expr_op_access
 
-  isl_map *ptr = nullptr;
+class ast_expr_op_access : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_access ast_expr_op::as<ast_expr_op_access>() const;
+  static const auto type = isl_ast_expr_op_access;
 
-  inline explicit map(__isl_take isl_map *ptr);
+protected:
+  inline explicit ast_expr_op_access(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ map();
-  inline /* implicit */ map(const map &obj);
-  inline explicit map(ctx ctx, const std::string &str);
-  inline /* implicit */ map(basic_map bmap);
-  inline map &operator=(map obj);
-  inline ~map();
-  inline __isl_give isl_map *copy() const &;
-  inline __isl_give isl_map *copy() && = delete;
-  inline __isl_keep isl_map *get() const;
-  inline __isl_give isl_map *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_map affine_hull() const;
-  inline map apply_domain(map map2) const;
-  inline map apply_range(map map2) const;
-  inline map coalesce() const;
-  inline map complement() const;
-  inline set deltas() const;
-  inline map detect_equalities() const;
-  inline map flatten() const;
-  inline map flatten_domain() const;
-  inline map flatten_range() const;
-  inline void foreach_basic_map(const std::function<void(basic_map)> &fn) const;
-  inline map gist(map context) const;
-  inline map gist_domain(set context) const;
-  inline map intersect(map map2) const;
-  inline map intersect_domain(set set) const;
-  inline map intersect_params(set params) const;
-  inline map intersect_range(set set) const;
-  inline bool is_bijective() const;
-  inline bool is_disjoint(const map &map2) const;
-  inline bool is_empty() const;
-  inline bool is_equal(const map &map2) const;
-  inline bool is_injective() const;
-  inline bool is_single_valued() const;
-  inline bool is_strict_subset(const map &map2) const;
-  inline bool is_subset(const map &map2) const;
-  inline map lexmax() const;
-  inline map lexmin() const;
-  inline basic_map polyhedral_hull() const;
-  inline map reverse() const;
-  inline basic_map sample() const;
-  inline map subtract(map map2) const;
-  inline map unite(map map2) const;
-  inline basic_map unshifted_simple_hull() const;
-};
+  inline /* implicit */ ast_expr_op_access();
+  inline /* implicit */ ast_expr_op_access(const ast_expr_op_access &obj);
+  inline ast_expr_op_access &operator=(ast_expr_op_access obj);
+  inline isl::ctx ctx() const;
 
-// declarations for isl::multi_aff
-inline multi_aff manage(__isl_take isl_multi_aff *ptr);
-inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+};
 
-class multi_aff {
-  friend inline multi_aff manage(__isl_take isl_multi_aff *ptr);
-  friend inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+// declarations for isl::ast_expr_op_add
 
-  isl_multi_aff *ptr = nullptr;
+class ast_expr_op_add : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_add ast_expr_op::as<ast_expr_op_add>() const;
+  static const auto type = isl_ast_expr_op_add;
 
-  inline explicit multi_aff(__isl_take isl_multi_aff *ptr);
+protected:
+  inline explicit ast_expr_op_add(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_aff();
-  inline /* implicit */ multi_aff(const multi_aff &obj);
-  inline /* implicit */ multi_aff(aff aff);
-  inline explicit multi_aff(ctx ctx, const std::string &str);
-  inline multi_aff &operator=(multi_aff obj);
-  inline ~multi_aff();
-  inline __isl_give isl_multi_aff *copy() const &;
-  inline __isl_give isl_multi_aff *copy() && = delete;
-  inline __isl_keep isl_multi_aff *get() const;
-  inline __isl_give isl_multi_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_add();
+  inline /* implicit */ ast_expr_op_add(const ast_expr_op_add &obj);
+  inline ast_expr_op_add &operator=(ast_expr_op_add obj);
+  inline isl::ctx ctx() const;
 
-  inline multi_aff add(multi_aff multi2) const;
-  inline multi_aff flat_range_product(multi_aff multi2) const;
-  inline multi_aff product(multi_aff multi2) const;
-  inline multi_aff pullback(multi_aff ma2) const;
-  inline multi_aff range_product(multi_aff multi2) const;
 };
 
-// declarations for isl::multi_pw_aff
-inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
-inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
-
-class multi_pw_aff {
-  friend inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
-  friend inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+// declarations for isl::ast_expr_op_address_of
 
-  isl_multi_pw_aff *ptr = nullptr;
+class ast_expr_op_address_of : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_address_of ast_expr_op::as<ast_expr_op_address_of>() const;
+  static const auto type = isl_ast_expr_op_address_of;
 
-  inline explicit multi_pw_aff(__isl_take isl_multi_pw_aff *ptr);
+protected:
+  inline explicit ast_expr_op_address_of(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_pw_aff();
-  inline /* implicit */ multi_pw_aff(const multi_pw_aff &obj);
-  inline /* implicit */ multi_pw_aff(multi_aff ma);
-  inline /* implicit */ multi_pw_aff(pw_aff pa);
-  inline /* implicit */ multi_pw_aff(pw_multi_aff pma);
-  inline explicit multi_pw_aff(ctx ctx, const std::string &str);
-  inline multi_pw_aff &operator=(multi_pw_aff obj);
-  inline ~multi_pw_aff();
-  inline __isl_give isl_multi_pw_aff *copy() const &;
-  inline __isl_give isl_multi_pw_aff *copy() && = delete;
-  inline __isl_keep isl_multi_pw_aff *get() const;
-  inline __isl_give isl_multi_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline multi_pw_aff add(multi_pw_aff multi2) const;
-  inline multi_pw_aff flat_range_product(multi_pw_aff multi2) const;
-  inline multi_pw_aff product(multi_pw_aff multi2) const;
-  inline multi_pw_aff pullback(multi_aff ma) const;
-  inline multi_pw_aff pullback(pw_multi_aff pma) const;
-  inline multi_pw_aff pullback(multi_pw_aff mpa2) const;
-  inline multi_pw_aff range_product(multi_pw_aff multi2) const;
-};
+  inline /* implicit */ ast_expr_op_address_of();
+  inline /* implicit */ ast_expr_op_address_of(const ast_expr_op_address_of &obj);
+  inline ast_expr_op_address_of &operator=(ast_expr_op_address_of obj);
+  inline isl::ctx ctx() const;
 
-// declarations for isl::multi_union_pw_aff
-inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
-inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+};
 
-class multi_union_pw_aff {
-  friend inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
-  friend inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+// declarations for isl::ast_expr_op_and
 
-  isl_multi_union_pw_aff *ptr = nullptr;
+class ast_expr_op_and : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_and ast_expr_op::as<ast_expr_op_and>() const;
+  static const auto type = isl_ast_expr_op_and;
 
-  inline explicit multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr);
+protected:
+  inline explicit ast_expr_op_and(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_union_pw_aff();
-  inline /* implicit */ multi_union_pw_aff(const multi_union_pw_aff &obj);
-  inline /* implicit */ multi_union_pw_aff(union_pw_aff upa);
-  inline /* implicit */ multi_union_pw_aff(multi_pw_aff mpa);
-  inline explicit multi_union_pw_aff(ctx ctx, const std::string &str);
-  inline multi_union_pw_aff &operator=(multi_union_pw_aff obj);
-  inline ~multi_union_pw_aff();
-  inline __isl_give isl_multi_union_pw_aff *copy() const &;
-  inline __isl_give isl_multi_union_pw_aff *copy() && = delete;
-  inline __isl_keep isl_multi_union_pw_aff *get() const;
-  inline __isl_give isl_multi_union_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_and();
+  inline /* implicit */ ast_expr_op_and(const ast_expr_op_and &obj);
+  inline ast_expr_op_and &operator=(ast_expr_op_and obj);
+  inline isl::ctx ctx() const;
 
-  inline multi_union_pw_aff add(multi_union_pw_aff multi2) const;
-  inline multi_union_pw_aff flat_range_product(multi_union_pw_aff multi2) const;
-  inline multi_union_pw_aff pullback(union_pw_multi_aff upma) const;
-  inline multi_union_pw_aff range_product(multi_union_pw_aff multi2) const;
-  inline multi_union_pw_aff union_add(multi_union_pw_aff mupa2) const;
 };
 
-// declarations for isl::multi_val
-inline multi_val manage(__isl_take isl_multi_val *ptr);
-inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
-
-class multi_val {
-  friend inline multi_val manage(__isl_take isl_multi_val *ptr);
-  friend inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+// declarations for isl::ast_expr_op_and_then
 
-  isl_multi_val *ptr = nullptr;
+class ast_expr_op_and_then : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_and_then ast_expr_op::as<ast_expr_op_and_then>() const;
+  static const auto type = isl_ast_expr_op_and_then;
 
-  inline explicit multi_val(__isl_take isl_multi_val *ptr);
+protected:
+  inline explicit ast_expr_op_and_then(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ multi_val();
-  inline /* implicit */ multi_val(const multi_val &obj);
-  inline multi_val &operator=(multi_val obj);
-  inline ~multi_val();
-  inline __isl_give isl_multi_val *copy() const &;
-  inline __isl_give isl_multi_val *copy() && = delete;
-  inline __isl_keep isl_multi_val *get() const;
-  inline __isl_give isl_multi_val *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_and_then();
+  inline /* implicit */ ast_expr_op_and_then(const ast_expr_op_and_then &obj);
+  inline ast_expr_op_and_then &operator=(ast_expr_op_and_then obj);
+  inline isl::ctx ctx() const;
 
-  inline multi_val add(multi_val multi2) const;
-  inline multi_val flat_range_product(multi_val multi2) const;
-  inline multi_val product(multi_val multi2) const;
-  inline multi_val range_product(multi_val multi2) const;
 };
 
-// declarations for isl::point
-inline point manage(__isl_take isl_point *ptr);
-inline point manage_copy(__isl_keep isl_point *ptr);
-
-class point {
-  friend inline point manage(__isl_take isl_point *ptr);
-  friend inline point manage_copy(__isl_keep isl_point *ptr);
+// declarations for isl::ast_expr_op_call
 
-  isl_point *ptr = nullptr;
+class ast_expr_op_call : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_call ast_expr_op::as<ast_expr_op_call>() const;
+  static const auto type = isl_ast_expr_op_call;
 
-  inline explicit point(__isl_take isl_point *ptr);
+protected:
+  inline explicit ast_expr_op_call(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ point();
-  inline /* implicit */ point(const point &obj);
-  inline point &operator=(point obj);
-  inline ~point();
-  inline __isl_give isl_point *copy() const &;
-  inline __isl_give isl_point *copy() && = delete;
-  inline __isl_keep isl_point *get() const;
-  inline __isl_give isl_point *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_call();
+  inline /* implicit */ ast_expr_op_call(const ast_expr_op_call &obj);
+  inline ast_expr_op_call &operator=(ast_expr_op_call obj);
+  inline isl::ctx ctx() const;
 
 };
 
-// declarations for isl::pw_aff
-inline pw_aff manage(__isl_take isl_pw_aff *ptr);
-inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
-
-class pw_aff {
-  friend inline pw_aff manage(__isl_take isl_pw_aff *ptr);
-  friend inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+// declarations for isl::ast_expr_op_cond
 
-  isl_pw_aff *ptr = nullptr;
+class ast_expr_op_cond : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_cond ast_expr_op::as<ast_expr_op_cond>() const;
+  static const auto type = isl_ast_expr_op_cond;
 
-  inline explicit pw_aff(__isl_take isl_pw_aff *ptr);
+protected:
+  inline explicit ast_expr_op_cond(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ pw_aff();
-  inline /* implicit */ pw_aff(const pw_aff &obj);
-  inline /* implicit */ pw_aff(aff aff);
-  inline explicit pw_aff(ctx ctx, const std::string &str);
-  inline pw_aff &operator=(pw_aff obj);
-  inline ~pw_aff();
-  inline __isl_give isl_pw_aff *copy() const &;
-  inline __isl_give isl_pw_aff *copy() && = delete;
-  inline __isl_keep isl_pw_aff *get() const;
-  inline __isl_give isl_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline pw_aff add(pw_aff pwaff2) const;
-  inline pw_aff ceil() const;
-  inline pw_aff cond(pw_aff pwaff_true, pw_aff pwaff_false) const;
-  inline pw_aff div(pw_aff pa2) const;
-  inline set eq_set(pw_aff pwaff2) const;
-  inline pw_aff floor() const;
-  inline set ge_set(pw_aff pwaff2) const;
-  inline set gt_set(pw_aff pwaff2) const;
-  inline set le_set(pw_aff pwaff2) const;
-  inline set lt_set(pw_aff pwaff2) const;
-  inline pw_aff max(pw_aff pwaff2) const;
-  inline pw_aff min(pw_aff pwaff2) const;
-  inline pw_aff mod(val mod) const;
-  inline pw_aff mul(pw_aff pwaff2) const;
-  inline set ne_set(pw_aff pwaff2) const;
-  inline pw_aff neg() const;
-  inline pw_aff pullback(multi_aff ma) const;
-  inline pw_aff pullback(pw_multi_aff pma) const;
-  inline pw_aff pullback(multi_pw_aff mpa) const;
-  inline pw_aff scale(val v) const;
-  inline pw_aff scale_down(val f) const;
-  inline pw_aff sub(pw_aff pwaff2) const;
-  inline pw_aff tdiv_q(pw_aff pa2) const;
-  inline pw_aff tdiv_r(pw_aff pa2) const;
-  inline pw_aff union_add(pw_aff pwaff2) const;
-};
+  inline /* implicit */ ast_expr_op_cond();
+  inline /* implicit */ ast_expr_op_cond(const ast_expr_op_cond &obj);
+  inline ast_expr_op_cond &operator=(ast_expr_op_cond obj);
+  inline isl::ctx ctx() const;
 
-// declarations for isl::pw_multi_aff
-inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
-inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+};
 
-class pw_multi_aff {
-  friend inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
-  friend inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+// declarations for isl::ast_expr_op_div
 
-  isl_pw_multi_aff *ptr = nullptr;
+class ast_expr_op_div : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_div ast_expr_op::as<ast_expr_op_div>() const;
+  static const auto type = isl_ast_expr_op_div;
 
-  inline explicit pw_multi_aff(__isl_take isl_pw_multi_aff *ptr);
+protected:
+  inline explicit ast_expr_op_div(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ pw_multi_aff();
-  inline /* implicit */ pw_multi_aff(const pw_multi_aff &obj);
-  inline /* implicit */ pw_multi_aff(multi_aff ma);
-  inline /* implicit */ pw_multi_aff(pw_aff pa);
-  inline explicit pw_multi_aff(ctx ctx, const std::string &str);
-  inline pw_multi_aff &operator=(pw_multi_aff obj);
-  inline ~pw_multi_aff();
-  inline __isl_give isl_pw_multi_aff *copy() const &;
-  inline __isl_give isl_pw_multi_aff *copy() && = delete;
-  inline __isl_keep isl_pw_multi_aff *get() const;
-  inline __isl_give isl_pw_multi_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline pw_multi_aff add(pw_multi_aff pma2) const;
-  inline pw_multi_aff flat_range_product(pw_multi_aff pma2) const;
-  inline pw_multi_aff product(pw_multi_aff pma2) const;
-  inline pw_multi_aff pullback(multi_aff ma) const;
-  inline pw_multi_aff pullback(pw_multi_aff pma2) const;
-  inline pw_multi_aff range_product(pw_multi_aff pma2) const;
-  inline pw_multi_aff union_add(pw_multi_aff pma2) const;
+  inline /* implicit */ ast_expr_op_div();
+  inline /* implicit */ ast_expr_op_div(const ast_expr_op_div &obj);
+  inline ast_expr_op_div &operator=(ast_expr_op_div obj);
+  inline isl::ctx ctx() const;
+
 };
 
-// declarations for isl::schedule
-inline schedule manage(__isl_take isl_schedule *ptr);
-inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+// declarations for isl::ast_expr_op_eq
 
-class schedule {
-  friend inline schedule manage(__isl_take isl_schedule *ptr);
-  friend inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+class ast_expr_op_eq : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_eq ast_expr_op::as<ast_expr_op_eq>() const;
+  static const auto type = isl_ast_expr_op_eq;
 
-  isl_schedule *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_eq(__isl_take isl_ast_expr *ptr);
 
-  inline explicit schedule(__isl_take isl_schedule *ptr);
+public:
+  inline /* implicit */ ast_expr_op_eq();
+  inline /* implicit */ ast_expr_op_eq(const ast_expr_op_eq &obj);
+  inline ast_expr_op_eq &operator=(ast_expr_op_eq obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_fdiv_q
+
+class ast_expr_op_fdiv_q : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_fdiv_q ast_expr_op::as<ast_expr_op_fdiv_q>() const;
+  static const auto type = isl_ast_expr_op_fdiv_q;
+
+protected:
+  inline explicit ast_expr_op_fdiv_q(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ schedule();
-  inline /* implicit */ schedule(const schedule &obj);
-  inline explicit schedule(ctx ctx, const std::string &str);
-  inline schedule &operator=(schedule obj);
-  inline ~schedule();
-  inline __isl_give isl_schedule *copy() const &;
-  inline __isl_give isl_schedule *copy() && = delete;
-  inline __isl_keep isl_schedule *get() const;
-  inline __isl_give isl_schedule *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_fdiv_q();
+  inline /* implicit */ ast_expr_op_fdiv_q(const ast_expr_op_fdiv_q &obj);
+  inline ast_expr_op_fdiv_q &operator=(ast_expr_op_fdiv_q obj);
+  inline isl::ctx ctx() const;
 
-  inline union_map get_map() const;
-  inline schedule_node get_root() const;
-  inline schedule pullback(union_pw_multi_aff upma) const;
 };
 
-// declarations for isl::schedule_constraints
-inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
-inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+// declarations for isl::ast_expr_op_ge
 
-class schedule_constraints {
-  friend inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
-  friend inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+class ast_expr_op_ge : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_ge ast_expr_op::as<ast_expr_op_ge>() const;
+  static const auto type = isl_ast_expr_op_ge;
 
-  isl_schedule_constraints *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_ge(__isl_take isl_ast_expr *ptr);
 
-  inline explicit schedule_constraints(__isl_take isl_schedule_constraints *ptr);
+public:
+  inline /* implicit */ ast_expr_op_ge();
+  inline /* implicit */ ast_expr_op_ge(const ast_expr_op_ge &obj);
+  inline ast_expr_op_ge &operator=(ast_expr_op_ge obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_gt
+
+class ast_expr_op_gt : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_gt ast_expr_op::as<ast_expr_op_gt>() const;
+  static const auto type = isl_ast_expr_op_gt;
+
+protected:
+  inline explicit ast_expr_op_gt(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ schedule_constraints();
-  inline /* implicit */ schedule_constraints(const schedule_constraints &obj);
-  inline explicit schedule_constraints(ctx ctx, const std::string &str);
-  inline schedule_constraints &operator=(schedule_constraints obj);
-  inline ~schedule_constraints();
-  inline __isl_give isl_schedule_constraints *copy() const &;
-  inline __isl_give isl_schedule_constraints *copy() && = delete;
-  inline __isl_keep isl_schedule_constraints *get() const;
-  inline __isl_give isl_schedule_constraints *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline schedule compute_schedule() const;
-  inline union_map get_coincidence() const;
-  inline union_map get_conditional_validity() const;
-  inline union_map get_conditional_validity_condition() const;
-  inline set get_context() const;
-  inline union_set get_domain() const;
-  inline union_map get_proximity() const;
-  inline union_map get_validity() const;
-  static inline schedule_constraints on_domain(union_set domain);
-  inline schedule_constraints set_coincidence(union_map coincidence) const;
-  inline schedule_constraints set_conditional_validity(union_map condition, union_map validity) const;
-  inline schedule_constraints set_context(set context) const;
-  inline schedule_constraints set_proximity(union_map proximity) const;
-  inline schedule_constraints set_validity(union_map validity) const;
+  inline /* implicit */ ast_expr_op_gt();
+  inline /* implicit */ ast_expr_op_gt(const ast_expr_op_gt &obj);
+  inline ast_expr_op_gt &operator=(ast_expr_op_gt obj);
+  inline isl::ctx ctx() const;
+
 };
 
-// declarations for isl::schedule_node
-inline schedule_node manage(__isl_take isl_schedule_node *ptr);
-inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+// declarations for isl::ast_expr_op_le
 
-class schedule_node {
-  friend inline schedule_node manage(__isl_take isl_schedule_node *ptr);
-  friend inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+class ast_expr_op_le : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_le ast_expr_op::as<ast_expr_op_le>() const;
+  static const auto type = isl_ast_expr_op_le;
 
-  isl_schedule_node *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_le(__isl_take isl_ast_expr *ptr);
 
-  inline explicit schedule_node(__isl_take isl_schedule_node *ptr);
+public:
+  inline /* implicit */ ast_expr_op_le();
+  inline /* implicit */ ast_expr_op_le(const ast_expr_op_le &obj);
+  inline ast_expr_op_le &operator=(ast_expr_op_le obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_lt
+
+class ast_expr_op_lt : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_lt ast_expr_op::as<ast_expr_op_lt>() const;
+  static const auto type = isl_ast_expr_op_lt;
+
+protected:
+  inline explicit ast_expr_op_lt(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ schedule_node();
-  inline /* implicit */ schedule_node(const schedule_node &obj);
-  inline schedule_node &operator=(schedule_node obj);
-  inline ~schedule_node();
-  inline __isl_give isl_schedule_node *copy() const &;
-  inline __isl_give isl_schedule_node *copy() && = delete;
-  inline __isl_keep isl_schedule_node *get() const;
-  inline __isl_give isl_schedule_node *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline bool band_member_get_coincident(int pos) const;
-  inline schedule_node band_member_set_coincident(int pos, int coincident) const;
-  inline schedule_node child(int pos) const;
-  inline multi_union_pw_aff get_prefix_schedule_multi_union_pw_aff() const;
-  inline union_map get_prefix_schedule_union_map() const;
-  inline union_pw_multi_aff get_prefix_schedule_union_pw_multi_aff() const;
-  inline schedule get_schedule() const;
-  inline schedule_node parent() const;
+  inline /* implicit */ ast_expr_op_lt();
+  inline /* implicit */ ast_expr_op_lt(const ast_expr_op_lt &obj);
+  inline ast_expr_op_lt &operator=(ast_expr_op_lt obj);
+  inline isl::ctx ctx() const;
+
 };
 
-// declarations for isl::set
-inline set manage(__isl_take isl_set *ptr);
-inline set manage_copy(__isl_keep isl_set *ptr);
+// declarations for isl::ast_expr_op_max
 
-class set {
-  friend inline set manage(__isl_take isl_set *ptr);
-  friend inline set manage_copy(__isl_keep isl_set *ptr);
+class ast_expr_op_max : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_max ast_expr_op::as<ast_expr_op_max>() const;
+  static const auto type = isl_ast_expr_op_max;
 
-  isl_set *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_max(__isl_take isl_ast_expr *ptr);
 
-  inline explicit set(__isl_take isl_set *ptr);
+public:
+  inline /* implicit */ ast_expr_op_max();
+  inline /* implicit */ ast_expr_op_max(const ast_expr_op_max &obj);
+  inline ast_expr_op_max &operator=(ast_expr_op_max obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_member
+
+class ast_expr_op_member : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_member ast_expr_op::as<ast_expr_op_member>() const;
+  static const auto type = isl_ast_expr_op_member;
+
+protected:
+  inline explicit ast_expr_op_member(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ set();
-  inline /* implicit */ set(const set &obj);
-  inline explicit set(ctx ctx, const std::string &str);
-  inline /* implicit */ set(basic_set bset);
-  inline /* implicit */ set(point pnt);
-  inline set &operator=(set obj);
-  inline ~set();
-  inline __isl_give isl_set *copy() const &;
-  inline __isl_give isl_set *copy() && = delete;
-  inline __isl_keep isl_set *get() const;
-  inline __isl_give isl_set *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline basic_set affine_hull() const;
-  inline set apply(map map) const;
-  inline set coalesce() const;
-  inline set complement() const;
-  inline set detect_equalities() const;
-  inline set flatten() const;
-  inline void foreach_basic_set(const std::function<void(basic_set)> &fn) const;
-  inline val get_stride(int pos) const;
-  inline set gist(set context) const;
-  inline map identity() const;
-  inline set intersect(set set2) const;
-  inline set intersect_params(set params) const;
-  inline bool is_disjoint(const set &set2) const;
-  inline bool is_empty() const;
-  inline bool is_equal(const set &set2) const;
-  inline bool is_strict_subset(const set &set2) const;
-  inline bool is_subset(const set &set2) const;
-  inline bool is_wrapping() const;
-  inline set lexmax() const;
-  inline set lexmin() const;
-  inline val max_val(const aff &obj) const;
-  inline val min_val(const aff &obj) const;
-  inline basic_set polyhedral_hull() const;
-  inline basic_set sample() const;
-  inline point sample_point() const;
-  inline set subtract(set set2) const;
-  inline set unite(set set2) const;
-  inline basic_set unshifted_simple_hull() const;
+  inline /* implicit */ ast_expr_op_member();
+  inline /* implicit */ ast_expr_op_member(const ast_expr_op_member &obj);
+  inline ast_expr_op_member &operator=(ast_expr_op_member obj);
+  inline isl::ctx ctx() const;
+
 };
 
-// declarations for isl::union_access_info
-inline union_access_info manage(__isl_take isl_union_access_info *ptr);
-inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+// declarations for isl::ast_expr_op_min
 
-class union_access_info {
-  friend inline union_access_info manage(__isl_take isl_union_access_info *ptr);
-  friend inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+class ast_expr_op_min : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_min ast_expr_op::as<ast_expr_op_min>() const;
+  static const auto type = isl_ast_expr_op_min;
 
-  isl_union_access_info *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_min(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_access_info(__isl_take isl_union_access_info *ptr);
+public:
+  inline /* implicit */ ast_expr_op_min();
+  inline /* implicit */ ast_expr_op_min(const ast_expr_op_min &obj);
+  inline ast_expr_op_min &operator=(ast_expr_op_min obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_minus
+
+class ast_expr_op_minus : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_minus ast_expr_op::as<ast_expr_op_minus>() const;
+  static const auto type = isl_ast_expr_op_minus;
+
+protected:
+  inline explicit ast_expr_op_minus(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_access_info();
-  inline /* implicit */ union_access_info(const union_access_info &obj);
-  inline explicit union_access_info(union_map sink);
-  inline union_access_info &operator=(union_access_info obj);
-  inline ~union_access_info();
-  inline __isl_give isl_union_access_info *copy() const &;
-  inline __isl_give isl_union_access_info *copy() && = delete;
-  inline __isl_keep isl_union_access_info *get() const;
-  inline __isl_give isl_union_access_info *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_flow compute_flow() const;
-  inline union_access_info set_kill(union_map kill) const;
-  inline union_access_info set_may_source(union_map may_source) const;
-  inline union_access_info set_must_source(union_map must_source) const;
-  inline union_access_info set_schedule(schedule schedule) const;
-  inline union_access_info set_schedule_map(union_map schedule_map) const;
+  inline /* implicit */ ast_expr_op_minus();
+  inline /* implicit */ ast_expr_op_minus(const ast_expr_op_minus &obj);
+  inline ast_expr_op_minus &operator=(ast_expr_op_minus obj);
+  inline isl::ctx ctx() const;
+
 };
 
-// declarations for isl::union_flow
-inline union_flow manage(__isl_take isl_union_flow *ptr);
-inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+// declarations for isl::ast_expr_op_mul
 
-class union_flow {
-  friend inline union_flow manage(__isl_take isl_union_flow *ptr);
-  friend inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+class ast_expr_op_mul : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_mul ast_expr_op::as<ast_expr_op_mul>() const;
+  static const auto type = isl_ast_expr_op_mul;
 
-  isl_union_flow *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_mul(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_flow(__isl_take isl_union_flow *ptr);
+public:
+  inline /* implicit */ ast_expr_op_mul();
+  inline /* implicit */ ast_expr_op_mul(const ast_expr_op_mul &obj);
+  inline ast_expr_op_mul &operator=(ast_expr_op_mul obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_or
+
+class ast_expr_op_or : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_or ast_expr_op::as<ast_expr_op_or>() const;
+  static const auto type = isl_ast_expr_op_or;
+
+protected:
+  inline explicit ast_expr_op_or(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_flow();
-  inline /* implicit */ union_flow(const union_flow &obj);
-  inline union_flow &operator=(union_flow obj);
-  inline ~union_flow();
-  inline __isl_give isl_union_flow *copy() const &;
-  inline __isl_give isl_union_flow *copy() && = delete;
-  inline __isl_keep isl_union_flow *get() const;
-  inline __isl_give isl_union_flow *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_map get_full_may_dependence() const;
-  inline union_map get_full_must_dependence() const;
-  inline union_map get_may_dependence() const;
-  inline union_map get_may_no_source() const;
-  inline union_map get_must_dependence() const;
-  inline union_map get_must_no_source() const;
+  inline /* implicit */ ast_expr_op_or();
+  inline /* implicit */ ast_expr_op_or(const ast_expr_op_or &obj);
+  inline ast_expr_op_or &operator=(ast_expr_op_or obj);
+  inline isl::ctx ctx() const;
+
 };
 
-// declarations for isl::union_map
-inline union_map manage(__isl_take isl_union_map *ptr);
-inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+// declarations for isl::ast_expr_op_or_else
 
-class union_map {
-  friend inline union_map manage(__isl_take isl_union_map *ptr);
-  friend inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+class ast_expr_op_or_else : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_or_else ast_expr_op::as<ast_expr_op_or_else>() const;
+  static const auto type = isl_ast_expr_op_or_else;
 
-  isl_union_map *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_or_else(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_map(__isl_take isl_union_map *ptr);
+public:
+  inline /* implicit */ ast_expr_op_or_else();
+  inline /* implicit */ ast_expr_op_or_else(const ast_expr_op_or_else &obj);
+  inline ast_expr_op_or_else &operator=(ast_expr_op_or_else obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_pdiv_q
+
+class ast_expr_op_pdiv_q : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_pdiv_q ast_expr_op::as<ast_expr_op_pdiv_q>() const;
+  static const auto type = isl_ast_expr_op_pdiv_q;
+
+protected:
+  inline explicit ast_expr_op_pdiv_q(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_map();
-  inline /* implicit */ union_map(const union_map &obj);
-  inline /* implicit */ union_map(basic_map bmap);
-  inline /* implicit */ union_map(map map);
-  inline explicit union_map(ctx ctx, const std::string &str);
-  inline union_map &operator=(union_map obj);
-  inline ~union_map();
-  inline __isl_give isl_union_map *copy() const &;
-  inline __isl_give isl_union_map *copy() && = delete;
-  inline __isl_keep isl_union_map *get() const;
-  inline __isl_give isl_union_map *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_map affine_hull() const;
-  inline union_map apply_domain(union_map umap2) const;
-  inline union_map apply_range(union_map umap2) const;
-  inline union_map coalesce() const;
-  inline union_map compute_divs() const;
-  inline union_set deltas() const;
-  inline union_map detect_equalities() const;
-  inline union_set domain() const;
-  inline union_map domain_factor_domain() const;
-  inline union_map domain_factor_range() const;
-  inline union_map domain_map() const;
-  inline union_pw_multi_aff domain_map_union_pw_multi_aff() const;
-  inline union_map domain_product(union_map umap2) const;
-  inline union_map eq_at(multi_union_pw_aff mupa) const;
-  inline union_map factor_domain() const;
-  inline union_map factor_range() const;
-  inline union_map fixed_power(val exp) const;
-  inline void foreach_map(const std::function<void(map)> &fn) const;
-  static inline union_map from(union_pw_multi_aff upma);
-  static inline union_map from(multi_union_pw_aff mupa);
-  static inline union_map from_domain(union_set uset);
-  static inline union_map from_domain_and_range(union_set domain, union_set range);
-  static inline union_map from_range(union_set uset);
-  inline union_map gist(union_map context) const;
-  inline union_map gist_domain(union_set uset) const;
-  inline union_map gist_params(set set) const;
-  inline union_map gist_range(union_set uset) const;
-  inline union_map intersect(union_map umap2) const;
-  inline union_map intersect_domain(union_set uset) const;
-  inline union_map intersect_params(set set) const;
-  inline union_map intersect_range(union_set uset) const;
-  inline bool is_bijective() const;
-  inline bool is_empty() const;
-  inline bool is_equal(const union_map &umap2) const;
-  inline bool is_injective() const;
-  inline bool is_single_valued() const;
-  inline bool is_strict_subset(const union_map &umap2) const;
-  inline bool is_subset(const union_map &umap2) const;
-  inline union_map lexmax() const;
-  inline union_map lexmin() const;
-  inline union_map polyhedral_hull() const;
-  inline union_map product(union_map umap2) const;
-  inline union_map project_out_all_params() const;
-  inline union_set range() const;
-  inline union_map range_factor_domain() const;
-  inline union_map range_factor_range() const;
-  inline union_map range_map() const;
-  inline union_map range_product(union_map umap2) const;
-  inline union_map reverse() const;
-  inline union_map subtract(union_map umap2) const;
-  inline union_map subtract_domain(union_set dom) const;
-  inline union_map subtract_range(union_set dom) const;
-  inline union_map unite(union_map umap2) const;
-  inline union_set wrap() const;
-  inline union_map zip() const;
+  inline /* implicit */ ast_expr_op_pdiv_q();
+  inline /* implicit */ ast_expr_op_pdiv_q(const ast_expr_op_pdiv_q &obj);
+  inline ast_expr_op_pdiv_q &operator=(ast_expr_op_pdiv_q obj);
+  inline isl::ctx ctx() const;
+
 };
 
-// declarations for isl::union_pw_aff
-inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
-inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+// declarations for isl::ast_expr_op_pdiv_r
 
-class union_pw_aff {
-  friend inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
-  friend inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+class ast_expr_op_pdiv_r : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_pdiv_r ast_expr_op::as<ast_expr_op_pdiv_r>() const;
+  static const auto type = isl_ast_expr_op_pdiv_r;
 
-  isl_union_pw_aff *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_pdiv_r(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_pw_aff(__isl_take isl_union_pw_aff *ptr);
+public:
+  inline /* implicit */ ast_expr_op_pdiv_r();
+  inline /* implicit */ ast_expr_op_pdiv_r(const ast_expr_op_pdiv_r &obj);
+  inline ast_expr_op_pdiv_r &operator=(ast_expr_op_pdiv_r obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_select
+
+class ast_expr_op_select : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_select ast_expr_op::as<ast_expr_op_select>() const;
+  static const auto type = isl_ast_expr_op_select;
+
+protected:
+  inline explicit ast_expr_op_select(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_pw_aff();
-  inline /* implicit */ union_pw_aff(const union_pw_aff &obj);
-  inline /* implicit */ union_pw_aff(pw_aff pa);
-  inline explicit union_pw_aff(ctx ctx, const std::string &str);
-  inline union_pw_aff &operator=(union_pw_aff obj);
-  inline ~union_pw_aff();
-  inline __isl_give isl_union_pw_aff *copy() const &;
-  inline __isl_give isl_union_pw_aff *copy() && = delete;
-  inline __isl_keep isl_union_pw_aff *get() const;
-  inline __isl_give isl_union_pw_aff *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+  inline /* implicit */ ast_expr_op_select();
+  inline /* implicit */ ast_expr_op_select(const ast_expr_op_select &obj);
+  inline ast_expr_op_select &operator=(ast_expr_op_select obj);
+  inline isl::ctx ctx() const;
 
-  inline union_pw_aff add(union_pw_aff upa2) const;
-  inline union_pw_aff pullback(union_pw_multi_aff upma) const;
-  inline union_pw_aff union_add(union_pw_aff upa2) const;
 };
 
-// declarations for isl::union_pw_multi_aff
-inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
-inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+// declarations for isl::ast_expr_op_sub
 
-class union_pw_multi_aff {
-  friend inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
-  friend inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+class ast_expr_op_sub : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_sub ast_expr_op::as<ast_expr_op_sub>() const;
+  static const auto type = isl_ast_expr_op_sub;
 
-  isl_union_pw_multi_aff *ptr = nullptr;
+protected:
+  inline explicit ast_expr_op_sub(__isl_take isl_ast_expr *ptr);
 
-  inline explicit union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr);
+public:
+  inline /* implicit */ ast_expr_op_sub();
+  inline /* implicit */ ast_expr_op_sub(const ast_expr_op_sub &obj);
+  inline ast_expr_op_sub &operator=(ast_expr_op_sub obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_expr_op_zdiv_r
+
+class ast_expr_op_zdiv_r : public ast_expr_op {
+  template <class T>
+  friend bool ast_expr_op::isa() const;
+  friend ast_expr_op_zdiv_r ast_expr_op::as<ast_expr_op_zdiv_r>() const;
+  static const auto type = isl_ast_expr_op_zdiv_r;
+
+protected:
+  inline explicit ast_expr_op_zdiv_r(__isl_take isl_ast_expr *ptr);
 
 public:
-  inline /* implicit */ union_pw_multi_aff();
-  inline /* implicit */ union_pw_multi_aff(const union_pw_multi_aff &obj);
-  inline /* implicit */ union_pw_multi_aff(pw_multi_aff pma);
-  inline explicit union_pw_multi_aff(ctx ctx, const std::string &str);
-  inline /* implicit */ union_pw_multi_aff(union_pw_aff upa);
-  inline union_pw_multi_aff &operator=(union_pw_multi_aff obj);
-  inline ~union_pw_multi_aff();
-  inline __isl_give isl_union_pw_multi_aff *copy() const &;
-  inline __isl_give isl_union_pw_multi_aff *copy() && = delete;
-  inline __isl_keep isl_union_pw_multi_aff *get() const;
-  inline __isl_give isl_union_pw_multi_aff *release();
+  inline /* implicit */ ast_expr_op_zdiv_r();
+  inline /* implicit */ ast_expr_op_zdiv_r(const ast_expr_op_zdiv_r &obj);
+  inline ast_expr_op_zdiv_r &operator=(ast_expr_op_zdiv_r obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::ast_node
+inline ast_node manage(__isl_take isl_ast_node *ptr);
+inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+
+class ast_node {
+  friend inline ast_node manage(__isl_take isl_ast_node *ptr);
+  friend inline ast_node manage_copy(__isl_keep isl_ast_node *ptr);
+
+protected:
+  isl_ast_node *ptr = nullptr;
+
+  inline explicit ast_node(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node();
+  inline /* implicit */ ast_node(const ast_node &obj);
+  inline ast_node &operator=(ast_node obj);
+  inline ~ast_node();
+  inline __isl_give isl_ast_node *copy() const &;
+  inline __isl_give isl_ast_node *copy() && = delete;
+  inline __isl_keep isl_ast_node *get() const;
+  inline __isl_give isl_ast_node *release();
   inline bool is_null() const;
-  inline ctx get_ctx() const;
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_ast_node_get_type(NULL)),
+                  const T>::value>::type>
+  inline bool isa_type(T subtype) const;
+public:
+  template <class T> inline bool isa() const;
+  template <class T> inline T as() const;
+  inline isl::ctx ctx() const;
 
-  inline union_pw_multi_aff add(union_pw_multi_aff upma2) const;
-  inline union_pw_multi_aff flat_range_product(union_pw_multi_aff upma2) const;
-  inline union_pw_multi_aff pullback(union_pw_multi_aff upma2) const;
-  inline union_pw_multi_aff union_add(union_pw_multi_aff upma2) const;
+  inline std::string to_C_str() const;
 };
 
-// declarations for isl::union_set
-inline union_set manage(__isl_take isl_union_set *ptr);
-inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+// declarations for isl::ast_node_block
+
+class ast_node_block : public ast_node {
+  template <class T>
+  friend bool ast_node::isa() const;
+  friend ast_node_block ast_node::as<ast_node_block>() const;
+  static const auto type = isl_ast_node_block;
+
+protected:
+  inline explicit ast_node_block(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_block();
+  inline /* implicit */ ast_node_block(const ast_node_block &obj);
+  inline ast_node_block &operator=(ast_node_block obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::ast_node_list children() const;
+  inline isl::ast_node_list get_children() const;
+};
+
+// declarations for isl::ast_node_for
+
+class ast_node_for : public ast_node {
+  template <class T>
+  friend bool ast_node::isa() const;
+  friend ast_node_for ast_node::as<ast_node_for>() const;
+  static const auto type = isl_ast_node_for;
+
+protected:
+  inline explicit ast_node_for(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_for();
+  inline /* implicit */ ast_node_for(const ast_node_for &obj);
+  inline ast_node_for &operator=(ast_node_for obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::ast_node body() const;
+  inline isl::ast_node get_body() const;
+  inline isl::ast_expr cond() const;
+  inline isl::ast_expr get_cond() const;
+  inline isl::ast_expr inc() const;
+  inline isl::ast_expr get_inc() const;
+  inline isl::ast_expr init() const;
+  inline isl::ast_expr get_init() const;
+  inline isl::ast_expr iterator() const;
+  inline isl::ast_expr get_iterator() const;
+  inline bool is_degenerate() const;
+};
+
+// declarations for isl::ast_node_if
+
+class ast_node_if : public ast_node {
+  template <class T>
+  friend bool ast_node::isa() const;
+  friend ast_node_if ast_node::as<ast_node_if>() const;
+  static const auto type = isl_ast_node_if;
+
+protected:
+  inline explicit ast_node_if(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_if();
+  inline /* implicit */ ast_node_if(const ast_node_if &obj);
+  inline ast_node_if &operator=(ast_node_if obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::ast_expr cond() const;
+  inline isl::ast_expr get_cond() const;
+  inline isl::ast_node else_node() const;
+  inline isl::ast_node get_else_node() const;
+  inline isl::ast_node then_node() const;
+  inline isl::ast_node get_then_node() const;
+  inline bool has_else_node() const;
+};
+
+// declarations for isl::ast_node_list
+inline ast_node_list manage(__isl_take isl_ast_node_list *ptr);
+inline ast_node_list manage_copy(__isl_keep isl_ast_node_list *ptr);
+
+class ast_node_list {
+  friend inline ast_node_list manage(__isl_take isl_ast_node_list *ptr);
+  friend inline ast_node_list manage_copy(__isl_keep isl_ast_node_list *ptr);
+
+protected:
+  isl_ast_node_list *ptr = nullptr;
+
+  inline explicit ast_node_list(__isl_take isl_ast_node_list *ptr);
+
+public:
+  inline /* implicit */ ast_node_list();
+  inline /* implicit */ ast_node_list(const ast_node_list &obj);
+  inline explicit ast_node_list(isl::ctx ctx, int n);
+  inline explicit ast_node_list(isl::ast_node el);
+  inline ast_node_list &operator=(ast_node_list obj);
+  inline ~ast_node_list();
+  inline __isl_give isl_ast_node_list *copy() const &;
+  inline __isl_give isl_ast_node_list *copy() && = delete;
+  inline __isl_keep isl_ast_node_list *get() const;
+  inline __isl_give isl_ast_node_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::ast_node_list add(isl::ast_node el) const;
+  inline isl::ast_node_list clear() const;
+  inline isl::ast_node_list concat(isl::ast_node_list list2) const;
+  inline void foreach(const std::function<void(isl::ast_node)> &fn) const;
+  inline isl::ast_node at(int index) const;
+  inline isl::ast_node get_at(int index) const;
+  inline unsigned size() const;
+};
+
+// declarations for isl::ast_node_mark
+
+class ast_node_mark : public ast_node {
+  template <class T>
+  friend bool ast_node::isa() const;
+  friend ast_node_mark ast_node::as<ast_node_mark>() const;
+  static const auto type = isl_ast_node_mark;
+
+protected:
+  inline explicit ast_node_mark(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_mark();
+  inline /* implicit */ ast_node_mark(const ast_node_mark &obj);
+  inline ast_node_mark &operator=(ast_node_mark obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::id id() const;
+  inline isl::id get_id() const;
+  inline isl::ast_node node() const;
+  inline isl::ast_node get_node() const;
+};
+
+// declarations for isl::ast_node_user
+
+class ast_node_user : public ast_node {
+  template <class T>
+  friend bool ast_node::isa() const;
+  friend ast_node_user ast_node::as<ast_node_user>() const;
+  static const auto type = isl_ast_node_user;
+
+protected:
+  inline explicit ast_node_user(__isl_take isl_ast_node *ptr);
+
+public:
+  inline /* implicit */ ast_node_user();
+  inline /* implicit */ ast_node_user(const ast_node_user &obj);
+  inline ast_node_user &operator=(ast_node_user obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::ast_expr expr() const;
+  inline isl::ast_expr get_expr() const;
+};
+
+// declarations for isl::basic_map
+inline basic_map manage(__isl_take isl_basic_map *ptr);
+inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+class basic_map {
+  friend inline basic_map manage(__isl_take isl_basic_map *ptr);
+  friend inline basic_map manage_copy(__isl_keep isl_basic_map *ptr);
+
+protected:
+  isl_basic_map *ptr = nullptr;
+
+  inline explicit basic_map(__isl_take isl_basic_map *ptr);
+
+public:
+  inline /* implicit */ basic_map();
+  inline /* implicit */ basic_map(const basic_map &obj);
+  inline explicit basic_map(isl::ctx ctx, const std::string &str);
+  inline basic_map &operator=(basic_map obj);
+  inline ~basic_map();
+  inline __isl_give isl_basic_map *copy() const &;
+  inline __isl_give isl_basic_map *copy() && = delete;
+  inline __isl_keep isl_basic_map *get() const;
+  inline __isl_give isl_basic_map *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::basic_map affine_hull() const;
+  inline isl::basic_map apply_domain(isl::basic_map bmap2) const;
+  inline isl::basic_map apply_range(isl::basic_map bmap2) const;
+  inline isl::basic_set deltas() const;
+  inline isl::basic_map detect_equalities() const;
+  inline isl::basic_map flatten() const;
+  inline isl::basic_map flatten_domain() const;
+  inline isl::basic_map flatten_range() const;
+  inline isl::basic_map gist(isl::basic_map context) const;
+  inline isl::basic_map intersect(isl::basic_map bmap2) const;
+  inline isl::basic_map intersect_domain(isl::basic_set bset) const;
+  inline isl::basic_map intersect_range(isl::basic_set bset) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const isl::basic_map &bmap2) const;
+  inline bool is_subset(const isl::basic_map &bmap2) const;
+  inline isl::map lexmax() const;
+  inline isl::map lexmin() const;
+  inline isl::basic_map reverse() const;
+  inline isl::basic_map sample() const;
+  inline isl::map unite(isl::basic_map bmap2) const;
+};
+
+// declarations for isl::basic_set
+inline basic_set manage(__isl_take isl_basic_set *ptr);
+inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+class basic_set {
+  friend inline basic_set manage(__isl_take isl_basic_set *ptr);
+  friend inline basic_set manage_copy(__isl_keep isl_basic_set *ptr);
+
+protected:
+  isl_basic_set *ptr = nullptr;
+
+  inline explicit basic_set(__isl_take isl_basic_set *ptr);
+
+public:
+  inline /* implicit */ basic_set();
+  inline /* implicit */ basic_set(const basic_set &obj);
+  inline /* implicit */ basic_set(isl::point pnt);
+  inline explicit basic_set(isl::ctx ctx, const std::string &str);
+  inline basic_set &operator=(basic_set obj);
+  inline ~basic_set();
+  inline __isl_give isl_basic_set *copy() const &;
+  inline __isl_give isl_basic_set *copy() && = delete;
+  inline __isl_keep isl_basic_set *get() const;
+  inline __isl_give isl_basic_set *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::basic_set affine_hull() const;
+  inline isl::basic_set apply(isl::basic_map bmap) const;
+  inline isl::basic_set detect_equalities() const;
+  inline isl::val dim_max_val(int pos) const;
+  inline isl::basic_set flatten() const;
+  inline isl::basic_set gist(isl::basic_set context) const;
+  inline isl::basic_set intersect(isl::basic_set bset2) const;
+  inline isl::basic_set intersect_params(isl::basic_set bset2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const isl::basic_set &bset2) const;
+  inline bool is_subset(const isl::basic_set &bset2) const;
+  inline bool is_wrapping() const;
+  inline isl::set lexmax() const;
+  inline isl::set lexmin() const;
+  inline isl::basic_set params() const;
+  inline isl::basic_set sample() const;
+  inline isl::point sample_point() const;
+  inline isl::set unite(isl::basic_set bset2) const;
+};
+
+// declarations for isl::fixed_box
+inline fixed_box manage(__isl_take isl_fixed_box *ptr);
+inline fixed_box manage_copy(__isl_keep isl_fixed_box *ptr);
+
+class fixed_box {
+  friend inline fixed_box manage(__isl_take isl_fixed_box *ptr);
+  friend inline fixed_box manage_copy(__isl_keep isl_fixed_box *ptr);
+
+protected:
+  isl_fixed_box *ptr = nullptr;
+
+  inline explicit fixed_box(__isl_take isl_fixed_box *ptr);
+
+public:
+  inline /* implicit */ fixed_box();
+  inline /* implicit */ fixed_box(const fixed_box &obj);
+  inline fixed_box &operator=(fixed_box obj);
+  inline ~fixed_box();
+  inline __isl_give isl_fixed_box *copy() const &;
+  inline __isl_give isl_fixed_box *copy() && = delete;
+  inline __isl_keep isl_fixed_box *get() const;
+  inline __isl_give isl_fixed_box *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::multi_aff offset() const;
+  inline isl::multi_aff get_offset() const;
+  inline isl::multi_val size() const;
+  inline isl::multi_val get_size() const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline bool is_valid() const;
+};
+
+// declarations for isl::id
+inline id manage(__isl_take isl_id *ptr);
+inline id manage_copy(__isl_keep isl_id *ptr);
+
+class id {
+  friend inline id manage(__isl_take isl_id *ptr);
+  friend inline id manage_copy(__isl_keep isl_id *ptr);
+
+protected:
+  isl_id *ptr = nullptr;
+
+  inline explicit id(__isl_take isl_id *ptr);
+
+public:
+  inline /* implicit */ id();
+  inline /* implicit */ id(const id &obj);
+  inline explicit id(isl::ctx ctx, const std::string &str);
+  inline id &operator=(id obj);
+  inline ~id();
+  inline __isl_give isl_id *copy() const &;
+  inline __isl_give isl_id *copy() && = delete;
+  inline __isl_keep isl_id *get() const;
+  inline __isl_give isl_id *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline std::string name() const;
+  inline std::string get_name() const;
+};
+
+// declarations for isl::id_list
+inline id_list manage(__isl_take isl_id_list *ptr);
+inline id_list manage_copy(__isl_keep isl_id_list *ptr);
+
+class id_list {
+  friend inline id_list manage(__isl_take isl_id_list *ptr);
+  friend inline id_list manage_copy(__isl_keep isl_id_list *ptr);
+
+protected:
+  isl_id_list *ptr = nullptr;
+
+  inline explicit id_list(__isl_take isl_id_list *ptr);
+
+public:
+  inline /* implicit */ id_list();
+  inline /* implicit */ id_list(const id_list &obj);
+  inline explicit id_list(isl::ctx ctx, int n);
+  inline explicit id_list(isl::id el);
+  inline id_list &operator=(id_list obj);
+  inline ~id_list();
+  inline __isl_give isl_id_list *copy() const &;
+  inline __isl_give isl_id_list *copy() && = delete;
+  inline __isl_keep isl_id_list *get() const;
+  inline __isl_give isl_id_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::id_list add(isl::id el) const;
+  inline isl::id_list add(const std::string &el) const;
+  inline isl::id_list clear() const;
+  inline isl::id_list concat(isl::id_list list2) const;
+  inline void foreach(const std::function<void(isl::id)> &fn) const;
+  inline isl::id at(int index) const;
+  inline isl::id get_at(int index) const;
+  inline unsigned size() const;
+};
+
+// declarations for isl::map
+inline map manage(__isl_take isl_map *ptr);
+inline map manage_copy(__isl_keep isl_map *ptr);
+
+class map {
+  friend inline map manage(__isl_take isl_map *ptr);
+  friend inline map manage_copy(__isl_keep isl_map *ptr);
+
+protected:
+  isl_map *ptr = nullptr;
+
+  inline explicit map(__isl_take isl_map *ptr);
+
+public:
+  inline /* implicit */ map();
+  inline /* implicit */ map(const map &obj);
+  inline /* implicit */ map(isl::basic_map bmap);
+  inline explicit map(isl::ctx ctx, const std::string &str);
+  inline map &operator=(map obj);
+  inline ~map();
+  inline __isl_give isl_map *copy() const &;
+  inline __isl_give isl_map *copy() && = delete;
+  inline __isl_keep isl_map *get() const;
+  inline __isl_give isl_map *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::basic_map affine_hull() const;
+  inline isl::map apply_domain(isl::map map2) const;
+  inline isl::map apply_range(isl::map map2) const;
+  inline isl::set bind_domain(isl::multi_id tuple) const;
+  inline isl::set bind_range(isl::multi_id tuple) const;
+  inline isl::map coalesce() const;
+  inline isl::map complement() const;
+  inline isl::map curry() const;
+  inline isl::set deltas() const;
+  inline isl::map detect_equalities() const;
+  inline isl::set domain() const;
+  inline isl::map domain_factor_domain() const;
+  inline isl::map domain_factor_range() const;
+  inline isl::map domain_product(isl::map map2) const;
+  static inline isl::map empty(isl::space space);
+  inline isl::map factor_domain() const;
+  inline isl::map factor_range() const;
+  inline isl::map flatten() const;
+  inline isl::map flatten_domain() const;
+  inline isl::map flatten_range() const;
+  inline void foreach_basic_map(const std::function<void(isl::basic_map)> &fn) const;
+  inline isl::fixed_box range_simple_fixed_box_hull() const;
+  inline isl::fixed_box get_range_simple_fixed_box_hull() const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::map gist(isl::map context) const;
+  inline isl::map gist_domain(isl::set context) const;
+  inline isl::map intersect(isl::map map2) const;
+  inline isl::map intersect_domain(isl::set set) const;
+  inline isl::map intersect_params(isl::set params) const;
+  inline isl::map intersect_range(isl::set set) const;
+  inline bool is_bijective() const;
+  inline bool is_disjoint(const isl::map &map2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const isl::map &map2) const;
+  inline bool is_injective() const;
+  inline bool is_single_valued() const;
+  inline bool is_strict_subset(const isl::map &map2) const;
+  inline bool is_subset(const isl::map &map2) const;
+  inline isl::map lexmax() const;
+  inline isl::pw_multi_aff lexmax_pw_multi_aff() const;
+  inline isl::map lexmin() const;
+  inline isl::pw_multi_aff lexmin_pw_multi_aff() const;
+  inline isl::map lower_bound(isl::multi_pw_aff lower) const;
+  inline isl::map lower_bound(isl::multi_val lower) const;
+  inline isl::basic_map polyhedral_hull() const;
+  inline isl::map preimage_domain(isl::multi_aff ma) const;
+  inline isl::map preimage_domain(isl::multi_pw_aff mpa) const;
+  inline isl::map preimage_domain(isl::pw_multi_aff pma) const;
+  inline isl::map preimage_range(isl::multi_aff ma) const;
+  inline isl::map preimage_range(isl::pw_multi_aff pma) const;
+  inline isl::map project_out_all_params() const;
+  inline isl::set range() const;
+  inline isl::map range_factor_domain() const;
+  inline isl::map range_factor_range() const;
+  inline isl::map range_product(isl::map map2) const;
+  inline isl::map range_reverse() const;
+  inline isl::map reverse() const;
+  inline isl::basic_map sample() const;
+  inline isl::map subtract(isl::map map2) const;
+  inline isl::map uncurry() const;
+  inline isl::map unite(isl::map map2) const;
+  static inline isl::map universe(isl::space space);
+  inline isl::basic_map unshifted_simple_hull() const;
+  inline isl::map upper_bound(isl::multi_pw_aff upper) const;
+  inline isl::map upper_bound(isl::multi_val upper) const;
+  inline isl::set wrap() const;
+};
+
+// declarations for isl::multi_aff
+inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+class multi_aff {
+  friend inline multi_aff manage(__isl_take isl_multi_aff *ptr);
+  friend inline multi_aff manage_copy(__isl_keep isl_multi_aff *ptr);
+
+protected:
+  isl_multi_aff *ptr = nullptr;
+
+  inline explicit multi_aff(__isl_take isl_multi_aff *ptr);
+
+public:
+  inline /* implicit */ multi_aff();
+  inline /* implicit */ multi_aff(const multi_aff &obj);
+  inline /* implicit */ multi_aff(isl::aff aff);
+  inline explicit multi_aff(isl::space space, isl::aff_list list);
+  inline explicit multi_aff(isl::ctx ctx, const std::string &str);
+  inline multi_aff &operator=(multi_aff obj);
+  inline ~multi_aff();
+  inline __isl_give isl_multi_aff *copy() const &;
+  inline __isl_give isl_multi_aff *copy() && = delete;
+  inline __isl_keep isl_multi_aff *get() const;
+  inline __isl_give isl_multi_aff *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::multi_aff add(isl::multi_aff multi2) const;
+  inline isl::multi_aff add_constant(isl::multi_val mv) const;
+  inline isl::multi_aff add_constant(isl::val v) const;
+  inline isl::multi_aff add_constant(long v) const;
+  inline isl::basic_set bind(isl::multi_id tuple) const;
+  inline isl::multi_aff bind_domain(isl::multi_id tuple) const;
+  inline isl::multi_aff bind_domain_wrapped_domain(isl::multi_id tuple) const;
+  static inline isl::multi_aff domain_map(isl::space space);
+  inline isl::multi_aff flat_range_product(isl::multi_aff multi2) const;
+  inline isl::multi_aff floor() const;
+  inline isl::aff at(int pos) const;
+  inline isl::aff get_at(int pos) const;
+  inline isl::multi_val constant_multi_val() const;
+  inline isl::multi_val get_constant_multi_val() const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::multi_aff gist(isl::set context) const;
+  inline isl::multi_aff identity() const;
+  static inline isl::multi_aff identity_on_domain(isl::space space);
+  inline bool involves_locals() const;
+  inline isl::multi_aff neg() const;
+  inline bool plain_is_equal(const isl::multi_aff &multi2) const;
+  inline isl::multi_aff product(isl::multi_aff multi2) const;
+  inline isl::multi_aff pullback(isl::multi_aff ma2) const;
+  static inline isl::multi_aff range_map(isl::space space);
+  inline isl::multi_aff range_product(isl::multi_aff multi2) const;
+  inline isl::multi_aff scale(isl::multi_val mv) const;
+  inline isl::multi_aff scale(isl::val v) const;
+  inline isl::multi_aff scale(long v) const;
+  inline isl::multi_aff scale_down(isl::multi_val mv) const;
+  inline isl::multi_aff scale_down(isl::val v) const;
+  inline isl::multi_aff scale_down(long v) const;
+  inline isl::multi_aff set_at(int pos, isl::aff el) const;
+  inline unsigned size() const;
+  inline isl::multi_aff sub(isl::multi_aff multi2) const;
+  static inline isl::multi_aff zero(isl::space space);
+};
+
+// declarations for isl::multi_id
+inline multi_id manage(__isl_take isl_multi_id *ptr);
+inline multi_id manage_copy(__isl_keep isl_multi_id *ptr);
+
+class multi_id {
+  friend inline multi_id manage(__isl_take isl_multi_id *ptr);
+  friend inline multi_id manage_copy(__isl_keep isl_multi_id *ptr);
+
+protected:
+  isl_multi_id *ptr = nullptr;
+
+  inline explicit multi_id(__isl_take isl_multi_id *ptr);
+
+public:
+  inline /* implicit */ multi_id();
+  inline /* implicit */ multi_id(const multi_id &obj);
+  inline explicit multi_id(isl::space space, isl::id_list list);
+  inline explicit multi_id(isl::ctx ctx, const std::string &str);
+  inline multi_id &operator=(multi_id obj);
+  inline ~multi_id();
+  inline __isl_give isl_multi_id *copy() const &;
+  inline __isl_give isl_multi_id *copy() && = delete;
+  inline __isl_keep isl_multi_id *get() const;
+  inline __isl_give isl_multi_id *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::multi_id flat_range_product(isl::multi_id multi2) const;
+  inline isl::id at(int pos) const;
+  inline isl::id get_at(int pos) const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline bool plain_is_equal(const isl::multi_id &multi2) const;
+  inline isl::multi_id range_product(isl::multi_id multi2) const;
+  inline isl::multi_id set_at(int pos, isl::id el) const;
+  inline isl::multi_id set_at(int pos, const std::string &el) const;
+  inline unsigned size() const;
+};
+
+// declarations for isl::multi_pw_aff
+inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+class multi_pw_aff {
+  friend inline multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr);
+  friend inline multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr);
+
+protected:
+  isl_multi_pw_aff *ptr = nullptr;
+
+  inline explicit multi_pw_aff(__isl_take isl_multi_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_pw_aff();
+  inline /* implicit */ multi_pw_aff(const multi_pw_aff &obj);
+  inline /* implicit */ multi_pw_aff(isl::multi_aff ma);
+  inline /* implicit */ multi_pw_aff(isl::pw_aff pa);
+  inline explicit multi_pw_aff(isl::space space, isl::pw_aff_list list);
+  inline /* implicit */ multi_pw_aff(isl::pw_multi_aff pma);
+  inline explicit multi_pw_aff(isl::ctx ctx, const std::string &str);
+  inline multi_pw_aff &operator=(multi_pw_aff obj);
+  inline ~multi_pw_aff();
+  inline __isl_give isl_multi_pw_aff *copy() const &;
+  inline __isl_give isl_multi_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_pw_aff *get() const;
+  inline __isl_give isl_multi_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::multi_pw_aff add(isl::multi_pw_aff multi2) const;
+  inline isl::multi_pw_aff add_constant(isl::multi_val mv) const;
+  inline isl::multi_pw_aff add_constant(isl::val v) const;
+  inline isl::multi_pw_aff add_constant(long v) const;
+  inline isl::set bind(isl::multi_id tuple) const;
+  inline isl::multi_pw_aff bind_domain(isl::multi_id tuple) const;
+  inline isl::multi_pw_aff bind_domain_wrapped_domain(isl::multi_id tuple) const;
+  inline isl::multi_pw_aff coalesce() const;
+  inline isl::set domain() const;
+  inline isl::multi_pw_aff flat_range_product(isl::multi_pw_aff multi2) const;
+  inline isl::pw_aff at(int pos) const;
+  inline isl::pw_aff get_at(int pos) const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::multi_pw_aff gist(isl::set set) const;
+  inline isl::multi_pw_aff identity() const;
+  static inline isl::multi_pw_aff identity_on_domain(isl::space space);
+  inline isl::multi_pw_aff intersect_domain(isl::set domain) const;
+  inline isl::multi_pw_aff intersect_params(isl::set set) const;
+  inline bool involves_param(const isl::id &id) const;
+  inline bool involves_param(const std::string &id) const;
+  inline bool involves_param(const isl::id_list &list) const;
+  inline isl::multi_pw_aff neg() const;
+  inline bool plain_is_equal(const isl::multi_pw_aff &multi2) const;
+  inline isl::multi_pw_aff product(isl::multi_pw_aff multi2) const;
+  inline isl::multi_pw_aff pullback(isl::multi_aff ma) const;
+  inline isl::multi_pw_aff pullback(isl::multi_pw_aff mpa2) const;
+  inline isl::multi_pw_aff pullback(isl::pw_multi_aff pma) const;
+  inline isl::multi_pw_aff range_product(isl::multi_pw_aff multi2) const;
+  inline isl::multi_pw_aff scale(isl::multi_val mv) const;
+  inline isl::multi_pw_aff scale(isl::val v) const;
+  inline isl::multi_pw_aff scale(long v) const;
+  inline isl::multi_pw_aff scale_down(isl::multi_val mv) const;
+  inline isl::multi_pw_aff scale_down(isl::val v) const;
+  inline isl::multi_pw_aff scale_down(long v) const;
+  inline isl::multi_pw_aff set_at(int pos, isl::pw_aff el) const;
+  inline unsigned size() const;
+  inline isl::multi_pw_aff sub(isl::multi_pw_aff multi2) const;
+  static inline isl::multi_pw_aff zero(isl::space space);
+};
+
+// declarations for isl::multi_union_pw_aff
+inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+class multi_union_pw_aff {
+  friend inline multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr);
+  friend inline multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr);
+
+protected:
+  isl_multi_union_pw_aff *ptr = nullptr;
+
+  inline explicit multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ multi_union_pw_aff();
+  inline /* implicit */ multi_union_pw_aff(const multi_union_pw_aff &obj);
+  inline /* implicit */ multi_union_pw_aff(isl::multi_pw_aff mpa);
+  inline /* implicit */ multi_union_pw_aff(isl::union_pw_aff upa);
+  inline explicit multi_union_pw_aff(isl::space space, isl::union_pw_aff_list list);
+  inline explicit multi_union_pw_aff(isl::ctx ctx, const std::string &str);
+  inline multi_union_pw_aff &operator=(multi_union_pw_aff obj);
+  inline ~multi_union_pw_aff();
+  inline __isl_give isl_multi_union_pw_aff *copy() const &;
+  inline __isl_give isl_multi_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_multi_union_pw_aff *get() const;
+  inline __isl_give isl_multi_union_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::multi_union_pw_aff add(isl::multi_union_pw_aff multi2) const;
+  inline isl::union_set bind(isl::multi_id tuple) const;
+  inline isl::multi_union_pw_aff coalesce() const;
+  inline isl::union_set domain() const;
+  inline isl::multi_union_pw_aff flat_range_product(isl::multi_union_pw_aff multi2) const;
+  inline isl::union_pw_aff at(int pos) const;
+  inline isl::union_pw_aff get_at(int pos) const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::multi_union_pw_aff gist(isl::union_set context) const;
+  inline isl::multi_union_pw_aff intersect_domain(isl::union_set uset) const;
+  inline isl::multi_union_pw_aff intersect_params(isl::set params) const;
+  inline isl::multi_union_pw_aff neg() const;
+  inline bool plain_is_equal(const isl::multi_union_pw_aff &multi2) const;
+  inline isl::multi_union_pw_aff pullback(isl::union_pw_multi_aff upma) const;
+  inline isl::multi_union_pw_aff range_product(isl::multi_union_pw_aff multi2) const;
+  inline isl::multi_union_pw_aff scale(isl::multi_val mv) const;
+  inline isl::multi_union_pw_aff scale(isl::val v) const;
+  inline isl::multi_union_pw_aff scale(long v) const;
+  inline isl::multi_union_pw_aff scale_down(isl::multi_val mv) const;
+  inline isl::multi_union_pw_aff scale_down(isl::val v) const;
+  inline isl::multi_union_pw_aff scale_down(long v) const;
+  inline isl::multi_union_pw_aff set_at(int pos, isl::union_pw_aff el) const;
+  inline unsigned size() const;
+  inline isl::multi_union_pw_aff sub(isl::multi_union_pw_aff multi2) const;
+  inline isl::multi_union_pw_aff union_add(isl::multi_union_pw_aff mupa2) const;
+  static inline isl::multi_union_pw_aff zero(isl::space space);
+};
+
+// declarations for isl::multi_val
+inline multi_val manage(__isl_take isl_multi_val *ptr);
+inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+class multi_val {
+  friend inline multi_val manage(__isl_take isl_multi_val *ptr);
+  friend inline multi_val manage_copy(__isl_keep isl_multi_val *ptr);
+
+protected:
+  isl_multi_val *ptr = nullptr;
+
+  inline explicit multi_val(__isl_take isl_multi_val *ptr);
+
+public:
+  inline /* implicit */ multi_val();
+  inline /* implicit */ multi_val(const multi_val &obj);
+  inline explicit multi_val(isl::space space, isl::val_list list);
+  inline explicit multi_val(isl::ctx ctx, const std::string &str);
+  inline multi_val &operator=(multi_val obj);
+  inline ~multi_val();
+  inline __isl_give isl_multi_val *copy() const &;
+  inline __isl_give isl_multi_val *copy() && = delete;
+  inline __isl_keep isl_multi_val *get() const;
+  inline __isl_give isl_multi_val *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::multi_val add(isl::multi_val multi2) const;
+  inline isl::multi_val add(isl::val v) const;
+  inline isl::multi_val add(long v) const;
+  inline isl::multi_val flat_range_product(isl::multi_val multi2) const;
+  inline isl::val at(int pos) const;
+  inline isl::val get_at(int pos) const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::multi_val neg() const;
+  inline bool plain_is_equal(const isl::multi_val &multi2) const;
+  inline isl::multi_val product(isl::multi_val multi2) const;
+  inline isl::multi_val range_product(isl::multi_val multi2) const;
+  inline isl::multi_val scale(isl::multi_val mv) const;
+  inline isl::multi_val scale(isl::val v) const;
+  inline isl::multi_val scale(long v) const;
+  inline isl::multi_val scale_down(isl::multi_val mv) const;
+  inline isl::multi_val scale_down(isl::val v) const;
+  inline isl::multi_val scale_down(long v) const;
+  inline isl::multi_val set_at(int pos, isl::val el) const;
+  inline isl::multi_val set_at(int pos, long el) const;
+  inline unsigned size() const;
+  inline isl::multi_val sub(isl::multi_val multi2) const;
+  static inline isl::multi_val zero(isl::space space);
+};
+
+// declarations for isl::point
+inline point manage(__isl_take isl_point *ptr);
+inline point manage_copy(__isl_keep isl_point *ptr);
+
+class point {
+  friend inline point manage(__isl_take isl_point *ptr);
+  friend inline point manage_copy(__isl_keep isl_point *ptr);
+
+protected:
+  isl_point *ptr = nullptr;
+
+  inline explicit point(__isl_take isl_point *ptr);
+
+public:
+  inline /* implicit */ point();
+  inline /* implicit */ point(const point &obj);
+  inline point &operator=(point obj);
+  inline ~point();
+  inline __isl_give isl_point *copy() const &;
+  inline __isl_give isl_point *copy() && = delete;
+  inline __isl_keep isl_point *get() const;
+  inline __isl_give isl_point *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::multi_val multi_val() const;
+  inline isl::multi_val get_multi_val() const;
+};
+
+// declarations for isl::pw_aff
+inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+class pw_aff {
+  friend inline pw_aff manage(__isl_take isl_pw_aff *ptr);
+  friend inline pw_aff manage_copy(__isl_keep isl_pw_aff *ptr);
+
+protected:
+  isl_pw_aff *ptr = nullptr;
+
+  inline explicit pw_aff(__isl_take isl_pw_aff *ptr);
+
+public:
+  inline /* implicit */ pw_aff();
+  inline /* implicit */ pw_aff(const pw_aff &obj);
+  inline /* implicit */ pw_aff(isl::aff aff);
+  inline explicit pw_aff(isl::ctx ctx, const std::string &str);
+  inline pw_aff &operator=(pw_aff obj);
+  inline ~pw_aff();
+  inline __isl_give isl_pw_aff *copy() const &;
+  inline __isl_give isl_pw_aff *copy() && = delete;
+  inline __isl_keep isl_pw_aff *get() const;
+  inline __isl_give isl_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::pw_aff add(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff add_constant(isl::val v) const;
+  inline isl::pw_aff add_constant(long v) const;
+  inline isl::aff as_aff() const;
+  inline isl::set bind(isl::id id) const;
+  inline isl::set bind(const std::string &id) const;
+  inline isl::pw_aff bind_domain(isl::multi_id tuple) const;
+  inline isl::pw_aff bind_domain_wrapped_domain(isl::multi_id tuple) const;
+  inline isl::pw_aff ceil() const;
+  inline isl::pw_aff coalesce() const;
+  inline isl::pw_aff cond(isl::pw_aff pwaff_true, isl::pw_aff pwaff_false) const;
+  inline isl::pw_aff div(isl::pw_aff pa2) const;
+  inline isl::set domain() const;
+  inline isl::set eq_set(isl::pw_aff pwaff2) const;
+  inline isl::val eval(isl::point pnt) const;
+  inline isl::pw_aff floor() const;
+  inline isl::set ge_set(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff gist(isl::set context) const;
+  inline isl::set gt_set(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff intersect_domain(isl::set set) const;
+  inline isl::pw_aff intersect_params(isl::set set) const;
+  inline bool isa_aff() const;
+  inline isl::set le_set(isl::pw_aff pwaff2) const;
+  inline isl::set lt_set(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff max(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff min(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff mod(isl::val mod) const;
+  inline isl::pw_aff mod(long mod) const;
+  inline isl::pw_aff mul(isl::pw_aff pwaff2) const;
+  inline isl::set ne_set(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff neg() const;
+  static inline isl::pw_aff param_on_domain(isl::set domain, isl::id id);
+  inline isl::pw_aff pullback(isl::multi_aff ma) const;
+  inline isl::pw_aff pullback(isl::multi_pw_aff mpa) const;
+  inline isl::pw_aff pullback(isl::pw_multi_aff pma) const;
+  inline isl::pw_aff scale(isl::val v) const;
+  inline isl::pw_aff scale(long v) const;
+  inline isl::pw_aff scale_down(isl::val f) const;
+  inline isl::pw_aff scale_down(long f) const;
+  inline isl::pw_aff sub(isl::pw_aff pwaff2) const;
+  inline isl::pw_aff subtract_domain(isl::set set) const;
+  inline isl::pw_aff tdiv_q(isl::pw_aff pa2) const;
+  inline isl::pw_aff tdiv_r(isl::pw_aff pa2) const;
+  inline isl::pw_aff union_add(isl::pw_aff pwaff2) const;
+};
+
+// declarations for isl::pw_aff_list
+inline pw_aff_list manage(__isl_take isl_pw_aff_list *ptr);
+inline pw_aff_list manage_copy(__isl_keep isl_pw_aff_list *ptr);
+
+class pw_aff_list {
+  friend inline pw_aff_list manage(__isl_take isl_pw_aff_list *ptr);
+  friend inline pw_aff_list manage_copy(__isl_keep isl_pw_aff_list *ptr);
+
+protected:
+  isl_pw_aff_list *ptr = nullptr;
+
+  inline explicit pw_aff_list(__isl_take isl_pw_aff_list *ptr);
+
+public:
+  inline /* implicit */ pw_aff_list();
+  inline /* implicit */ pw_aff_list(const pw_aff_list &obj);
+  inline explicit pw_aff_list(isl::ctx ctx, int n);
+  inline explicit pw_aff_list(isl::pw_aff el);
+  inline pw_aff_list &operator=(pw_aff_list obj);
+  inline ~pw_aff_list();
+  inline __isl_give isl_pw_aff_list *copy() const &;
+  inline __isl_give isl_pw_aff_list *copy() && = delete;
+  inline __isl_keep isl_pw_aff_list *get() const;
+  inline __isl_give isl_pw_aff_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::pw_aff_list add(isl::pw_aff el) const;
+  inline isl::pw_aff_list clear() const;
+  inline isl::pw_aff_list concat(isl::pw_aff_list list2) const;
+  inline void foreach(const std::function<void(isl::pw_aff)> &fn) const;
+  inline isl::pw_aff at(int index) const;
+  inline isl::pw_aff get_at(int index) const;
+  inline unsigned size() const;
+};
+
+// declarations for isl::pw_multi_aff
+inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+class pw_multi_aff {
+  friend inline pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr);
+  friend inline pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr);
+
+protected:
+  isl_pw_multi_aff *ptr = nullptr;
+
+  inline explicit pw_multi_aff(__isl_take isl_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ pw_multi_aff();
+  inline /* implicit */ pw_multi_aff(const pw_multi_aff &obj);
+  inline /* implicit */ pw_multi_aff(isl::multi_aff ma);
+  inline /* implicit */ pw_multi_aff(isl::pw_aff pa);
+  inline explicit pw_multi_aff(isl::ctx ctx, const std::string &str);
+  inline pw_multi_aff &operator=(pw_multi_aff obj);
+  inline ~pw_multi_aff();
+  inline __isl_give isl_pw_multi_aff *copy() const &;
+  inline __isl_give isl_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_pw_multi_aff *get() const;
+  inline __isl_give isl_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::pw_multi_aff add(isl::pw_multi_aff pma2) const;
+  inline isl::pw_multi_aff add_constant(isl::multi_val mv) const;
+  inline isl::pw_multi_aff add_constant(isl::val v) const;
+  inline isl::pw_multi_aff add_constant(long v) const;
+  inline isl::multi_aff as_multi_aff() const;
+  inline isl::pw_multi_aff bind_domain(isl::multi_id tuple) const;
+  inline isl::pw_multi_aff bind_domain_wrapped_domain(isl::multi_id tuple) const;
+  inline isl::pw_multi_aff coalesce() const;
+  inline isl::set domain() const;
+  inline isl::pw_multi_aff flat_range_product(isl::pw_multi_aff pma2) const;
+  inline void foreach_piece(const std::function<void(isl::set, isl::multi_aff)> &fn) const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::pw_multi_aff gist(isl::set set) const;
+  inline isl::pw_multi_aff intersect_domain(isl::set set) const;
+  inline isl::pw_multi_aff intersect_params(isl::set set) const;
+  inline bool isa_multi_aff() const;
+  inline unsigned n_piece() const;
+  inline isl::pw_multi_aff product(isl::pw_multi_aff pma2) const;
+  inline isl::pw_multi_aff pullback(isl::multi_aff ma) const;
+  inline isl::pw_multi_aff pullback(isl::pw_multi_aff pma2) const;
+  inline isl::pw_multi_aff range_factor_domain() const;
+  inline isl::pw_multi_aff range_factor_range() const;
+  inline isl::pw_multi_aff range_product(isl::pw_multi_aff pma2) const;
+  inline isl::pw_multi_aff scale(isl::val v) const;
+  inline isl::pw_multi_aff scale(long v) const;
+  inline isl::pw_multi_aff scale_down(isl::val v) const;
+  inline isl::pw_multi_aff scale_down(long v) const;
+  inline isl::pw_multi_aff sub(isl::pw_multi_aff pma2) const;
+  inline isl::pw_multi_aff subtract_domain(isl::set set) const;
+  inline isl::pw_multi_aff union_add(isl::pw_multi_aff pma2) const;
+  static inline isl::pw_multi_aff zero(isl::space space);
+};
+
+// declarations for isl::pw_multi_aff_list
+inline pw_multi_aff_list manage(__isl_take isl_pw_multi_aff_list *ptr);
+inline pw_multi_aff_list manage_copy(__isl_keep isl_pw_multi_aff_list *ptr);
+
+class pw_multi_aff_list {
+  friend inline pw_multi_aff_list manage(__isl_take isl_pw_multi_aff_list *ptr);
+  friend inline pw_multi_aff_list manage_copy(__isl_keep isl_pw_multi_aff_list *ptr);
+
+protected:
+  isl_pw_multi_aff_list *ptr = nullptr;
+
+  inline explicit pw_multi_aff_list(__isl_take isl_pw_multi_aff_list *ptr);
+
+public:
+  inline /* implicit */ pw_multi_aff_list();
+  inline /* implicit */ pw_multi_aff_list(const pw_multi_aff_list &obj);
+  inline explicit pw_multi_aff_list(isl::ctx ctx, int n);
+  inline explicit pw_multi_aff_list(isl::pw_multi_aff el);
+  inline pw_multi_aff_list &operator=(pw_multi_aff_list obj);
+  inline ~pw_multi_aff_list();
+  inline __isl_give isl_pw_multi_aff_list *copy() const &;
+  inline __isl_give isl_pw_multi_aff_list *copy() && = delete;
+  inline __isl_keep isl_pw_multi_aff_list *get() const;
+  inline __isl_give isl_pw_multi_aff_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::pw_multi_aff_list add(isl::pw_multi_aff el) const;
+  inline isl::pw_multi_aff_list clear() const;
+  inline isl::pw_multi_aff_list concat(isl::pw_multi_aff_list list2) const;
+  inline void foreach(const std::function<void(isl::pw_multi_aff)> &fn) const;
+  inline isl::pw_multi_aff at(int index) const;
+  inline isl::pw_multi_aff get_at(int index) const;
+  inline unsigned size() const;
+};
+
+// declarations for isl::schedule
+inline schedule manage(__isl_take isl_schedule *ptr);
+inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+class schedule {
+  friend inline schedule manage(__isl_take isl_schedule *ptr);
+  friend inline schedule manage_copy(__isl_keep isl_schedule *ptr);
+
+protected:
+  isl_schedule *ptr = nullptr;
+
+  inline explicit schedule(__isl_take isl_schedule *ptr);
+
+public:
+  inline /* implicit */ schedule();
+  inline /* implicit */ schedule(const schedule &obj);
+  inline explicit schedule(isl::ctx ctx, const std::string &str);
+  inline schedule &operator=(schedule obj);
+  inline ~schedule();
+  inline __isl_give isl_schedule *copy() const &;
+  inline __isl_give isl_schedule *copy() && = delete;
+  inline __isl_keep isl_schedule *get() const;
+  inline __isl_give isl_schedule *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  static inline isl::schedule from_domain(isl::union_set domain);
+  inline isl::union_map map() const;
+  inline isl::union_map get_map() const;
+  inline isl::schedule_node root() const;
+  inline isl::schedule_node get_root() const;
+  inline isl::schedule pullback(isl::union_pw_multi_aff upma) const;
+};
+
+// declarations for isl::schedule_constraints
+inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+class schedule_constraints {
+  friend inline schedule_constraints manage(__isl_take isl_schedule_constraints *ptr);
+  friend inline schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr);
+
+protected:
+  isl_schedule_constraints *ptr = nullptr;
+
+  inline explicit schedule_constraints(__isl_take isl_schedule_constraints *ptr);
+
+public:
+  inline /* implicit */ schedule_constraints();
+  inline /* implicit */ schedule_constraints(const schedule_constraints &obj);
+  inline explicit schedule_constraints(isl::ctx ctx, const std::string &str);
+  inline schedule_constraints &operator=(schedule_constraints obj);
+  inline ~schedule_constraints();
+  inline __isl_give isl_schedule_constraints *copy() const &;
+  inline __isl_give isl_schedule_constraints *copy() && = delete;
+  inline __isl_keep isl_schedule_constraints *get() const;
+  inline __isl_give isl_schedule_constraints *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::schedule compute_schedule() const;
+  inline isl::union_map coincidence() const;
+  inline isl::union_map get_coincidence() const;
+  inline isl::union_map conditional_validity() const;
+  inline isl::union_map get_conditional_validity() const;
+  inline isl::union_map conditional_validity_condition() const;
+  inline isl::union_map get_conditional_validity_condition() const;
+  inline isl::set context() const;
+  inline isl::set get_context() const;
+  inline isl::union_set domain() const;
+  inline isl::union_set get_domain() const;
+  inline isl::union_map proximity() const;
+  inline isl::union_map get_proximity() const;
+  inline isl::union_map validity() const;
+  inline isl::union_map get_validity() const;
+  static inline isl::schedule_constraints on_domain(isl::union_set domain);
+  inline isl::schedule_constraints set_coincidence(isl::union_map coincidence) const;
+  inline isl::schedule_constraints set_conditional_validity(isl::union_map condition, isl::union_map validity) const;
+  inline isl::schedule_constraints set_context(isl::set context) const;
+  inline isl::schedule_constraints set_proximity(isl::union_map proximity) const;
+  inline isl::schedule_constraints set_validity(isl::union_map validity) const;
+};
+
+// declarations for isl::schedule_node
+inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+class schedule_node {
+  friend inline schedule_node manage(__isl_take isl_schedule_node *ptr);
+  friend inline schedule_node manage_copy(__isl_keep isl_schedule_node *ptr);
+
+protected:
+  isl_schedule_node *ptr = nullptr;
+
+  inline explicit schedule_node(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node();
+  inline /* implicit */ schedule_node(const schedule_node &obj);
+  inline schedule_node &operator=(schedule_node obj);
+  inline ~schedule_node();
+  inline __isl_give isl_schedule_node *copy() const &;
+  inline __isl_give isl_schedule_node *copy() && = delete;
+  inline __isl_keep isl_schedule_node *get() const;
+  inline __isl_give isl_schedule_node *release();
+  inline bool is_null() const;
+private:
+  template <typename T,
+          typename = typename std::enable_if<std::is_same<
+                  const decltype(isl_schedule_node_get_type(NULL)),
+                  const T>::value>::type>
+  inline bool isa_type(T subtype) const;
+public:
+  template <class T> inline bool isa() const;
+  template <class T> inline T as() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::schedule_node ancestor(int generation) const;
+  inline isl::schedule_node child(int pos) const;
+  inline bool every_descendant(const std::function<bool(isl::schedule_node)> &test) const;
+  inline isl::schedule_node first_child() const;
+  inline void foreach_ancestor_top_down(const std::function<void(isl::schedule_node)> &fn) const;
+  inline void foreach_descendant_top_down(const std::function<bool(isl::schedule_node)> &fn) const;
+  static inline isl::schedule_node from_domain(isl::union_set domain);
+  static inline isl::schedule_node from_extension(isl::union_map extension);
+  inline unsigned ancestor_child_position(const isl::schedule_node &ancestor) const;
+  inline unsigned get_ancestor_child_position(const isl::schedule_node &ancestor) const;
+  inline unsigned child_position() const;
+  inline unsigned get_child_position() const;
+  inline isl::multi_union_pw_aff prefix_schedule_multi_union_pw_aff() const;
+  inline isl::multi_union_pw_aff get_prefix_schedule_multi_union_pw_aff() const;
+  inline isl::union_map prefix_schedule_union_map() const;
+  inline isl::union_map get_prefix_schedule_union_map() const;
+  inline isl::union_pw_multi_aff prefix_schedule_union_pw_multi_aff() const;
+  inline isl::union_pw_multi_aff get_prefix_schedule_union_pw_multi_aff() const;
+  inline isl::schedule schedule() const;
+  inline isl::schedule get_schedule() const;
+  inline isl::schedule_node shared_ancestor(const isl::schedule_node &node2) const;
+  inline isl::schedule_node get_shared_ancestor(const isl::schedule_node &node2) const;
+  inline unsigned tree_depth() const;
+  inline unsigned get_tree_depth() const;
+  inline isl::schedule_node graft_after(isl::schedule_node graft) const;
+  inline isl::schedule_node graft_before(isl::schedule_node graft) const;
+  inline bool has_children() const;
+  inline bool has_next_sibling() const;
+  inline bool has_parent() const;
+  inline bool has_previous_sibling() const;
+  inline isl::schedule_node insert_context(isl::set context) const;
+  inline isl::schedule_node insert_filter(isl::union_set filter) const;
+  inline isl::schedule_node insert_guard(isl::set context) const;
+  inline isl::schedule_node insert_mark(isl::id mark) const;
+  inline isl::schedule_node insert_mark(const std::string &mark) const;
+  inline isl::schedule_node insert_partial_schedule(isl::multi_union_pw_aff schedule) const;
+  inline isl::schedule_node insert_sequence(isl::union_set_list filters) const;
+  inline isl::schedule_node insert_set(isl::union_set_list filters) const;
+  inline bool is_equal(const isl::schedule_node &node2) const;
+  inline bool is_subtree_anchored() const;
+  inline isl::schedule_node map_descendant_bottom_up(const std::function<isl::schedule_node(isl::schedule_node)> &fn) const;
+  inline unsigned n_children() const;
+  inline isl::schedule_node next_sibling() const;
+  inline isl::schedule_node order_after(isl::union_set filter) const;
+  inline isl::schedule_node order_before(isl::union_set filter) const;
+  inline isl::schedule_node parent() const;
+  inline isl::schedule_node previous_sibling() const;
+  inline isl::schedule_node root() const;
+};
+
+// declarations for isl::schedule_node_band
+
+class schedule_node_band : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_band schedule_node::as<schedule_node_band>() const;
+  static const auto type = isl_schedule_node_band;
+
+protected:
+  inline explicit schedule_node_band(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_band();
+  inline /* implicit */ schedule_node_band(const schedule_node_band &obj);
+  inline schedule_node_band &operator=(schedule_node_band obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::union_set ast_build_options() const;
+  inline isl::union_set get_ast_build_options() const;
+  inline isl::set ast_isolate_option() const;
+  inline isl::set get_ast_isolate_option() const;
+  inline isl::multi_union_pw_aff partial_schedule() const;
+  inline isl::multi_union_pw_aff get_partial_schedule() const;
+  inline bool permutable() const;
+  inline bool get_permutable() const;
+  inline bool member_get_coincident(int pos) const;
+  inline schedule_node_band member_set_coincident(int pos, int coincident) const;
+  inline schedule_node_band mod(isl::multi_val mv) const;
+  inline unsigned n_member() const;
+  inline schedule_node_band scale(isl::multi_val mv) const;
+  inline schedule_node_band scale_down(isl::multi_val mv) const;
+  inline schedule_node_band set_ast_build_options(isl::union_set options) const;
+  inline schedule_node_band set_permutable(int permutable) const;
+  inline schedule_node_band shift(isl::multi_union_pw_aff shift) const;
+  inline schedule_node_band split(int pos) const;
+  inline schedule_node_band tile(isl::multi_val sizes) const;
+  inline schedule_node_band member_set_ast_loop_default(int pos) const;
+  inline schedule_node_band member_set_ast_loop_atomic(int pos) const;
+  inline schedule_node_band member_set_ast_loop_unroll(int pos) const;
+  inline schedule_node_band member_set_ast_loop_separate(int pos) const;
+};
+
+// declarations for isl::schedule_node_context
+
+class schedule_node_context : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_context schedule_node::as<schedule_node_context>() const;
+  static const auto type = isl_schedule_node_context;
+
+protected:
+  inline explicit schedule_node_context(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_context();
+  inline /* implicit */ schedule_node_context(const schedule_node_context &obj);
+  inline schedule_node_context &operator=(schedule_node_context obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::set context() const;
+  inline isl::set get_context() const;
+};
+
+// declarations for isl::schedule_node_domain
+
+class schedule_node_domain : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_domain schedule_node::as<schedule_node_domain>() const;
+  static const auto type = isl_schedule_node_domain;
+
+protected:
+  inline explicit schedule_node_domain(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_domain();
+  inline /* implicit */ schedule_node_domain(const schedule_node_domain &obj);
+  inline schedule_node_domain &operator=(schedule_node_domain obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::union_set domain() const;
+  inline isl::union_set get_domain() const;
+};
+
+// declarations for isl::schedule_node_expansion
+
+class schedule_node_expansion : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_expansion schedule_node::as<schedule_node_expansion>() const;
+  static const auto type = isl_schedule_node_expansion;
+
+protected:
+  inline explicit schedule_node_expansion(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_expansion();
+  inline /* implicit */ schedule_node_expansion(const schedule_node_expansion &obj);
+  inline schedule_node_expansion &operator=(schedule_node_expansion obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::union_pw_multi_aff contraction() const;
+  inline isl::union_pw_multi_aff get_contraction() const;
+  inline isl::union_map expansion() const;
+  inline isl::union_map get_expansion() const;
+};
+
+// declarations for isl::schedule_node_extension
+
+class schedule_node_extension : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_extension schedule_node::as<schedule_node_extension>() const;
+  static const auto type = isl_schedule_node_extension;
+
+protected:
+  inline explicit schedule_node_extension(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_extension();
+  inline /* implicit */ schedule_node_extension(const schedule_node_extension &obj);
+  inline schedule_node_extension &operator=(schedule_node_extension obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::union_map extension() const;
+  inline isl::union_map get_extension() const;
+};
+
+// declarations for isl::schedule_node_filter
+
+class schedule_node_filter : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_filter schedule_node::as<schedule_node_filter>() const;
+  static const auto type = isl_schedule_node_filter;
+
+protected:
+  inline explicit schedule_node_filter(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_filter();
+  inline /* implicit */ schedule_node_filter(const schedule_node_filter &obj);
+  inline schedule_node_filter &operator=(schedule_node_filter obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::union_set filter() const;
+  inline isl::union_set get_filter() const;
+};
+
+// declarations for isl::schedule_node_guard
+
+class schedule_node_guard : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_guard schedule_node::as<schedule_node_guard>() const;
+  static const auto type = isl_schedule_node_guard;
+
+protected:
+  inline explicit schedule_node_guard(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_guard();
+  inline /* implicit */ schedule_node_guard(const schedule_node_guard &obj);
+  inline schedule_node_guard &operator=(schedule_node_guard obj);
+  inline isl::ctx ctx() const;
+
+  inline isl::set guard() const;
+  inline isl::set get_guard() const;
+};
+
+// declarations for isl::schedule_node_leaf
+
+class schedule_node_leaf : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_leaf schedule_node::as<schedule_node_leaf>() const;
+  static const auto type = isl_schedule_node_leaf;
+
+protected:
+  inline explicit schedule_node_leaf(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_leaf();
+  inline /* implicit */ schedule_node_leaf(const schedule_node_leaf &obj);
+  inline schedule_node_leaf &operator=(schedule_node_leaf obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::schedule_node_mark
+
+class schedule_node_mark : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_mark schedule_node::as<schedule_node_mark>() const;
+  static const auto type = isl_schedule_node_mark;
+
+protected:
+  inline explicit schedule_node_mark(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_mark();
+  inline /* implicit */ schedule_node_mark(const schedule_node_mark &obj);
+  inline schedule_node_mark &operator=(schedule_node_mark obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::schedule_node_sequence
+
+class schedule_node_sequence : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_sequence schedule_node::as<schedule_node_sequence>() const;
+  static const auto type = isl_schedule_node_sequence;
+
+protected:
+  inline explicit schedule_node_sequence(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_sequence();
+  inline /* implicit */ schedule_node_sequence(const schedule_node_sequence &obj);
+  inline schedule_node_sequence &operator=(schedule_node_sequence obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::schedule_node_set
+
+class schedule_node_set : public schedule_node {
+  template <class T>
+  friend bool schedule_node::isa() const;
+  friend schedule_node_set schedule_node::as<schedule_node_set>() const;
+  static const auto type = isl_schedule_node_set;
+
+protected:
+  inline explicit schedule_node_set(__isl_take isl_schedule_node *ptr);
+
+public:
+  inline /* implicit */ schedule_node_set();
+  inline /* implicit */ schedule_node_set(const schedule_node_set &obj);
+  inline schedule_node_set &operator=(schedule_node_set obj);
+  inline isl::ctx ctx() const;
+
+};
+
+// declarations for isl::set
+inline set manage(__isl_take isl_set *ptr);
+inline set manage_copy(__isl_keep isl_set *ptr);
+
+class set {
+  friend inline set manage(__isl_take isl_set *ptr);
+  friend inline set manage_copy(__isl_keep isl_set *ptr);
+
+protected:
+  isl_set *ptr = nullptr;
+
+  inline explicit set(__isl_take isl_set *ptr);
+
+public:
+  inline /* implicit */ set();
+  inline /* implicit */ set(const set &obj);
+  inline /* implicit */ set(isl::basic_set bset);
+  inline /* implicit */ set(isl::point pnt);
+  inline explicit set(isl::ctx ctx, const std::string &str);
+  inline set &operator=(set obj);
+  inline ~set();
+  inline __isl_give isl_set *copy() const &;
+  inline __isl_give isl_set *copy() && = delete;
+  inline __isl_keep isl_set *get() const;
+  inline __isl_give isl_set *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::basic_set affine_hull() const;
+  inline isl::set apply(isl::map map) const;
+  inline isl::set bind(isl::multi_id tuple) const;
+  inline isl::set coalesce() const;
+  inline isl::set complement() const;
+  inline isl::set detect_equalities() const;
+  static inline isl::set empty(isl::space space);
+  inline isl::set flatten() const;
+  inline void foreach_basic_set(const std::function<void(isl::basic_set)> &fn) const;
+  inline void foreach_point(const std::function<void(isl::point)> &fn) const;
+  inline isl::multi_val plain_multi_val_if_fixed() const;
+  inline isl::multi_val get_plain_multi_val_if_fixed() const;
+  inline isl::fixed_box simple_fixed_box_hull() const;
+  inline isl::fixed_box get_simple_fixed_box_hull() const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::val stride(int pos) const;
+  inline isl::val get_stride(int pos) const;
+  inline isl::set gist(isl::set context) const;
+  inline isl::map identity() const;
+  inline isl::pw_aff indicator_function() const;
+  inline isl::set intersect(isl::set set2) const;
+  inline isl::set intersect_params(isl::set params) const;
+  inline bool is_disjoint(const isl::set &set2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const isl::set &set2) const;
+  inline bool is_singleton() const;
+  inline bool is_strict_subset(const isl::set &set2) const;
+  inline bool is_subset(const isl::set &set2) const;
+  inline bool is_wrapping() const;
+  inline isl::set lexmax() const;
+  inline isl::pw_multi_aff lexmax_pw_multi_aff() const;
+  inline isl::set lexmin() const;
+  inline isl::pw_multi_aff lexmin_pw_multi_aff() const;
+  inline isl::set lower_bound(isl::multi_pw_aff lower) const;
+  inline isl::set lower_bound(isl::multi_val lower) const;
+  inline isl::val max_val(const isl::aff &obj) const;
+  inline isl::val min_val(const isl::aff &obj) const;
+  inline isl::set params() const;
+  inline isl::basic_set polyhedral_hull() const;
+  inline isl::set preimage(isl::multi_aff ma) const;
+  inline isl::set preimage(isl::multi_pw_aff mpa) const;
+  inline isl::set preimage(isl::pw_multi_aff pma) const;
+  inline isl::set product(isl::set set2) const;
+  inline isl::set project_out_all_params() const;
+  inline isl::set project_out_param(isl::id id) const;
+  inline isl::set project_out_param(const std::string &id) const;
+  inline isl::set project_out_param(isl::id_list list) const;
+  inline isl::basic_set sample() const;
+  inline isl::point sample_point() const;
+  inline isl::set subtract(isl::set set2) const;
+  inline isl::set unbind_params(isl::multi_id tuple) const;
+  inline isl::map unbind_params_insert_domain(isl::multi_id domain) const;
+  inline isl::set unite(isl::set set2) const;
+  static inline isl::set universe(isl::space space);
+  inline isl::basic_set unshifted_simple_hull() const;
+  inline isl::map unwrap() const;
+  inline isl::set upper_bound(isl::multi_pw_aff upper) const;
+  inline isl::set upper_bound(isl::multi_val upper) const;
+};
+
+// declarations for isl::space
+inline space manage(__isl_take isl_space *ptr);
+inline space manage_copy(__isl_keep isl_space *ptr);
+
+class space {
+  friend inline space manage(__isl_take isl_space *ptr);
+  friend inline space manage_copy(__isl_keep isl_space *ptr);
+
+protected:
+  isl_space *ptr = nullptr;
+
+  inline explicit space(__isl_take isl_space *ptr);
+
+public:
+  inline /* implicit */ space();
+  inline /* implicit */ space(const space &obj);
+  inline space &operator=(space obj);
+  inline ~space();
+  inline __isl_give isl_space *copy() const &;
+  inline __isl_give isl_space *copy() && = delete;
+  inline __isl_keep isl_space *get() const;
+  inline __isl_give isl_space *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::space add_named_tuple(isl::id tuple_id, unsigned int dim) const;
+  inline isl::space add_named_tuple(const std::string &tuple_id, unsigned int dim) const;
+  inline isl::space add_unnamed_tuple(unsigned int dim) const;
+  inline isl::space domain() const;
+  inline isl::space flatten_domain() const;
+  inline isl::space flatten_range() const;
+  inline bool is_equal(const isl::space &space2) const;
+  inline bool is_wrapping() const;
+  inline isl::space map_from_set() const;
+  inline isl::space params() const;
+  inline isl::space range() const;
+  static inline isl::space unit(isl::ctx ctx);
+  inline isl::space unwrap() const;
+  inline isl::space wrap() const;
+};
+
+// declarations for isl::union_access_info
+inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+class union_access_info {
+  friend inline union_access_info manage(__isl_take isl_union_access_info *ptr);
+  friend inline union_access_info manage_copy(__isl_keep isl_union_access_info *ptr);
+
+protected:
+  isl_union_access_info *ptr = nullptr;
+
+  inline explicit union_access_info(__isl_take isl_union_access_info *ptr);
+
+public:
+  inline /* implicit */ union_access_info();
+  inline /* implicit */ union_access_info(const union_access_info &obj);
+  inline explicit union_access_info(isl::union_map sink);
+  inline union_access_info &operator=(union_access_info obj);
+  inline ~union_access_info();
+  inline __isl_give isl_union_access_info *copy() const &;
+  inline __isl_give isl_union_access_info *copy() && = delete;
+  inline __isl_keep isl_union_access_info *get() const;
+  inline __isl_give isl_union_access_info *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_flow compute_flow() const;
+  inline isl::union_access_info set_kill(isl::union_map kill) const;
+  inline isl::union_access_info set_may_source(isl::union_map may_source) const;
+  inline isl::union_access_info set_must_source(isl::union_map must_source) const;
+  inline isl::union_access_info set_schedule(isl::schedule schedule) const;
+  inline isl::union_access_info set_schedule_map(isl::union_map schedule_map) const;
+};
+
+// declarations for isl::union_flow
+inline union_flow manage(__isl_take isl_union_flow *ptr);
+inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+class union_flow {
+  friend inline union_flow manage(__isl_take isl_union_flow *ptr);
+  friend inline union_flow manage_copy(__isl_keep isl_union_flow *ptr);
+
+protected:
+  isl_union_flow *ptr = nullptr;
+
+  inline explicit union_flow(__isl_take isl_union_flow *ptr);
+
+public:
+  inline /* implicit */ union_flow();
+  inline /* implicit */ union_flow(const union_flow &obj);
+  inline union_flow &operator=(union_flow obj);
+  inline ~union_flow();
+  inline __isl_give isl_union_flow *copy() const &;
+  inline __isl_give isl_union_flow *copy() && = delete;
+  inline __isl_keep isl_union_flow *get() const;
+  inline __isl_give isl_union_flow *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_map full_may_dependence() const;
+  inline isl::union_map get_full_may_dependence() const;
+  inline isl::union_map full_must_dependence() const;
+  inline isl::union_map get_full_must_dependence() const;
+  inline isl::union_map may_dependence() const;
+  inline isl::union_map get_may_dependence() const;
+  inline isl::union_map may_no_source() const;
+  inline isl::union_map get_may_no_source() const;
+  inline isl::union_map must_dependence() const;
+  inline isl::union_map get_must_dependence() const;
+  inline isl::union_map must_no_source() const;
+  inline isl::union_map get_must_no_source() const;
+};
+
+// declarations for isl::union_map
+inline union_map manage(__isl_take isl_union_map *ptr);
+inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+class union_map {
+  friend inline union_map manage(__isl_take isl_union_map *ptr);
+  friend inline union_map manage_copy(__isl_keep isl_union_map *ptr);
+
+protected:
+  isl_union_map *ptr = nullptr;
+
+  inline explicit union_map(__isl_take isl_union_map *ptr);
+
+public:
+  inline /* implicit */ union_map();
+  inline /* implicit */ union_map(const union_map &obj);
+  inline /* implicit */ union_map(isl::basic_map bmap);
+  inline /* implicit */ union_map(isl::map map);
+  inline explicit union_map(isl::ctx ctx, const std::string &str);
+  inline union_map &operator=(union_map obj);
+  inline ~union_map();
+  inline __isl_give isl_union_map *copy() const &;
+  inline __isl_give isl_union_map *copy() && = delete;
+  inline __isl_keep isl_union_map *get() const;
+  inline __isl_give isl_union_map *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_map affine_hull() const;
+  inline isl::union_map apply_domain(isl::union_map umap2) const;
+  inline isl::union_map apply_range(isl::union_map umap2) const;
+  inline isl::union_set bind_range(isl::multi_id tuple) const;
+  inline isl::union_map coalesce() const;
+  inline isl::union_map compute_divs() const;
+  inline isl::union_map curry() const;
+  inline isl::union_set deltas() const;
+  inline isl::union_map detect_equalities() const;
+  inline isl::union_set domain() const;
+  inline isl::union_map domain_factor_domain() const;
+  inline isl::union_map domain_factor_range() const;
+  inline isl::union_map domain_map() const;
+  inline isl::union_pw_multi_aff domain_map_union_pw_multi_aff() const;
+  inline isl::union_map domain_product(isl::union_map umap2) const;
+  static inline isl::union_map empty(isl::ctx ctx);
+  inline isl::union_map eq_at(isl::multi_union_pw_aff mupa) const;
+  inline bool every_map(const std::function<bool(isl::map)> &test) const;
+  inline isl::map extract_map(isl::space space) const;
+  inline isl::union_map factor_domain() const;
+  inline isl::union_map factor_range() const;
+  inline isl::union_map fixed_power(isl::val exp) const;
+  inline isl::union_map fixed_power(long exp) const;
+  inline void foreach_map(const std::function<void(isl::map)> &fn) const;
+  static inline isl::union_map from(isl::multi_union_pw_aff mupa);
+  static inline isl::union_map from(isl::union_pw_multi_aff upma);
+  static inline isl::union_map from_domain(isl::union_set uset);
+  static inline isl::union_map from_domain_and_range(isl::union_set domain, isl::union_set range);
+  static inline isl::union_map from_range(isl::union_set uset);
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::union_map gist(isl::union_map context) const;
+  inline isl::union_map gist_domain(isl::union_set uset) const;
+  inline isl::union_map gist_params(isl::set set) const;
+  inline isl::union_map gist_range(isl::union_set uset) const;
+  inline isl::union_map intersect(isl::union_map umap2) const;
+  inline isl::union_map intersect_domain(isl::union_set uset) const;
+  inline isl::union_map intersect_params(isl::set set) const;
+  inline isl::union_map intersect_range(isl::union_set uset) const;
+  inline bool is_bijective() const;
+  inline bool is_disjoint(const isl::union_map &umap2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const isl::union_map &umap2) const;
+  inline bool is_injective() const;
+  inline bool is_single_valued() const;
+  inline bool is_strict_subset(const isl::union_map &umap2) const;
+  inline bool is_subset(const isl::union_map &umap2) const;
+  inline bool isa_map() const;
+  inline isl::union_map lexmax() const;
+  inline isl::union_map lexmin() const;
+  inline isl::union_map polyhedral_hull() const;
+  inline isl::union_map preimage_domain(isl::multi_aff ma) const;
+  inline isl::union_map preimage_domain(isl::multi_pw_aff mpa) const;
+  inline isl::union_map preimage_domain(isl::pw_multi_aff pma) const;
+  inline isl::union_map preimage_domain(isl::union_pw_multi_aff upma) const;
+  inline isl::union_map preimage_range(isl::multi_aff ma) const;
+  inline isl::union_map preimage_range(isl::pw_multi_aff pma) const;
+  inline isl::union_map preimage_range(isl::union_pw_multi_aff upma) const;
+  inline isl::union_map product(isl::union_map umap2) const;
+  inline isl::union_map project_out_all_params() const;
+  inline isl::union_set range() const;
+  inline isl::union_map range_factor_domain() const;
+  inline isl::union_map range_factor_range() const;
+  inline isl::union_map range_map() const;
+  inline isl::union_map range_product(isl::union_map umap2) const;
+  inline isl::union_map range_reverse() const;
+  inline isl::union_map reverse() const;
+  inline isl::union_map subtract(isl::union_map umap2) const;
+  inline isl::union_map subtract_domain(isl::union_set dom) const;
+  inline isl::union_map subtract_range(isl::union_set dom) const;
+  inline isl::union_map uncurry() const;
+  inline isl::union_map unite(isl::union_map umap2) const;
+  inline isl::union_map universe() const;
+  inline isl::union_set wrap() const;
+  inline isl::union_map zip() const;
+};
+
+// declarations for isl::union_pw_aff
+inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+class union_pw_aff {
+  friend inline union_pw_aff manage(__isl_take isl_union_pw_aff *ptr);
+  friend inline union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr);
+
+protected:
+  isl_union_pw_aff *ptr = nullptr;
+
+  inline explicit union_pw_aff(__isl_take isl_union_pw_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_aff();
+  inline /* implicit */ union_pw_aff(const union_pw_aff &obj);
+  inline /* implicit */ union_pw_aff(isl::pw_aff pa);
+  inline explicit union_pw_aff(isl::ctx ctx, const std::string &str);
+  inline union_pw_aff &operator=(union_pw_aff obj);
+  inline ~union_pw_aff();
+  inline __isl_give isl_union_pw_aff *copy() const &;
+  inline __isl_give isl_union_pw_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_aff *get() const;
+  inline __isl_give isl_union_pw_aff *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_pw_aff add(isl::union_pw_aff upa2) const;
+  inline isl::union_set bind(isl::id id) const;
+  inline isl::union_set bind(const std::string &id) const;
+  inline isl::union_pw_aff coalesce() const;
+  inline isl::union_set domain() const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::union_pw_aff gist(isl::union_set context) const;
+  inline isl::union_pw_aff intersect_domain(isl::union_set uset) const;
+  inline isl::union_pw_aff intersect_domain_wrapped_domain(isl::union_set uset) const;
+  inline isl::union_pw_aff intersect_domain_wrapped_range(isl::union_set uset) const;
+  inline isl::union_pw_aff intersect_params(isl::set set) const;
+  inline isl::union_pw_aff pullback(isl::union_pw_multi_aff upma) const;
+  inline isl::union_pw_aff sub(isl::union_pw_aff upa2) const;
+  inline isl::union_pw_aff subtract_domain(isl::union_set uset) const;
+  inline isl::union_pw_aff union_add(isl::union_pw_aff upa2) const;
+};
+
+// declarations for isl::union_pw_aff_list
+inline union_pw_aff_list manage(__isl_take isl_union_pw_aff_list *ptr);
+inline union_pw_aff_list manage_copy(__isl_keep isl_union_pw_aff_list *ptr);
+
+class union_pw_aff_list {
+  friend inline union_pw_aff_list manage(__isl_take isl_union_pw_aff_list *ptr);
+  friend inline union_pw_aff_list manage_copy(__isl_keep isl_union_pw_aff_list *ptr);
+
+protected:
+  isl_union_pw_aff_list *ptr = nullptr;
+
+  inline explicit union_pw_aff_list(__isl_take isl_union_pw_aff_list *ptr);
+
+public:
+  inline /* implicit */ union_pw_aff_list();
+  inline /* implicit */ union_pw_aff_list(const union_pw_aff_list &obj);
+  inline explicit union_pw_aff_list(isl::ctx ctx, int n);
+  inline explicit union_pw_aff_list(isl::union_pw_aff el);
+  inline union_pw_aff_list &operator=(union_pw_aff_list obj);
+  inline ~union_pw_aff_list();
+  inline __isl_give isl_union_pw_aff_list *copy() const &;
+  inline __isl_give isl_union_pw_aff_list *copy() && = delete;
+  inline __isl_keep isl_union_pw_aff_list *get() const;
+  inline __isl_give isl_union_pw_aff_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_pw_aff_list add(isl::union_pw_aff el) const;
+  inline isl::union_pw_aff_list clear() const;
+  inline isl::union_pw_aff_list concat(isl::union_pw_aff_list list2) const;
+  inline void foreach(const std::function<void(isl::union_pw_aff)> &fn) const;
+  inline isl::union_pw_aff at(int index) const;
+  inline isl::union_pw_aff get_at(int index) const;
+  inline unsigned size() const;
+};
+
+// declarations for isl::union_pw_multi_aff
+inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+class union_pw_multi_aff {
+  friend inline union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr);
+  friend inline union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr);
+
+protected:
+  isl_union_pw_multi_aff *ptr = nullptr;
+
+  inline explicit union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr);
+
+public:
+  inline /* implicit */ union_pw_multi_aff();
+  inline /* implicit */ union_pw_multi_aff(const union_pw_multi_aff &obj);
+  inline /* implicit */ union_pw_multi_aff(isl::pw_multi_aff pma);
+  inline /* implicit */ union_pw_multi_aff(isl::union_pw_aff upa);
+  inline explicit union_pw_multi_aff(isl::ctx ctx, const std::string &str);
+  inline union_pw_multi_aff &operator=(union_pw_multi_aff obj);
+  inline ~union_pw_multi_aff();
+  inline __isl_give isl_union_pw_multi_aff *copy() const &;
+  inline __isl_give isl_union_pw_multi_aff *copy() && = delete;
+  inline __isl_keep isl_union_pw_multi_aff *get() const;
+  inline __isl_give isl_union_pw_multi_aff *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_pw_multi_aff add(isl::union_pw_multi_aff upma2) const;
+  inline isl::pw_multi_aff as_pw_multi_aff() const;
+  inline isl::union_pw_multi_aff coalesce() const;
+  inline isl::union_set domain() const;
+  static inline isl::union_pw_multi_aff empty(isl::ctx ctx);
+  inline isl::pw_multi_aff extract_pw_multi_aff(isl::space space) const;
+  inline isl::union_pw_multi_aff flat_range_product(isl::union_pw_multi_aff upma2) const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::union_pw_multi_aff gist(isl::union_set context) const;
+  inline isl::union_pw_multi_aff intersect_domain(isl::union_set uset) const;
+  inline isl::union_pw_multi_aff intersect_domain_wrapped_domain(isl::union_set uset) const;
+  inline isl::union_pw_multi_aff intersect_domain_wrapped_range(isl::union_set uset) const;
+  inline isl::union_pw_multi_aff intersect_params(isl::set set) const;
+  inline bool isa_pw_multi_aff() const;
+  inline isl::union_pw_multi_aff pullback(isl::union_pw_multi_aff upma2) const;
+  inline isl::union_pw_multi_aff range_factor_domain() const;
+  inline isl::union_pw_multi_aff range_factor_range() const;
+  inline isl::union_pw_multi_aff sub(isl::union_pw_multi_aff upma2) const;
+  inline isl::union_pw_multi_aff subtract_domain(isl::union_set uset) const;
+  inline isl::union_pw_multi_aff union_add(isl::union_pw_multi_aff upma2) const;
+};
+
+// declarations for isl::union_set
+inline union_set manage(__isl_take isl_union_set *ptr);
+inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+class union_set {
+  friend inline union_set manage(__isl_take isl_union_set *ptr);
+  friend inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+
+protected:
+  isl_union_set *ptr = nullptr;
+
+  inline explicit union_set(__isl_take isl_union_set *ptr);
+
+public:
+  inline /* implicit */ union_set();
+  inline /* implicit */ union_set(const union_set &obj);
+  inline /* implicit */ union_set(isl::basic_set bset);
+  inline /* implicit */ union_set(isl::point pnt);
+  inline /* implicit */ union_set(isl::set set);
+  inline explicit union_set(isl::ctx ctx, const std::string &str);
+  inline union_set &operator=(union_set obj);
+  inline ~union_set();
+  inline __isl_give isl_union_set *copy() const &;
+  inline __isl_give isl_union_set *copy() && = delete;
+  inline __isl_keep isl_union_set *get() const;
+  inline __isl_give isl_union_set *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_set affine_hull() const;
+  inline isl::union_set apply(isl::union_map umap) const;
+  inline isl::union_set coalesce() const;
+  inline isl::union_set compute_divs() const;
+  inline isl::union_set detect_equalities() const;
+  static inline isl::union_set empty(isl::ctx ctx);
+  inline bool every_set(const std::function<bool(isl::set)> &test) const;
+  inline isl::set extract_set(isl::space space) const;
+  inline void foreach_point(const std::function<void(isl::point)> &fn) const;
+  inline void foreach_set(const std::function<void(isl::set)> &fn) const;
+  inline isl::space space() const;
+  inline isl::space get_space() const;
+  inline isl::union_set gist(isl::union_set context) const;
+  inline isl::union_set gist_params(isl::set set) const;
+  inline isl::union_map identity() const;
+  inline isl::union_set intersect(isl::union_set uset2) const;
+  inline isl::union_set intersect_params(isl::set set) const;
+  inline bool is_disjoint(const isl::union_set &uset2) const;
+  inline bool is_empty() const;
+  inline bool is_equal(const isl::union_set &uset2) const;
+  inline bool is_strict_subset(const isl::union_set &uset2) const;
+  inline bool is_subset(const isl::union_set &uset2) const;
+  inline bool isa_set() const;
+  inline isl::union_set lexmax() const;
+  inline isl::union_set lexmin() const;
+  inline isl::union_set polyhedral_hull() const;
+  inline isl::union_set preimage(isl::multi_aff ma) const;
+  inline isl::union_set preimage(isl::pw_multi_aff pma) const;
+  inline isl::union_set preimage(isl::union_pw_multi_aff upma) const;
+  inline isl::point sample_point() const;
+  inline isl::union_set subtract(isl::union_set uset2) const;
+  inline isl::union_set unite(isl::union_set uset2) const;
+  inline isl::union_set universe() const;
+  inline isl::union_map unwrap() const;
+};
+
+// declarations for isl::union_set_list
+inline union_set_list manage(__isl_take isl_union_set_list *ptr);
+inline union_set_list manage_copy(__isl_keep isl_union_set_list *ptr);
+
+class union_set_list {
+  friend inline union_set_list manage(__isl_take isl_union_set_list *ptr);
+  friend inline union_set_list manage_copy(__isl_keep isl_union_set_list *ptr);
+
+protected:
+  isl_union_set_list *ptr = nullptr;
+
+  inline explicit union_set_list(__isl_take isl_union_set_list *ptr);
+
+public:
+  inline /* implicit */ union_set_list();
+  inline /* implicit */ union_set_list(const union_set_list &obj);
+  inline explicit union_set_list(isl::ctx ctx, int n);
+  inline explicit union_set_list(isl::union_set el);
+  inline union_set_list &operator=(union_set_list obj);
+  inline ~union_set_list();
+  inline __isl_give isl_union_set_list *copy() const &;
+  inline __isl_give isl_union_set_list *copy() && = delete;
+  inline __isl_keep isl_union_set_list *get() const;
+  inline __isl_give isl_union_set_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::union_set_list add(isl::union_set el) const;
+  inline isl::union_set_list clear() const;
+  inline isl::union_set_list concat(isl::union_set_list list2) const;
+  inline void foreach(const std::function<void(isl::union_set)> &fn) const;
+  inline isl::union_set at(int index) const;
+  inline isl::union_set get_at(int index) const;
+  inline unsigned size() const;
+};
+
+// declarations for isl::val
+inline val manage(__isl_take isl_val *ptr);
+inline val manage_copy(__isl_keep isl_val *ptr);
+
+class val {
+  friend inline val manage(__isl_take isl_val *ptr);
+  friend inline val manage_copy(__isl_keep isl_val *ptr);
+
+protected:
+  isl_val *ptr = nullptr;
+
+  inline explicit val(__isl_take isl_val *ptr);
+
+public:
+  inline /* implicit */ val();
+  inline /* implicit */ val(const val &obj);
+  inline explicit val(isl::ctx ctx, long i);
+  inline explicit val(isl::ctx ctx, const std::string &str);
+  inline val &operator=(val obj);
+  inline ~val();
+  inline __isl_give isl_val *copy() const &;
+  inline __isl_give isl_val *copy() && = delete;
+  inline __isl_keep isl_val *get() const;
+  inline __isl_give isl_val *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::val abs() const;
+  inline bool abs_eq(const isl::val &v2) const;
+  inline bool abs_eq(long v2) const;
+  inline isl::val add(isl::val v2) const;
+  inline isl::val add(long v2) const;
+  inline isl::val ceil() const;
+  inline int cmp_si(long i) const;
+  inline isl::val div(isl::val v2) const;
+  inline isl::val div(long v2) const;
+  inline bool eq(const isl::val &v2) const;
+  inline bool eq(long v2) const;
+  inline isl::val floor() const;
+  inline isl::val gcd(isl::val v2) const;
+  inline isl::val gcd(long v2) const;
+  inline bool ge(const isl::val &v2) const;
+  inline bool ge(long v2) const;
+  inline long den_si() const;
+  inline long get_den_si() const;
+  inline long num_si() const;
+  inline long get_num_si() const;
+  inline bool gt(const isl::val &v2) const;
+  inline bool gt(long v2) const;
+  static inline isl::val infty(isl::ctx ctx);
+  inline isl::val inv() const;
+  inline bool is_divisible_by(const isl::val &v2) const;
+  inline bool is_divisible_by(long v2) const;
+  inline bool is_infty() const;
+  inline bool is_int() const;
+  inline bool is_nan() const;
+  inline bool is_neg() const;
+  inline bool is_neginfty() const;
+  inline bool is_negone() const;
+  inline bool is_nonneg() const;
+  inline bool is_nonpos() const;
+  inline bool is_one() const;
+  inline bool is_pos() const;
+  inline bool is_rat() const;
+  inline bool is_zero() const;
+  inline bool le(const isl::val &v2) const;
+  inline bool le(long v2) const;
+  inline bool lt(const isl::val &v2) const;
+  inline bool lt(long v2) const;
+  inline isl::val max(isl::val v2) const;
+  inline isl::val max(long v2) const;
+  inline isl::val min(isl::val v2) const;
+  inline isl::val min(long v2) const;
+  inline isl::val mod(isl::val v2) const;
+  inline isl::val mod(long v2) const;
+  inline isl::val mul(isl::val v2) const;
+  inline isl::val mul(long v2) const;
+  static inline isl::val nan(isl::ctx ctx);
+  inline bool ne(const isl::val &v2) const;
+  inline bool ne(long v2) const;
+  inline isl::val neg() const;
+  static inline isl::val neginfty(isl::ctx ctx);
+  static inline isl::val negone(isl::ctx ctx);
+  static inline isl::val one(isl::ctx ctx);
+  inline isl::val pow2() const;
+  inline int sgn() const;
+  inline isl::val sub(isl::val v2) const;
+  inline isl::val sub(long v2) const;
+  inline isl::val trunc() const;
+  static inline isl::val zero(isl::ctx ctx);
+};
+
+// declarations for isl::val_list
+inline val_list manage(__isl_take isl_val_list *ptr);
+inline val_list manage_copy(__isl_keep isl_val_list *ptr);
+
+class val_list {
+  friend inline val_list manage(__isl_take isl_val_list *ptr);
+  friend inline val_list manage_copy(__isl_keep isl_val_list *ptr);
+
+protected:
+  isl_val_list *ptr = nullptr;
+
+  inline explicit val_list(__isl_take isl_val_list *ptr);
+
+public:
+  inline /* implicit */ val_list();
+  inline /* implicit */ val_list(const val_list &obj);
+  inline explicit val_list(isl::ctx ctx, int n);
+  inline explicit val_list(isl::val el);
+  inline val_list &operator=(val_list obj);
+  inline ~val_list();
+  inline __isl_give isl_val_list *copy() const &;
+  inline __isl_give isl_val_list *copy() && = delete;
+  inline __isl_keep isl_val_list *get() const;
+  inline __isl_give isl_val_list *release();
+  inline bool is_null() const;
+  inline isl::ctx ctx() const;
+
+  inline isl::val_list add(isl::val el) const;
+  inline isl::val_list add(long el) const;
+  inline isl::val_list clear() const;
+  inline isl::val_list concat(isl::val_list list2) const;
+  inline void foreach(const std::function<void(isl::val)> &fn) const;
+  inline isl::val at(int index) const;
+  inline isl::val get_at(int index) const;
+  inline unsigned size() const;
+};
+
+// implementations for isl::aff
+aff manage(__isl_take isl_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return aff(ptr);
+}
+aff manage_copy(__isl_keep isl_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return aff(ptr);
+}
+
+aff::aff()
+    : ptr(nullptr) {}
+
+aff::aff(const aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+aff::aff(__isl_take isl_aff *ptr)
+    : ptr(ptr) {}
+
+aff::aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+aff &aff::operator=(aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+aff::~aff() {
+  if (ptr)
+    isl_aff_free(ptr);
+}
+
+__isl_give isl_aff *aff::copy() const & {
+  return isl_aff_copy(ptr);
+}
+
+__isl_keep isl_aff *aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_aff *aff::release() {
+  isl_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx aff::ctx() const {
+  return isl::ctx(isl_aff_get_ctx(ptr));
+}
+
+isl::aff aff::add(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_add(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::add_constant(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_add_constant_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::add_constant(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add_constant(isl::val(ctx(), v));
+}
+
+isl::basic_set aff::bind(isl::id id) const
+{
+  if (!ptr || id.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_bind_id(copy(), id.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set aff::bind(const std::string &id) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->bind(isl::id(ctx(), id));
+}
+
+isl::aff aff::ceil() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_ceil(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::div(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_div(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set aff::eq_set(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_eq_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val aff::eval(isl::point pnt) const
+{
+  if (!ptr || pnt.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_eval(copy(), pnt.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::floor() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_floor(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set aff::ge_set(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_ge_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::gist(isl::set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set aff::gt_set(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_gt_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set aff::le_set(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_le_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set aff::lt_set(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_lt_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::mod(isl::val mod) const
+{
+  if (!ptr || mod.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_mod_val(copy(), mod.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::mod(long mod) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->mod(isl::val(ctx(), mod));
+}
+
+isl::aff aff::mul(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_mul(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set aff::ne_set(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_ne_set(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::neg() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_neg(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::pullback(isl::multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_pullback_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::scale(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::scale(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale(isl::val(ctx(), v));
+}
+
+isl::aff aff::scale_down(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_scale_down_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::scale_down(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale_down(isl::val(ctx(), v));
+}
+
+isl::aff aff::sub(isl::aff aff2) const
+{
+  if (!ptr || aff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_sub(copy(), aff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff::unbind_params_insert_domain(isl::multi_id domain) const
+{
+  if (!ptr || domain.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_unbind_params_insert_domain(copy(), domain.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const aff &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::aff_list
+aff_list manage(__isl_take isl_aff_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return aff_list(ptr);
+}
+aff_list manage_copy(__isl_keep isl_aff_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_aff_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_aff_list_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return aff_list(ptr);
+}
+
+aff_list::aff_list()
+    : ptr(nullptr) {}
+
+aff_list::aff_list(const aff_list &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_aff_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+aff_list::aff_list(__isl_take isl_aff_list *ptr)
+    : ptr(ptr) {}
+
+aff_list::aff_list(isl::ctx ctx, int n)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_list_alloc(ctx.release(), n);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+aff_list::aff_list(isl::aff el)
+{
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_list_from_aff(el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+aff_list &aff_list::operator=(aff_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+aff_list::~aff_list() {
+  if (ptr)
+    isl_aff_list_free(ptr);
+}
+
+__isl_give isl_aff_list *aff_list::copy() const & {
+  return isl_aff_list_copy(ptr);
+}
+
+__isl_keep isl_aff_list *aff_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_aff_list *aff_list::release() {
+  isl_aff_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool aff_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx aff_list::ctx() const {
+  return isl::ctx(isl_aff_list_get_ctx(ptr));
+}
+
+isl::aff_list aff_list::add(isl::aff el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_list_add(copy(), el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff_list aff_list::clear() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_list_clear(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff_list aff_list::concat(isl::aff_list list2) const
+{
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_list_concat(copy(), list2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+void aff_list::foreach(const std::function<void(isl::aff)> &fn) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::aff)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_aff_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
+
+isl::aff aff_list::at(int index) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_list_get_at(get(), index);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff aff_list::get_at(int index) const
+{
+  return at(index);
+}
+
+unsigned aff_list::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_aff_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const aff_list &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_aff_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_aff_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_build
+ast_build manage(__isl_take isl_ast_build *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return ast_build(ptr);
+}
+ast_build manage_copy(__isl_keep isl_ast_build *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_build_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_ast_build_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return ast_build(ptr);
+}
+
+ast_build::ast_build()
+    : ptr(nullptr) {}
+
+ast_build::ast_build(const ast_build &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_build_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  copy_callbacks(obj);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+ast_build::ast_build(__isl_take isl_ast_build *ptr)
+    : ptr(ptr) {}
+
+ast_build::ast_build(isl::ctx ctx)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_alloc(ctx.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+ast_build &ast_build::operator=(ast_build obj) {
+  std::swap(this->ptr, obj.ptr);
+  copy_callbacks(obj);
+  return *this;
+}
+
+ast_build::~ast_build() {
+  if (ptr)
+    isl_ast_build_free(ptr);
+}
+
+__isl_give isl_ast_build *ast_build::copy() const & {
+  return isl_ast_build_copy(ptr);
+}
+
+__isl_keep isl_ast_build *ast_build::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_build *ast_build::release() {
+  if (at_each_domain_data)
+    exception::throw_invalid("cannot release object with persistent callbacks", __FILE__, __LINE__);
+  isl_ast_build *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_build::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx ast_build::ctx() const {
+  return isl::ctx(isl_ast_build_get_ctx(ptr));
+}
+
+ast_build &ast_build::copy_callbacks(const ast_build &obj)
+{
+  at_each_domain_data = obj.at_each_domain_data;
+  return *this;
+}
+
+isl_ast_node *ast_build::at_each_domain(isl_ast_node *arg_0, isl_ast_build *arg_1, void *arg_2)
+{
+  auto *data = static_cast<struct at_each_domain_data *>(arg_2);
+  ISL_CPP_TRY {
+    auto ret = (data->func)(manage(arg_0), manage_copy(arg_1));
+    return ret.release();
+  } ISL_CPP_CATCH_ALL {
+    data->eptr = std::current_exception();
+    return NULL;
+  }
+}
+
+void ast_build::set_at_each_domain_data(const std::function<isl::ast_node(isl::ast_node, isl::ast_build)> &fn)
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_build_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  at_each_domain_data = std::make_shared<struct at_each_domain_data>();
+  at_each_domain_data->func = fn;
+  ptr = isl_ast_build_set_at_each_domain(ptr, &at_each_domain, at_each_domain_data.get());
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+isl::ast_build ast_build::set_at_each_domain(const std::function<isl::ast_node(isl::ast_node, isl::ast_build)> &fn) const
+{
+  auto copy = *this;
+  copy.set_at_each_domain_data(fn);
+  return copy;
+}
+
+isl::ast_expr ast_build::access_from(isl::multi_pw_aff mpa) const
+{
+  if (!ptr || mpa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_access_from_multi_pw_aff(get(), mpa.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_build::access_from(isl::pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_access_from_pw_multi_aff(get(), pma.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_build::call_from(isl::multi_pw_aff mpa) const
+{
+  if (!ptr || mpa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_call_from_multi_pw_aff(get(), mpa.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_build::call_from(isl::pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_call_from_pw_multi_aff(get(), pma.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_build::expr_from(isl::pw_aff pa) const
+{
+  if (!ptr || pa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_expr_from_pw_aff(get(), pa.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_build::expr_from(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_expr_from_set(get(), set.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_build ast_build::from_context(isl::set set)
+{
+  if (set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = set.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_from_context(set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_map ast_build::schedule() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_get_schedule(get());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_map ast_build::get_schedule() const
+{
+  return schedule();
+}
+
+isl::ast_node ast_build::node_from(isl::schedule schedule) const
+{
+  if (!ptr || schedule.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_node_from_schedule(get(), schedule.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node ast_build::node_from_schedule_map(isl::union_map schedule) const
+{
+  if (!ptr || schedule.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_build_node_from_schedule_map(get(), schedule.release());
+  if (at_each_domain_data && at_each_domain_data->eptr) {
+    std::exception_ptr eptr = at_each_domain_data->eptr;
+    at_each_domain_data->eptr = nullptr;
+    std::rethrow_exception(eptr);
+  }
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+// implementations for isl::ast_expr
+ast_expr manage(__isl_take isl_ast_expr *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return ast_expr(ptr);
+}
+ast_expr manage_copy(__isl_keep isl_ast_expr *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_ast_expr_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return ast_expr(ptr);
+}
+
+ast_expr::ast_expr()
+    : ptr(nullptr) {}
+
+ast_expr::ast_expr(const ast_expr &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+ast_expr::ast_expr(__isl_take isl_ast_expr *ptr)
+    : ptr(ptr) {}
+
+ast_expr &ast_expr::operator=(ast_expr obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_expr::~ast_expr() {
+  if (ptr)
+    isl_ast_expr_free(ptr);
+}
+
+__isl_give isl_ast_expr *ast_expr::copy() const & {
+  return isl_ast_expr_copy(ptr);
+}
+
+__isl_keep isl_ast_expr *ast_expr::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_expr *ast_expr::release() {
+  isl_ast_expr *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_expr::is_null() const {
+  return ptr == nullptr;
+}
+
+template <typename T, typename>
+bool ast_expr::isa_type(T subtype) const
+{
+  if (is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return isl_ast_expr_get_type(get()) == subtype;
+}
+template <class T>
+bool ast_expr::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T ast_expr::as() const
+{
+ if (!isa<T>())
+    exception::throw_invalid("not an object of the requested subtype", __FILE__, __LINE__);
+  return T(copy());
+}
+
+isl::ctx ast_expr::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+std::string ast_expr::to_C_str() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_expr_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_id
+ast_expr_id::ast_expr_id()
+    : ast_expr() {}
+
+ast_expr_id::ast_expr_id(const ast_expr_id &obj)
+    : ast_expr(obj)
+{
+}
+
+ast_expr_id::ast_expr_id(__isl_take isl_ast_expr *ptr)
+    : ast_expr(ptr) {}
+
+ast_expr_id &ast_expr_id::operator=(ast_expr_id obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_id::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+isl::id ast_expr_id::id() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_expr_id_get_id(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::id ast_expr_id::get_id() const
+{
+  return id();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_id &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_int
+ast_expr_int::ast_expr_int()
+    : ast_expr() {}
+
+ast_expr_int::ast_expr_int(const ast_expr_int &obj)
+    : ast_expr(obj)
+{
+}
+
+ast_expr_int::ast_expr_int(__isl_take isl_ast_expr *ptr)
+    : ast_expr(ptr) {}
+
+ast_expr_int &ast_expr_int::operator=(ast_expr_int obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_int::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+isl::val ast_expr_int::val() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_expr_int_get_val(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val ast_expr_int::get_val() const
+{
+  return val();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_int &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op
+ast_expr_op::ast_expr_op()
+    : ast_expr() {}
+
+ast_expr_op::ast_expr_op(const ast_expr_op &obj)
+    : ast_expr(obj)
+{
+}
+
+ast_expr_op::ast_expr_op(__isl_take isl_ast_expr *ptr)
+    : ast_expr(ptr) {}
+
+ast_expr_op &ast_expr_op::operator=(ast_expr_op obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+template <typename T, typename>
+bool ast_expr_op::isa_type(T subtype) const
+{
+  if (is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return isl_ast_expr_op_get_type(get()) == subtype;
+}
+template <class T>
+bool ast_expr_op::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T ast_expr_op::as() const
+{
+ if (!isa<T>())
+    exception::throw_invalid("not an object of the requested subtype", __FILE__, __LINE__);
+  return T(copy());
+}
+
+isl::ctx ast_expr_op::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+isl::ast_expr ast_expr_op::arg(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_expr_op_get_arg(get(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_expr_op::get_arg(int pos) const
+{
+  return arg(pos);
+}
+
+unsigned ast_expr_op::n_arg() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_expr_op_get_n_arg(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+unsigned ast_expr_op::get_n_arg() const
+{
+  return n_arg();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_access
+ast_expr_op_access::ast_expr_op_access()
+    : ast_expr_op() {}
+
+ast_expr_op_access::ast_expr_op_access(const ast_expr_op_access &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_access::ast_expr_op_access(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_access &ast_expr_op_access::operator=(ast_expr_op_access obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_access::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_access &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_add
+ast_expr_op_add::ast_expr_op_add()
+    : ast_expr_op() {}
+
+ast_expr_op_add::ast_expr_op_add(const ast_expr_op_add &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_add::ast_expr_op_add(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_add &ast_expr_op_add::operator=(ast_expr_op_add obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_add::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_add &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_address_of
+ast_expr_op_address_of::ast_expr_op_address_of()
+    : ast_expr_op() {}
+
+ast_expr_op_address_of::ast_expr_op_address_of(const ast_expr_op_address_of &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_address_of::ast_expr_op_address_of(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_address_of &ast_expr_op_address_of::operator=(ast_expr_op_address_of obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_address_of::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_address_of &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_and
+ast_expr_op_and::ast_expr_op_and()
+    : ast_expr_op() {}
+
+ast_expr_op_and::ast_expr_op_and(const ast_expr_op_and &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_and::ast_expr_op_and(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_and &ast_expr_op_and::operator=(ast_expr_op_and obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_and::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_and &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_and_then
+ast_expr_op_and_then::ast_expr_op_and_then()
+    : ast_expr_op() {}
+
+ast_expr_op_and_then::ast_expr_op_and_then(const ast_expr_op_and_then &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_and_then::ast_expr_op_and_then(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_and_then &ast_expr_op_and_then::operator=(ast_expr_op_and_then obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_and_then::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_and_then &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_call
+ast_expr_op_call::ast_expr_op_call()
+    : ast_expr_op() {}
+
+ast_expr_op_call::ast_expr_op_call(const ast_expr_op_call &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_call::ast_expr_op_call(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_call &ast_expr_op_call::operator=(ast_expr_op_call obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_call::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_call &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_cond
+ast_expr_op_cond::ast_expr_op_cond()
+    : ast_expr_op() {}
+
+ast_expr_op_cond::ast_expr_op_cond(const ast_expr_op_cond &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_cond::ast_expr_op_cond(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_cond &ast_expr_op_cond::operator=(ast_expr_op_cond obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_cond::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_cond &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_div
+ast_expr_op_div::ast_expr_op_div()
+    : ast_expr_op() {}
+
+ast_expr_op_div::ast_expr_op_div(const ast_expr_op_div &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_div::ast_expr_op_div(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_div &ast_expr_op_div::operator=(ast_expr_op_div obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_div::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_div &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_eq
+ast_expr_op_eq::ast_expr_op_eq()
+    : ast_expr_op() {}
+
+ast_expr_op_eq::ast_expr_op_eq(const ast_expr_op_eq &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_eq::ast_expr_op_eq(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_eq &ast_expr_op_eq::operator=(ast_expr_op_eq obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_eq::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_eq &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_fdiv_q
+ast_expr_op_fdiv_q::ast_expr_op_fdiv_q()
+    : ast_expr_op() {}
+
+ast_expr_op_fdiv_q::ast_expr_op_fdiv_q(const ast_expr_op_fdiv_q &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_fdiv_q::ast_expr_op_fdiv_q(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_fdiv_q &ast_expr_op_fdiv_q::operator=(ast_expr_op_fdiv_q obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_fdiv_q::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_fdiv_q &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_ge
+ast_expr_op_ge::ast_expr_op_ge()
+    : ast_expr_op() {}
+
+ast_expr_op_ge::ast_expr_op_ge(const ast_expr_op_ge &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_ge::ast_expr_op_ge(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_ge &ast_expr_op_ge::operator=(ast_expr_op_ge obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_ge::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_ge &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_gt
+ast_expr_op_gt::ast_expr_op_gt()
+    : ast_expr_op() {}
+
+ast_expr_op_gt::ast_expr_op_gt(const ast_expr_op_gt &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_gt::ast_expr_op_gt(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_gt &ast_expr_op_gt::operator=(ast_expr_op_gt obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_gt::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_gt &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_le
+ast_expr_op_le::ast_expr_op_le()
+    : ast_expr_op() {}
+
+ast_expr_op_le::ast_expr_op_le(const ast_expr_op_le &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_le::ast_expr_op_le(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_le &ast_expr_op_le::operator=(ast_expr_op_le obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_le::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_le &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_lt
+ast_expr_op_lt::ast_expr_op_lt()
+    : ast_expr_op() {}
+
+ast_expr_op_lt::ast_expr_op_lt(const ast_expr_op_lt &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_lt::ast_expr_op_lt(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_lt &ast_expr_op_lt::operator=(ast_expr_op_lt obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_lt::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_lt &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_max
+ast_expr_op_max::ast_expr_op_max()
+    : ast_expr_op() {}
+
+ast_expr_op_max::ast_expr_op_max(const ast_expr_op_max &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_max::ast_expr_op_max(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_max &ast_expr_op_max::operator=(ast_expr_op_max obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_max::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_max &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_member
+ast_expr_op_member::ast_expr_op_member()
+    : ast_expr_op() {}
+
+ast_expr_op_member::ast_expr_op_member(const ast_expr_op_member &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_member::ast_expr_op_member(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_member &ast_expr_op_member::operator=(ast_expr_op_member obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_member::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_member &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_min
+ast_expr_op_min::ast_expr_op_min()
+    : ast_expr_op() {}
+
+ast_expr_op_min::ast_expr_op_min(const ast_expr_op_min &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_min::ast_expr_op_min(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_min &ast_expr_op_min::operator=(ast_expr_op_min obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_min::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_min &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_minus
+ast_expr_op_minus::ast_expr_op_minus()
+    : ast_expr_op() {}
+
+ast_expr_op_minus::ast_expr_op_minus(const ast_expr_op_minus &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_minus::ast_expr_op_minus(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_minus &ast_expr_op_minus::operator=(ast_expr_op_minus obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_minus::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_minus &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_mul
+ast_expr_op_mul::ast_expr_op_mul()
+    : ast_expr_op() {}
+
+ast_expr_op_mul::ast_expr_op_mul(const ast_expr_op_mul &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_mul::ast_expr_op_mul(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_mul &ast_expr_op_mul::operator=(ast_expr_op_mul obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_mul::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_mul &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_or
+ast_expr_op_or::ast_expr_op_or()
+    : ast_expr_op() {}
+
+ast_expr_op_or::ast_expr_op_or(const ast_expr_op_or &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_or::ast_expr_op_or(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_or &ast_expr_op_or::operator=(ast_expr_op_or obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_or::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_or &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_or_else
+ast_expr_op_or_else::ast_expr_op_or_else()
+    : ast_expr_op() {}
+
+ast_expr_op_or_else::ast_expr_op_or_else(const ast_expr_op_or_else &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_or_else::ast_expr_op_or_else(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_or_else &ast_expr_op_or_else::operator=(ast_expr_op_or_else obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_or_else::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_or_else &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_pdiv_q
+ast_expr_op_pdiv_q::ast_expr_op_pdiv_q()
+    : ast_expr_op() {}
+
+ast_expr_op_pdiv_q::ast_expr_op_pdiv_q(const ast_expr_op_pdiv_q &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_pdiv_q::ast_expr_op_pdiv_q(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_pdiv_q &ast_expr_op_pdiv_q::operator=(ast_expr_op_pdiv_q obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_pdiv_q::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_pdiv_q &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_pdiv_r
+ast_expr_op_pdiv_r::ast_expr_op_pdiv_r()
+    : ast_expr_op() {}
+
+ast_expr_op_pdiv_r::ast_expr_op_pdiv_r(const ast_expr_op_pdiv_r &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_pdiv_r::ast_expr_op_pdiv_r(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_pdiv_r &ast_expr_op_pdiv_r::operator=(ast_expr_op_pdiv_r obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_pdiv_r::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_pdiv_r &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_select
+ast_expr_op_select::ast_expr_op_select()
+    : ast_expr_op() {}
+
+ast_expr_op_select::ast_expr_op_select(const ast_expr_op_select &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_select::ast_expr_op_select(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_select &ast_expr_op_select::operator=(ast_expr_op_select obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_select::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_select &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_sub
+ast_expr_op_sub::ast_expr_op_sub()
+    : ast_expr_op() {}
+
+ast_expr_op_sub::ast_expr_op_sub(const ast_expr_op_sub &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_sub::ast_expr_op_sub(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_sub &ast_expr_op_sub::operator=(ast_expr_op_sub obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_sub::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_sub &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_expr_op_zdiv_r
+ast_expr_op_zdiv_r::ast_expr_op_zdiv_r()
+    : ast_expr_op() {}
+
+ast_expr_op_zdiv_r::ast_expr_op_zdiv_r(const ast_expr_op_zdiv_r &obj)
+    : ast_expr_op(obj)
+{
+}
+
+ast_expr_op_zdiv_r::ast_expr_op_zdiv_r(__isl_take isl_ast_expr *ptr)
+    : ast_expr_op(ptr) {}
+
+ast_expr_op_zdiv_r &ast_expr_op_zdiv_r::operator=(ast_expr_op_zdiv_r obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_expr_op_zdiv_r::ctx() const {
+  return isl::ctx(isl_ast_expr_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_expr_op_zdiv_r &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_expr_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_expr_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node
+ast_node manage(__isl_take isl_ast_node *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return ast_node(ptr);
+}
+ast_node manage_copy(__isl_keep isl_ast_node *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_ast_node_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return ast_node(ptr);
+}
+
+ast_node::ast_node()
+    : ptr(nullptr) {}
+
+ast_node::ast_node(const ast_node &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+ast_node::ast_node(__isl_take isl_ast_node *ptr)
+    : ptr(ptr) {}
+
+ast_node &ast_node::operator=(ast_node obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_node::~ast_node() {
+  if (ptr)
+    isl_ast_node_free(ptr);
+}
+
+__isl_give isl_ast_node *ast_node::copy() const & {
+  return isl_ast_node_copy(ptr);
+}
+
+__isl_keep isl_ast_node *ast_node::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_node *ast_node::release() {
+  isl_ast_node *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_node::is_null() const {
+  return ptr == nullptr;
+}
+
+template <typename T, typename>
+bool ast_node::isa_type(T subtype) const
+{
+  if (is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return isl_ast_node_get_type(get()) == subtype;
+}
+template <class T>
+bool ast_node::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T ast_node::as() const
+{
+ if (!isa<T>())
+    exception::throw_invalid("not an object of the requested subtype", __FILE__, __LINE__);
+  return T(copy());
+}
+
+isl::ctx ast_node::ctx() const {
+  return isl::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+std::string ast_node::to_C_str() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_to_C_str(get());
+  std::string tmp(res);
+  free(res);
+  return tmp;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_block
+ast_node_block::ast_node_block()
+    : ast_node() {}
+
+ast_node_block::ast_node_block(const ast_node_block &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_block::ast_node_block(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_block &ast_node_block::operator=(ast_node_block obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_node_block::ctx() const {
+  return isl::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::ast_node_list ast_node_block::children() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_block_get_children(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node_list ast_node_block::get_children() const
+{
+  return children();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_block &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_for
+ast_node_for::ast_node_for()
+    : ast_node() {}
+
+ast_node_for::ast_node_for(const ast_node_for &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_for::ast_node_for(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_for &ast_node_for::operator=(ast_node_for obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_node_for::ctx() const {
+  return isl::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::ast_node ast_node_for::body() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_for_get_body(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node ast_node_for::get_body() const
+{
+  return body();
+}
+
+isl::ast_expr ast_node_for::cond() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_for_get_cond(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_node_for::get_cond() const
+{
+  return cond();
+}
+
+isl::ast_expr ast_node_for::inc() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_for_get_inc(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_node_for::get_inc() const
+{
+  return inc();
+}
+
+isl::ast_expr ast_node_for::init() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_for_get_init(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_node_for::get_init() const
+{
+  return init();
+}
+
+isl::ast_expr ast_node_for::iterator() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_for_get_iterator(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_node_for::get_iterator() const
+{
+  return iterator();
+}
+
+bool ast_node_for::is_degenerate() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_for_is_degenerate(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_for &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_if
+ast_node_if::ast_node_if()
+    : ast_node() {}
+
+ast_node_if::ast_node_if(const ast_node_if &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_if::ast_node_if(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_if &ast_node_if::operator=(ast_node_if obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_node_if::ctx() const {
+  return isl::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::ast_expr ast_node_if::cond() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_if_get_cond(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_node_if::get_cond() const
+{
+  return cond();
+}
+
+isl::ast_node ast_node_if::else_node() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_if_get_else_node(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node ast_node_if::get_else_node() const
+{
+  return else_node();
+}
+
+isl::ast_node ast_node_if::then_node() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_if_get_then_node(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node ast_node_if::get_then_node() const
+{
+  return then_node();
+}
+
+bool ast_node_if::has_else_node() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_if_has_else_node(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_if &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_list
+ast_node_list manage(__isl_take isl_ast_node_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return ast_node_list(ptr);
+}
+ast_node_list manage_copy(__isl_keep isl_ast_node_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_ast_node_list_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return ast_node_list(ptr);
+}
+
+ast_node_list::ast_node_list()
+    : ptr(nullptr) {}
+
+ast_node_list::ast_node_list(const ast_node_list &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+ast_node_list::ast_node_list(__isl_take isl_ast_node_list *ptr)
+    : ptr(ptr) {}
+
+ast_node_list::ast_node_list(isl::ctx ctx, int n)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_list_alloc(ctx.release(), n);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+ast_node_list::ast_node_list(isl::ast_node el)
+{
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_list_from_ast_node(el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+ast_node_list &ast_node_list::operator=(ast_node_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+ast_node_list::~ast_node_list() {
+  if (ptr)
+    isl_ast_node_list_free(ptr);
+}
+
+__isl_give isl_ast_node_list *ast_node_list::copy() const & {
+  return isl_ast_node_list_copy(ptr);
+}
+
+__isl_keep isl_ast_node_list *ast_node_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_ast_node_list *ast_node_list::release() {
+  isl_ast_node_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool ast_node_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx ast_node_list::ctx() const {
+  return isl::ctx(isl_ast_node_list_get_ctx(ptr));
+}
+
+isl::ast_node_list ast_node_list::add(isl::ast_node el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_list_add(copy(), el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node_list ast_node_list::clear() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_list_clear(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node_list ast_node_list::concat(isl::ast_node_list list2) const
+{
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_list_concat(copy(), list2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+void ast_node_list::foreach(const std::function<void(isl::ast_node)> &fn) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::ast_node)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_ast_node *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_ast_node_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
+
+isl::ast_node ast_node_list::at(int index) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_list_get_at(get(), index);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node ast_node_list::get_at(int index) const
+{
+  return at(index);
+}
+
+unsigned ast_node_list::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_list &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_node_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_mark
+ast_node_mark::ast_node_mark()
+    : ast_node() {}
+
+ast_node_mark::ast_node_mark(const ast_node_mark &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_mark::ast_node_mark(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_mark &ast_node_mark::operator=(ast_node_mark obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_node_mark::ctx() const {
+  return isl::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::id ast_node_mark::id() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_mark_get_id(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::id ast_node_mark::get_id() const
+{
+  return id();
+}
+
+isl::ast_node ast_node_mark::node() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_mark_get_node(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_node ast_node_mark::get_node() const
+{
+  return node();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_mark &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::ast_node_user
+ast_node_user::ast_node_user()
+    : ast_node() {}
+
+ast_node_user::ast_node_user(const ast_node_user &obj)
+    : ast_node(obj)
+{
+}
+
+ast_node_user::ast_node_user(__isl_take isl_ast_node *ptr)
+    : ast_node(ptr) {}
+
+ast_node_user &ast_node_user::operator=(ast_node_user obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx ast_node_user::ctx() const {
+  return isl::ctx(isl_ast_node_get_ctx(ptr));
+}
+
+isl::ast_expr ast_node_user::expr() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_ast_node_user_get_expr(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::ast_expr ast_node_user::get_expr() const
+{
+  return expr();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const ast_node_user &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_ast_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_ast_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::basic_map
+basic_map manage(__isl_take isl_basic_map *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return basic_map(ptr);
+}
+basic_map manage_copy(__isl_keep isl_basic_map *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_basic_map_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_basic_map_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return basic_map(ptr);
+}
+
+basic_map::basic_map()
+    : ptr(nullptr) {}
+
+basic_map::basic_map(const basic_map &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_basic_map_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+basic_map::basic_map(__isl_take isl_basic_map *ptr)
+    : ptr(ptr) {}
+
+basic_map::basic_map(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+basic_map &basic_map::operator=(basic_map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_map::~basic_map() {
+  if (ptr)
+    isl_basic_map_free(ptr);
+}
+
+__isl_give isl_basic_map *basic_map::copy() const & {
+  return isl_basic_map_copy(ptr);
+}
+
+__isl_keep isl_basic_map *basic_map::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_map *basic_map::release() {
+  isl_basic_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_map::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx basic_map::ctx() const {
+  return isl::ctx(isl_basic_map_get_ctx(ptr));
+}
+
+isl::basic_map basic_map::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::apply_domain(isl::basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_apply_domain(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::apply_range(isl::basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_apply_range(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_map::deltas() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_deltas(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::flatten() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_flatten(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::flatten_domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_flatten_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::flatten_range() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_flatten_range(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::gist(isl::basic_map context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::intersect(isl::basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_intersect(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::intersect_domain(isl::basic_set bset) const
+{
+  if (!ptr || bset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_intersect_domain(copy(), bset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::intersect_range(isl::basic_set bset) const
+{
+  if (!ptr || bset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_intersect_range(copy(), bset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool basic_map::is_empty() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool basic_map::is_equal(const isl::basic_map &bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_is_equal(get(), bmap2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool basic_map::is_subset(const isl::basic_map &bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_is_subset(get(), bmap2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::map basic_map::lexmax() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map basic_map::lexmin() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::reverse() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_reverse(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map basic_map::sample() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_sample(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map basic_map::unite(isl::basic_map bmap2) const
+{
+  if (!ptr || bmap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_map_union(copy(), bmap2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const basic_map &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_basic_map_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_basic_map_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::basic_set
+basic_set manage(__isl_take isl_basic_set *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return basic_set(ptr);
+}
+basic_set manage_copy(__isl_keep isl_basic_set *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_basic_set_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_basic_set_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return basic_set(ptr);
+}
+
+basic_set::basic_set()
+    : ptr(nullptr) {}
+
+basic_set::basic_set(const basic_set &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_basic_set_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+basic_set::basic_set(__isl_take isl_basic_set *ptr)
+    : ptr(ptr) {}
+
+basic_set::basic_set(isl::point pnt)
+{
+  if (pnt.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pnt.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_from_point(pnt.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+basic_set::basic_set(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+basic_set &basic_set::operator=(basic_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+basic_set::~basic_set() {
+  if (ptr)
+    isl_basic_set_free(ptr);
+}
+
+__isl_give isl_basic_set *basic_set::copy() const & {
+  return isl_basic_set_copy(ptr);
+}
+
+__isl_keep isl_basic_set *basic_set::get() const {
+  return ptr;
+}
+
+__isl_give isl_basic_set *basic_set::release() {
+  isl_basic_set *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool basic_set::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx basic_set::ctx() const {
+  return isl::ctx(isl_basic_set_get_ctx(ptr));
+}
+
+isl::basic_set basic_set::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::apply(isl::basic_map bmap) const
+{
+  if (!ptr || bmap.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_apply(copy(), bmap.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val basic_set::dim_max_val(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_dim_max_val(copy(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::flatten() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_flatten(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::gist(isl::basic_set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::intersect(isl::basic_set bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_intersect(copy(), bset2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::intersect_params(isl::basic_set bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_intersect_params(copy(), bset2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool basic_set::is_empty() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool basic_set::is_equal(const isl::basic_set &bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_is_equal(get(), bset2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool basic_set::is_subset(const isl::basic_set &bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_is_subset(get(), bset2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool basic_set::is_wrapping() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_is_wrapping(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::set basic_set::lexmax() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set basic_set::lexmin() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::params() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_params(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_set basic_set::sample() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_sample(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::point basic_set::sample_point() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_sample_point(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set basic_set::unite(isl::basic_set bset2) const
+{
+  if (!ptr || bset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_basic_set_union(copy(), bset2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const basic_set &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_basic_set_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_basic_set_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::fixed_box
+fixed_box manage(__isl_take isl_fixed_box *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return fixed_box(ptr);
+}
+fixed_box manage_copy(__isl_keep isl_fixed_box *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_fixed_box_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_fixed_box_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return fixed_box(ptr);
+}
+
+fixed_box::fixed_box()
+    : ptr(nullptr) {}
+
+fixed_box::fixed_box(const fixed_box &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_fixed_box_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+fixed_box::fixed_box(__isl_take isl_fixed_box *ptr)
+    : ptr(ptr) {}
+
+fixed_box &fixed_box::operator=(fixed_box obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+fixed_box::~fixed_box() {
+  if (ptr)
+    isl_fixed_box_free(ptr);
+}
+
+__isl_give isl_fixed_box *fixed_box::copy() const & {
+  return isl_fixed_box_copy(ptr);
+}
+
+__isl_keep isl_fixed_box *fixed_box::get() const {
+  return ptr;
+}
+
+__isl_give isl_fixed_box *fixed_box::release() {
+  isl_fixed_box *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool fixed_box::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx fixed_box::ctx() const {
+  return isl::ctx(isl_fixed_box_get_ctx(ptr));
+}
+
+isl::multi_aff fixed_box::offset() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_fixed_box_get_offset(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff fixed_box::get_offset() const
+{
+  return offset();
+}
+
+isl::multi_val fixed_box::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_fixed_box_get_size(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val fixed_box::get_size() const
+{
+  return size();
+}
+
+isl::space fixed_box::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_fixed_box_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space fixed_box::get_space() const
+{
+  return space();
+}
+
+bool fixed_box::is_valid() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_fixed_box_is_valid(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const fixed_box &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_fixed_box_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_fixed_box_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::id
+id manage(__isl_take isl_id *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return id(ptr);
+}
+id manage_copy(__isl_keep isl_id *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_id_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_id_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return id(ptr);
+}
+
+id::id()
+    : ptr(nullptr) {}
+
+id::id(const id &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_id_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+id::id(__isl_take isl_id *ptr)
+    : ptr(ptr) {}
+
+id::id(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+id &id::operator=(id obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+id::~id() {
+  if (ptr)
+    isl_id_free(ptr);
+}
+
+__isl_give isl_id *id::copy() const & {
+  return isl_id_copy(ptr);
+}
+
+__isl_keep isl_id *id::get() const {
+  return ptr;
+}
+
+__isl_give isl_id *id::release() {
+  isl_id *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool id::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx id::ctx() const {
+  return isl::ctx(isl_id_get_ctx(ptr));
+}
+
+std::string id::name() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_get_name(get());
+  std::string tmp(res);
+  return tmp;
+}
+
+std::string id::get_name() const
+{
+  return name();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const id &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_id_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_id_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::id_list
+id_list manage(__isl_take isl_id_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return id_list(ptr);
+}
+id_list manage_copy(__isl_keep isl_id_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_id_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_id_list_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return id_list(ptr);
+}
+
+id_list::id_list()
+    : ptr(nullptr) {}
+
+id_list::id_list(const id_list &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_id_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+id_list::id_list(__isl_take isl_id_list *ptr)
+    : ptr(ptr) {}
+
+id_list::id_list(isl::ctx ctx, int n)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_list_alloc(ctx.release(), n);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+id_list::id_list(isl::id el)
+{
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_list_from_id(el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+id_list &id_list::operator=(id_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+id_list::~id_list() {
+  if (ptr)
+    isl_id_list_free(ptr);
+}
+
+__isl_give isl_id_list *id_list::copy() const & {
+  return isl_id_list_copy(ptr);
+}
+
+__isl_keep isl_id_list *id_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_id_list *id_list::release() {
+  isl_id_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool id_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx id_list::ctx() const {
+  return isl::ctx(isl_id_list_get_ctx(ptr));
+}
+
+isl::id_list id_list::add(isl::id el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_list_add(copy(), el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::id_list id_list::add(const std::string &el) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add(isl::id(ctx(), el));
+}
+
+isl::id_list id_list::clear() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_list_clear(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::id_list id_list::concat(isl::id_list list2) const
+{
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_list_concat(copy(), list2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+void id_list::foreach(const std::function<void(isl::id)> &fn) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::id)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_id *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_id_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
+
+isl::id id_list::at(int index) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_list_get_at(get(), index);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::id id_list::get_at(int index) const
+{
+  return at(index);
+}
+
+unsigned id_list::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_id_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const id_list &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_id_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_id_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::map
+map manage(__isl_take isl_map *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return map(ptr);
+}
+map manage_copy(__isl_keep isl_map *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_map_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_map_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return map(ptr);
+}
+
+map::map()
+    : ptr(nullptr) {}
+
+map::map(const map &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_map_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+map::map(__isl_take isl_map *ptr)
+    : ptr(ptr) {}
+
+map::map(isl::basic_map bmap)
+{
+  if (bmap.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = bmap.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_from_basic_map(bmap.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+map::map(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+map &map::operator=(map obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+map::~map() {
+  if (ptr)
+    isl_map_free(ptr);
+}
+
+__isl_give isl_map *map::copy() const & {
+  return isl_map_copy(ptr);
+}
+
+__isl_keep isl_map *map::get() const {
+  return ptr;
+}
+
+__isl_give isl_map *map::release() {
+  isl_map *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool map::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx map::ctx() const {
+  return isl::ctx(isl_map_get_ctx(ptr));
+}
+
+isl::basic_map map::affine_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_affine_hull(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::apply_domain(isl::map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_apply_domain(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::apply_range(isl::map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_apply_range(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set map::bind_domain(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_bind_domain(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set map::bind_range(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_bind_range(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::coalesce() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::complement() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_complement(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::curry() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_curry(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set map::deltas() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_deltas(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::detect_equalities() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set map::domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::domain_factor_domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_domain_factor_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::domain_factor_range() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_domain_factor_range(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::domain_product(isl::map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_domain_product(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::empty(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_empty(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::factor_domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_factor_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::factor_range() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_factor_range(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::flatten() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_flatten(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::flatten_domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_flatten_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::flatten_range() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_flatten_range(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+void map::foreach_basic_map(const std::function<void(isl::basic_map)> &fn) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::basic_map)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_basic_map *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_map_foreach_basic_map(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
+
+isl::fixed_box map::range_simple_fixed_box_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_get_range_simple_fixed_box_hull(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::fixed_box map::get_range_simple_fixed_box_hull() const
+{
+  return range_simple_fixed_box_hull();
+}
+
+isl::space map::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space map::get_space() const
+{
+  return space();
+}
+
+isl::map map::gist(isl::map context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::gist_domain(isl::set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_gist_domain(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::intersect(isl::map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_intersect(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::intersect_domain(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_intersect_domain(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::intersect_params(isl::set params) const
+{
+  if (!ptr || params.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_intersect_params(copy(), params.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::intersect_range(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_intersect_range(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool map::is_bijective() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_bijective(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool map::is_disjoint(const isl::map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_disjoint(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool map::is_empty() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool map::is_equal(const isl::map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_equal(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool map::is_injective() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_injective(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool map::is_single_valued() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_single_valued(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool map::is_strict_subset(const isl::map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_strict_subset(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool map::is_subset(const isl::map &map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_is_subset(get(), map2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::map map::lexmax() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff map::lexmax_pw_multi_aff() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_lexmax_pw_multi_aff(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::lexmin() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff map::lexmin_pw_multi_aff() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_lexmin_pw_multi_aff(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::lower_bound(isl::multi_pw_aff lower) const
+{
+  if (!ptr || lower.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_lower_bound_multi_pw_aff(copy(), lower.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::lower_bound(isl::multi_val lower) const
+{
+  if (!ptr || lower.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_lower_bound_multi_val(copy(), lower.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map map::polyhedral_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_polyhedral_hull(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::preimage_domain(isl::multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_preimage_domain_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::preimage_domain(isl::multi_pw_aff mpa) const
+{
+  if (!ptr || mpa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_preimage_domain_multi_pw_aff(copy(), mpa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::preimage_domain(isl::pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_preimage_domain_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::preimage_range(isl::multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_preimage_range_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::preimage_range(isl::pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_preimage_range_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::project_out_all_params() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_project_out_all_params(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set map::range() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_range(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::range_factor_domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_range_factor_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::range_factor_range() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_range_factor_range(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::range_product(isl::map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_range_product(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::range_reverse() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_range_reverse(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::reverse() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_reverse(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map map::sample() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_sample(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::subtract(isl::map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_subtract(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::uncurry() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_uncurry(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::unite(isl::map map2) const
+{
+  if (!ptr || map2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_union(copy(), map2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::universe(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_universe(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::basic_map map::unshifted_simple_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_unshifted_simple_hull(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::upper_bound(isl::multi_pw_aff upper) const
+{
+  if (!ptr || upper.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_upper_bound_multi_pw_aff(copy(), upper.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::map map::upper_bound(isl::multi_val upper) const
+{
+  if (!ptr || upper.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_upper_bound_multi_val(copy(), upper.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set map::wrap() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_map_wrap(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const map &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_map_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_map_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_aff
+multi_aff manage(__isl_take isl_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return multi_aff(ptr);
+}
+multi_aff manage_copy(__isl_keep isl_multi_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_multi_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return multi_aff(ptr);
+}
+
+multi_aff::multi_aff()
+    : ptr(nullptr) {}
+
+multi_aff::multi_aff(const multi_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+multi_aff::multi_aff(__isl_take isl_multi_aff *ptr)
+    : ptr(ptr) {}
+
+multi_aff::multi_aff(isl::aff aff)
+{
+  if (aff.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = aff.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_from_aff(aff.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_aff::multi_aff(isl::space space, isl::aff_list list)
+{
+  if (space.is_null() || list.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_from_aff_list(space.release(), list.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_aff::multi_aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_aff &multi_aff::operator=(multi_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_aff::~multi_aff() {
+  if (ptr)
+    isl_multi_aff_free(ptr);
+}
+
+__isl_give isl_multi_aff *multi_aff::copy() const & {
+  return isl_multi_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_aff *multi_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_aff *multi_aff::release() {
+  isl_multi_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx multi_aff::ctx() const {
+  return isl::ctx(isl_multi_aff_get_ctx(ptr));
+}
+
+isl::multi_aff multi_aff::add(isl::multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::add_constant(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_add_constant_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::add_constant(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_add_constant_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::add_constant(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add_constant(isl::val(ctx(), v));
+}
+
+isl::basic_set multi_aff::bind(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_bind(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::bind_domain(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_bind_domain(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::bind_domain_wrapped_domain(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_bind_domain_wrapped_domain(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::domain_map(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_domain_map(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::flat_range_product(isl::multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::floor() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_floor(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff multi_aff::at(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_get_at(get(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::aff multi_aff::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::multi_val multi_aff::constant_multi_val() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_get_constant_multi_val(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_aff::get_constant_multi_val() const
+{
+  return constant_multi_val();
+}
+
+isl::space multi_aff::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space multi_aff::get_space() const
+{
+  return space();
+}
+
+isl::multi_aff multi_aff::gist(isl::set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::identity() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_identity_multi_aff(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::identity_on_domain(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_identity_on_domain_space(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool multi_aff::involves_locals() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_involves_locals(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_aff multi_aff::neg() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_neg(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool multi_aff::plain_is_equal(const isl::multi_aff &multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_plain_is_equal(get(), multi2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_aff multi_aff::product(isl::multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::pullback(isl::multi_aff ma2) const
+{
+  if (!ptr || ma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_pullback_multi_aff(copy(), ma2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::range_map(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_range_map(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::range_product(isl::multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::scale(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_scale_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::scale(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::scale(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale(isl::val(ctx(), v));
+}
+
+isl::multi_aff multi_aff::scale_down(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_scale_down_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::scale_down(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_scale_down_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::scale_down(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale_down(isl::val(ctx(), v));
+}
+
+isl::multi_aff multi_aff::set_at(int pos, isl::aff el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_set_at(copy(), pos, el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+unsigned multi_aff::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_aff multi_aff::sub(isl::multi_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_sub(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_aff multi_aff::zero(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_aff_zero(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_aff &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_multi_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_id
+multi_id manage(__isl_take isl_multi_id *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return multi_id(ptr);
+}
+multi_id manage_copy(__isl_keep isl_multi_id *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_id_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_multi_id_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return multi_id(ptr);
+}
+
+multi_id::multi_id()
+    : ptr(nullptr) {}
+
+multi_id::multi_id(const multi_id &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_id_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+multi_id::multi_id(__isl_take isl_multi_id *ptr)
+    : ptr(ptr) {}
+
+multi_id::multi_id(isl::space space, isl::id_list list)
+{
+  if (space.is_null() || list.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_from_id_list(space.release(), list.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_id::multi_id(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_id &multi_id::operator=(multi_id obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_id::~multi_id() {
+  if (ptr)
+    isl_multi_id_free(ptr);
+}
+
+__isl_give isl_multi_id *multi_id::copy() const & {
+  return isl_multi_id_copy(ptr);
+}
+
+__isl_keep isl_multi_id *multi_id::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_id *multi_id::release() {
+  isl_multi_id *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_id::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx multi_id::ctx() const {
+  return isl::ctx(isl_multi_id_get_ctx(ptr));
+}
+
+isl::multi_id multi_id::flat_range_product(isl::multi_id multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::id multi_id::at(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_get_at(get(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::id multi_id::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::space multi_id::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space multi_id::get_space() const
+{
+  return space();
+}
+
+bool multi_id::plain_is_equal(const isl::multi_id &multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_plain_is_equal(get(), multi2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_id multi_id::range_product(isl::multi_id multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_id multi_id::set_at(int pos, isl::id el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_set_at(copy(), pos, el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_id multi_id::set_at(int pos, const std::string &el) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->set_at(pos, isl::id(ctx(), el));
+}
+
+unsigned multi_id::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_id_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_id &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_id_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_multi_id_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_pw_aff
+multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return multi_pw_aff(ptr);
+}
+multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_multi_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return multi_pw_aff(ptr);
+}
+
+multi_pw_aff::multi_pw_aff()
+    : ptr(nullptr) {}
+
+multi_pw_aff::multi_pw_aff(const multi_pw_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+multi_pw_aff::multi_pw_aff(__isl_take isl_multi_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_pw_aff::multi_pw_aff(isl::multi_aff ma)
+{
+  if (ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ma.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_from_multi_aff(ma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::pw_aff pa)
+{
+  if (pa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pa.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_from_pw_aff(pa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::space space, isl::pw_aff_list list)
+{
+  if (space.is_null() || list.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_from_pw_aff_list(space.release(), list.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::pw_multi_aff pma)
+{
+  if (pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pma.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_from_pw_multi_aff(pma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_pw_aff::multi_pw_aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_pw_aff &multi_pw_aff::operator=(multi_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_pw_aff::~multi_pw_aff() {
+  if (ptr)
+    isl_multi_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::copy() const & {
+  return isl_multi_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_pw_aff *multi_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_pw_aff *multi_pw_aff::release() {
+  isl_multi_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx multi_pw_aff::ctx() const {
+  return isl::ctx(isl_multi_pw_aff_get_ctx(ptr));
+}
+
+isl::multi_pw_aff multi_pw_aff::add(isl::multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::add_constant(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_add_constant_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::add_constant(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_add_constant_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::add_constant(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add_constant(isl::val(ctx(), v));
+}
+
+isl::set multi_pw_aff::bind(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_bind(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::bind_domain(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_bind_domain(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::bind_domain_wrapped_domain(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_bind_domain_wrapped_domain(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::coalesce() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set multi_pw_aff::domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::flat_range_product(isl::multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff multi_pw_aff::at(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_get_at(get(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff multi_pw_aff::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::space multi_pw_aff::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space multi_pw_aff::get_space() const
+{
+  return space();
+}
+
+isl::multi_pw_aff multi_pw_aff::gist(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_gist(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::identity() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_identity_multi_pw_aff(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::identity_on_domain(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_identity_on_domain_space(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::intersect_domain(isl::set domain) const
+{
+  if (!ptr || domain.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_intersect_domain(copy(), domain.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::intersect_params(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_intersect_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool multi_pw_aff::involves_param(const isl::id &id) const
+{
+  if (!ptr || id.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_involves_param_id(get(), id.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool multi_pw_aff::involves_param(const std::string &id) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->involves_param(isl::id(ctx(), id));
+}
+
+bool multi_pw_aff::involves_param(const isl::id_list &list) const
+{
+  if (!ptr || list.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_involves_param_id_list(get(), list.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_pw_aff multi_pw_aff::neg() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_neg(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool multi_pw_aff::plain_is_equal(const isl::multi_pw_aff &multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_plain_is_equal(get(), multi2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_pw_aff multi_pw_aff::product(isl::multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::pullback(isl::multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_pullback_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::pullback(isl::multi_pw_aff mpa2) const
+{
+  if (!ptr || mpa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_pullback_multi_pw_aff(copy(), mpa2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::pullback(isl::pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::range_product(isl::multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::scale(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_scale_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::scale(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::scale(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale(isl::val(ctx(), v));
+}
+
+isl::multi_pw_aff multi_pw_aff::scale_down(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_scale_down_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::scale_down(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_scale_down_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::scale_down(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale_down(isl::val(ctx(), v));
+}
+
+isl::multi_pw_aff multi_pw_aff::set_at(int pos, isl::pw_aff el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_set_at(copy(), pos, el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+unsigned multi_pw_aff::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_pw_aff multi_pw_aff::sub(isl::multi_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_sub(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_pw_aff multi_pw_aff::zero(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_pw_aff_zero(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_pw_aff &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_pw_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_multi_pw_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_union_pw_aff
+multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return multi_union_pw_aff(ptr);
+}
+multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_union_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_multi_union_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return multi_union_pw_aff(ptr);
+}
+
+multi_union_pw_aff::multi_union_pw_aff()
+    : ptr(nullptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(const multi_union_pw_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_union_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+multi_union_pw_aff::multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::multi_pw_aff mpa)
+{
+  if (mpa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = mpa.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_from_multi_pw_aff(mpa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::union_pw_aff upa)
+{
+  if (upa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = upa.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_from_union_pw_aff(upa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::space space, isl::union_pw_aff_list list)
+{
+  if (space.is_null() || list.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_from_union_pw_aff_list(space.release(), list.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_union_pw_aff::multi_union_pw_aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_union_pw_aff &multi_union_pw_aff::operator=(multi_union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_union_pw_aff::~multi_union_pw_aff() {
+  if (ptr)
+    isl_multi_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::copy() const & {
+  return isl_multi_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_multi_union_pw_aff *multi_union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::release() {
+  isl_multi_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx multi_union_pw_aff::ctx() const {
+  return isl::ctx(isl_multi_union_pw_aff_get_ctx(ptr));
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::add(isl::multi_union_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set multi_union_pw_aff::bind(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_bind(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::coalesce() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set multi_union_pw_aff::domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::flat_range_product(isl::multi_union_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_pw_aff multi_union_pw_aff::at(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_get_at(get(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_pw_aff multi_union_pw_aff::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::space multi_union_pw_aff::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space multi_union_pw_aff::get_space() const
+{
+  return space();
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::gist(isl::union_set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::intersect_domain(isl::union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_intersect_domain(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::intersect_params(isl::set params) const
+{
+  if (!ptr || params.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_intersect_params(copy(), params.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::neg() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_neg(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool multi_union_pw_aff::plain_is_equal(const isl::multi_union_pw_aff &multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_plain_is_equal(get(), multi2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::pullback(isl::union_pw_multi_aff upma) const
+{
+  if (!ptr || upma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::range_product(isl::multi_union_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::scale(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_scale_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::scale(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::scale(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale(isl::val(ctx(), v));
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::scale_down(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_scale_down_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::scale_down(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_scale_down_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::scale_down(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale_down(isl::val(ctx(), v));
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::set_at(int pos, isl::union_pw_aff el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_set_at(copy(), pos, el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+unsigned multi_union_pw_aff::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::sub(isl::multi_union_pw_aff multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_sub(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::union_add(isl::multi_union_pw_aff mupa2) const
+{
+  if (!ptr || mupa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_union_add(copy(), mupa2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_union_pw_aff multi_union_pw_aff::zero(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_union_pw_aff_zero(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_union_pw_aff &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_union_pw_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_multi_union_pw_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::multi_val
+multi_val manage(__isl_take isl_multi_val *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return multi_val(ptr);
+}
+multi_val manage_copy(__isl_keep isl_multi_val *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_val_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_multi_val_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return multi_val(ptr);
+}
+
+multi_val::multi_val()
+    : ptr(nullptr) {}
+
+multi_val::multi_val(const multi_val &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_val_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+multi_val::multi_val(__isl_take isl_multi_val *ptr)
+    : ptr(ptr) {}
+
+multi_val::multi_val(isl::space space, isl::val_list list)
+{
+  if (space.is_null() || list.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_from_val_list(space.release(), list.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_val::multi_val(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+multi_val &multi_val::operator=(multi_val obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+multi_val::~multi_val() {
+  if (ptr)
+    isl_multi_val_free(ptr);
+}
+
+__isl_give isl_multi_val *multi_val::copy() const & {
+  return isl_multi_val_copy(ptr);
+}
+
+__isl_keep isl_multi_val *multi_val::get() const {
+  return ptr;
+}
+
+__isl_give isl_multi_val *multi_val::release() {
+  isl_multi_val *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool multi_val::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx multi_val::ctx() const {
+  return isl::ctx(isl_multi_val_get_ctx(ptr));
+}
+
+isl::multi_val multi_val::add(isl::multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_add(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::add(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_add_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::add(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add(isl::val(ctx(), v));
+}
+
+isl::multi_val multi_val::flat_range_product(isl::multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_flat_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val multi_val::at(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_get_at(get(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val multi_val::get_at(int pos) const
+{
+  return at(pos);
+}
+
+isl::space multi_val::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space multi_val::get_space() const
+{
+  return space();
+}
+
+isl::multi_val multi_val::neg() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_neg(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool multi_val::plain_is_equal(const isl::multi_val &multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_plain_is_equal(get(), multi2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_val multi_val::product(isl::multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::range_product(isl::multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_range_product(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::scale(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_scale_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::scale(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::scale(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale(isl::val(ctx(), v));
+}
+
+isl::multi_val multi_val::scale_down(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_scale_down_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::scale_down(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_scale_down_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::scale_down(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale_down(isl::val(ctx(), v));
+}
+
+isl::multi_val multi_val::set_at(int pos, isl::val el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_set_at(copy(), pos, el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::set_at(int pos, long el) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->set_at(pos, isl::val(ctx(), el));
+}
+
+unsigned multi_val::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::multi_val multi_val::sub(isl::multi_val multi2) const
+{
+  if (!ptr || multi2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_sub(copy(), multi2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val multi_val::zero(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_multi_val_zero(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const multi_val &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_multi_val_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_multi_val_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::point
+point manage(__isl_take isl_point *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return point(ptr);
+}
+point manage_copy(__isl_keep isl_point *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_point_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_point_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return point(ptr);
+}
+
+point::point()
+    : ptr(nullptr) {}
+
+point::point(const point &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_point_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+point::point(__isl_take isl_point *ptr)
+    : ptr(ptr) {}
+
+point &point::operator=(point obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+point::~point() {
+  if (ptr)
+    isl_point_free(ptr);
+}
+
+__isl_give isl_point *point::copy() const & {
+  return isl_point_copy(ptr);
+}
+
+__isl_keep isl_point *point::get() const {
+  return ptr;
+}
+
+__isl_give isl_point *point::release() {
+  isl_point *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool point::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx point::ctx() const {
+  return isl::ctx(isl_point_get_ctx(ptr));
+}
+
+isl::multi_val point::multi_val() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_point_get_multi_val(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::multi_val point::get_multi_val() const
+{
+  return multi_val();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const point &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_point_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_point_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::pw_aff
+pw_aff manage(__isl_take isl_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return pw_aff(ptr);
+}
+pw_aff manage_copy(__isl_keep isl_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return pw_aff(ptr);
+}
+
+pw_aff::pw_aff()
+    : ptr(nullptr) {}
+
+pw_aff::pw_aff(const pw_aff &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+pw_aff::pw_aff(__isl_take isl_pw_aff *ptr)
+    : ptr(ptr) {}
+
+pw_aff::pw_aff(isl::aff aff)
+{
+  if (aff.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = aff.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_from_aff(aff.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+pw_aff::pw_aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+pw_aff &pw_aff::operator=(pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+pw_aff::~pw_aff() {
+  if (ptr)
+    isl_pw_aff_free(ptr);
+}
+
+__isl_give isl_pw_aff *pw_aff::copy() const & {
+  return isl_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_pw_aff *pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_pw_aff *pw_aff::release() {
+  isl_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx pw_aff::ctx() const {
+  return isl::ctx(isl_pw_aff_get_ctx(ptr));
+}
+
+isl::pw_aff pw_aff::add(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_add(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::add_constant(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_add_constant_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::add_constant(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add_constant(isl::val(ctx(), v));
+}
+
+isl::aff pw_aff::as_aff() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_as_aff(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::bind(isl::id id) const
+{
+  if (!ptr || id.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_bind_id(copy(), id.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::bind(const std::string &id) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->bind(isl::id(ctx(), id));
+}
+
+isl::pw_aff pw_aff::bind_domain(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_bind_domain(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::bind_domain_wrapped_domain(isl::multi_id tuple) const
+{
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_bind_domain_wrapped_domain(copy(), tuple.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::ceil() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_ceil(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::coalesce() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::cond(isl::pw_aff pwaff_true, isl::pw_aff pwaff_false) const
+{
+  if (!ptr || pwaff_true.is_null() || pwaff_false.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_cond(copy(), pwaff_true.release(), pwaff_false.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::div(isl::pw_aff pa2) const
+{
+  if (!ptr || pa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_div(copy(), pa2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::eq_set(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_eq_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val pw_aff::eval(isl::point pnt) const
+{
+  if (!ptr || pnt.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_eval(copy(), pnt.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::floor() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_floor(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::ge_set(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_ge_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::gist(isl::set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::gt_set(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_gt_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::intersect_domain(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_intersect_domain(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::intersect_params(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_intersect_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool pw_aff::isa_aff() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_isa_aff(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::set pw_aff::le_set(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_le_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::lt_set(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_lt_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::max(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_max(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::min(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_min(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::mod(isl::val mod) const
+{
+  if (!ptr || mod.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_mod_val(copy(), mod.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::mod(long mod) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->mod(isl::val(ctx(), mod));
+}
+
+isl::pw_aff pw_aff::mul(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_mul(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_aff::ne_set(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_ne_set(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::neg() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_neg(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::param_on_domain(isl::set domain, isl::id id)
+{
+  if (domain.is_null() || id.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = domain.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_param_on_domain_id(domain.release(), id.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::pullback(isl::multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_pullback_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::pullback(isl::multi_pw_aff mpa) const
+{
+  if (!ptr || mpa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_pullback_multi_pw_aff(copy(), mpa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::pullback(isl::pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::scale(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_scale_val(copy(), v.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::scale(long v) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale(isl::val(ctx(), v));
+}
+
+isl::pw_aff pw_aff::scale_down(isl::val f) const
+{
+  if (!ptr || f.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_scale_down_val(copy(), f.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::scale_down(long f) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale_down(isl::val(ctx(), f));
+}
+
+isl::pw_aff pw_aff::sub(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_sub(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::subtract_domain(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_subtract_domain(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::tdiv_q(isl::pw_aff pa2) const
+{
+  if (!ptr || pa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_tdiv_q(copy(), pa2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::tdiv_r(isl::pw_aff pa2) const
+{
+  if (!ptr || pa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_tdiv_r(copy(), pa2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_aff pw_aff::union_add(isl::pw_aff pwaff2) const
+{
+  if (!ptr || pwaff2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_union_add(copy(), pwaff2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const pw_aff &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_pw_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::pw_aff_list
+pw_aff_list manage(__isl_take isl_pw_aff_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return pw_aff_list(ptr);
+}
+pw_aff_list manage_copy(__isl_keep isl_pw_aff_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_aff_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_pw_aff_list_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return pw_aff_list(ptr);
+}
+
+pw_aff_list::pw_aff_list()
+    : ptr(nullptr) {}
+
+pw_aff_list::pw_aff_list(const pw_aff_list &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_aff_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+pw_aff_list::pw_aff_list(__isl_take isl_pw_aff_list *ptr)
+    : ptr(ptr) {}
+
+pw_aff_list::pw_aff_list(isl::ctx ctx, int n)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_list_alloc(ctx.release(), n);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+pw_aff_list::pw_aff_list(isl::pw_aff el)
+{
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_list_from_pw_aff(el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+pw_aff_list &pw_aff_list::operator=(pw_aff_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+pw_aff_list::~pw_aff_list() {
+  if (ptr)
+    isl_pw_aff_list_free(ptr);
+}
+
+__isl_give isl_pw_aff_list *pw_aff_list::copy() const & {
+  return isl_pw_aff_list_copy(ptr);
+}
+
+__isl_keep isl_pw_aff_list *pw_aff_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_pw_aff_list *pw_aff_list::release() {
+  isl_pw_aff_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
 
-class union_set {
-  friend inline union_set manage(__isl_take isl_union_set *ptr);
-  friend inline union_set manage_copy(__isl_keep isl_union_set *ptr);
+bool pw_aff_list::is_null() const {
+  return ptr == nullptr;
+}
 
-  isl_union_set *ptr = nullptr;
+isl::ctx pw_aff_list::ctx() const {
+  return isl::ctx(isl_pw_aff_list_get_ctx(ptr));
+}
 
-  inline explicit union_set(__isl_take isl_union_set *ptr);
+isl::pw_aff_list pw_aff_list::add(isl::pw_aff el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_list_add(copy(), el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
 
-public:
-  inline /* implicit */ union_set();
-  inline /* implicit */ union_set(const union_set &obj);
-  inline /* implicit */ union_set(basic_set bset);
-  inline /* implicit */ union_set(set set);
-  inline /* implicit */ union_set(point pnt);
-  inline explicit union_set(ctx ctx, const std::string &str);
-  inline union_set &operator=(union_set obj);
-  inline ~union_set();
-  inline __isl_give isl_union_set *copy() const &;
-  inline __isl_give isl_union_set *copy() && = delete;
-  inline __isl_keep isl_union_set *get() const;
-  inline __isl_give isl_union_set *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
-
-  inline union_set affine_hull() const;
-  inline union_set apply(union_map umap) const;
-  inline union_set coalesce() const;
-  inline union_set compute_divs() const;
-  inline union_set detect_equalities() const;
-  inline void foreach_point(const std::function<void(point)> &fn) const;
-  inline void foreach_set(const std::function<void(set)> &fn) const;
-  inline union_set gist(union_set context) const;
-  inline union_set gist_params(set set) const;
-  inline union_map identity() const;
-  inline union_set intersect(union_set uset2) const;
-  inline union_set intersect_params(set set) const;
-  inline bool is_empty() const;
-  inline bool is_equal(const union_set &uset2) const;
-  inline bool is_strict_subset(const union_set &uset2) const;
-  inline bool is_subset(const union_set &uset2) const;
-  inline union_set lexmax() const;
-  inline union_set lexmin() const;
-  inline union_set polyhedral_hull() const;
-  inline union_set preimage(multi_aff ma) const;
-  inline union_set preimage(pw_multi_aff pma) const;
-  inline union_set preimage(union_pw_multi_aff upma) const;
-  inline point sample_point() const;
-  inline union_set subtract(union_set uset2) const;
-  inline union_set unite(union_set uset2) const;
-  inline union_map unwrap() const;
-};
+isl::pw_aff_list pw_aff_list::clear() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_list_clear(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
 
-// declarations for isl::val
-inline val manage(__isl_take isl_val *ptr);
-inline val manage_copy(__isl_keep isl_val *ptr);
+isl::pw_aff_list pw_aff_list::concat(isl::pw_aff_list list2) const
+{
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_list_concat(copy(), list2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
 
-class val {
-  friend inline val manage(__isl_take isl_val *ptr);
-  friend inline val manage_copy(__isl_keep isl_val *ptr);
+void pw_aff_list::foreach(const std::function<void(isl::pw_aff)> &fn) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::pw_aff)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_pw_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_pw_aff_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
 
-  isl_val *ptr = nullptr;
+isl::pw_aff pw_aff_list::at(int index) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_list_get_at(get(), index);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
 
-  inline explicit val(__isl_take isl_val *ptr);
+isl::pw_aff pw_aff_list::get_at(int index) const
+{
+  return at(index);
+}
 
-public:
-  inline /* implicit */ val();
-  inline /* implicit */ val(const val &obj);
-  inline explicit val(ctx ctx, const std::string &str);
-  inline explicit val(ctx ctx, long i);
-  inline val &operator=(val obj);
-  inline ~val();
-  inline __isl_give isl_val *copy() const &;
-  inline __isl_give isl_val *copy() && = delete;
-  inline __isl_keep isl_val *get() const;
-  inline __isl_give isl_val *release();
-  inline bool is_null() const;
-  inline ctx get_ctx() const;
+unsigned pw_aff_list::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_aff_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
 
-  inline val abs() const;
-  inline bool abs_eq(const val &v2) const;
-  inline val add(val v2) const;
-  inline val ceil() const;
-  inline int cmp_si(long i) const;
-  inline val div(val v2) const;
-  inline bool eq(const val &v2) const;
-  inline val floor() const;
-  inline val gcd(val v2) const;
-  inline bool ge(const val &v2) const;
-  inline bool gt(const val &v2) const;
-  static inline val infty(ctx ctx);
-  inline val inv() const;
-  inline bool is_divisible_by(const val &v2) const;
-  inline bool is_infty() const;
-  inline bool is_int() const;
-  inline bool is_nan() const;
-  inline bool is_neg() const;
-  inline bool is_neginfty() const;
-  inline bool is_negone() const;
-  inline bool is_nonneg() const;
-  inline bool is_nonpos() const;
-  inline bool is_one() const;
-  inline bool is_pos() const;
-  inline bool is_rat() const;
-  inline bool is_zero() const;
-  inline bool le(const val &v2) const;
-  inline bool lt(const val &v2) const;
-  inline val max(val v2) const;
-  inline val min(val v2) const;
-  inline val mod(val v2) const;
-  inline val mul(val v2) const;
-  static inline val nan(ctx ctx);
-  inline bool ne(const val &v2) const;
-  inline val neg() const;
-  static inline val neginfty(ctx ctx);
-  static inline val negone(ctx ctx);
-  static inline val one(ctx ctx);
-  inline val pow2() const;
-  inline int sgn() const;
-  inline val sub(val v2) const;
-  inline val trunc() const;
-  static inline val zero(ctx ctx);
-};
+inline std::ostream &operator<<(std::ostream &os, const pw_aff_list &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_aff_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_pw_aff_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
 
-// implementations for isl::aff
-aff manage(__isl_take isl_aff *ptr) {
+// implementations for isl::pw_multi_aff
+pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return aff(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return pw_multi_aff(ptr);
 }
-aff manage_copy(__isl_keep isl_aff *ptr) {
+pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_aff_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_multi_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_pw_multi_aff_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return aff(ptr);
+    exception::throw_last_error(saved_ctx);
+  return pw_multi_aff(ptr);
 }
 
-aff::aff()
+pw_multi_aff::pw_multi_aff()
     : ptr(nullptr) {}
 
-aff::aff(const aff &obj)
+pw_multi_aff::pw_multi_aff(const pw_multi_aff &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_multi_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-aff::aff(__isl_take isl_aff *ptr)
+pw_multi_aff::pw_multi_aff(__isl_take isl_pw_multi_aff *ptr)
     : ptr(ptr) {}
 
-aff::aff(ctx ctx, const std::string &str)
+pw_multi_aff::pw_multi_aff(isl::multi_aff ma)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_read_from_str(ctx.release(), str.c_str());
+  if (ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ma.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_from_multi_aff(ma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
 
-aff &aff::operator=(aff obj) {
+pw_multi_aff::pw_multi_aff(isl::pw_aff pa)
+{
+  if (pa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pa.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_from_pw_aff(pa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+pw_multi_aff::pw_multi_aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+pw_multi_aff &pw_multi_aff::operator=(pw_multi_aff obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-aff::~aff() {
+pw_multi_aff::~pw_multi_aff() {
   if (ptr)
-    isl_aff_free(ptr);
+    isl_pw_multi_aff_free(ptr);
 }
 
-__isl_give isl_aff *aff::copy() const & {
-  return isl_aff_copy(ptr);
+__isl_give isl_pw_multi_aff *pw_multi_aff::copy() const & {
+  return isl_pw_multi_aff_copy(ptr);
 }
 
-__isl_keep isl_aff *aff::get() const {
+__isl_keep isl_pw_multi_aff *pw_multi_aff::get() const {
   return ptr;
 }
 
-__isl_give isl_aff *aff::release() {
-  isl_aff *tmp = ptr;
+__isl_give isl_pw_multi_aff *pw_multi_aff::release() {
+  isl_pw_multi_aff *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool aff::is_null() const {
+bool pw_multi_aff::is_null() const {
   return ptr == nullptr;
 }
 
-ctx aff::get_ctx() const {
-  return ctx(isl_aff_get_ctx(ptr));
+isl::ctx pw_multi_aff::ctx() const {
+  return isl::ctx(isl_pw_multi_aff_get_ctx(ptr));
 }
 
-aff aff::add(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::add(isl::pw_multi_aff pma2) const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_add(copy(), aff2.release());
+  if (!ptr || pma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_add(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff pw_multi_aff::add_constant(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_add_constant_multi_val(copy(), mv.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff pw_multi_aff::add_constant(isl::val v) const
+{
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_add_constant_val(copy(), v.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::ceil() const
+isl::pw_multi_aff pw_multi_aff::add_constant(long v) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_ceil(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add_constant(isl::val(ctx(), v));
+}
+
+isl::multi_aff pw_multi_aff::as_multi_aff() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_as_multi_aff(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::div(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::bind_domain(isl::multi_id tuple) const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_div(copy(), aff2.release());
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_bind_domain(copy(), tuple.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set aff::eq_set(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::bind_domain_wrapped_domain(isl::multi_id tuple) const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_eq_set(copy(), aff2.release());
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_bind_domain_wrapped_domain(copy(), tuple.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::floor() const
+isl::pw_multi_aff pw_multi_aff::coalesce() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_floor(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_coalesce(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::set pw_multi_aff::domain() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff pw_multi_aff::flat_range_product(isl::pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_flat_range_product(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+void pw_multi_aff::foreach_piece(const std::function<void(isl::set, isl::multi_aff)> &fn) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::set, isl::multi_aff)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_set *arg_0, isl_multi_aff *arg_1, void *arg_2) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_2);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0), manage(arg_1));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_pw_multi_aff_foreach_piece(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
+
+isl::space pw_multi_aff::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space pw_multi_aff::get_space() const
+{
+  return space();
+}
+
+isl::pw_multi_aff pw_multi_aff::gist(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_gist(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff pw_multi_aff::intersect_domain(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_intersect_domain(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff pw_multi_aff::intersect_params(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_intersect_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool pw_multi_aff::isa_multi_aff() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_isa_multi_aff(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+unsigned pw_multi_aff::n_piece() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_n_piece(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::pw_multi_aff pw_multi_aff::product(isl::pw_multi_aff pma2) const
+{
+  if (!ptr || pma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_product(copy(), pma2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::pw_multi_aff pw_multi_aff::pullback(isl::multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_pullback_multi_aff(copy(), ma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set aff::ge_set(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::pullback(isl::pw_multi_aff pma2) const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_ge_set(copy(), aff2.release());
+  if (!ptr || pma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_pullback_pw_multi_aff(copy(), pma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set aff::gt_set(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::range_factor_domain() const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_gt_set(copy(), aff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_range_factor_domain(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set aff::le_set(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::range_factor_range() const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_le_set(copy(), aff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_range_factor_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set aff::lt_set(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::range_product(isl::pw_multi_aff pma2) const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_lt_set(copy(), aff2.release());
+  if (!ptr || pma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_range_product(copy(), pma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::mod(val mod) const
+isl::pw_multi_aff pw_multi_aff::scale(isl::val v) const
 {
-  if (!ptr || mod.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_mod_val(copy(), mod.release());
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_scale_val(copy(), v.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::mul(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::scale(long v) const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_mul(copy(), aff2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale(isl::val(ctx(), v));
 }
 
-set aff::ne_set(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::scale_down(isl::val v) const
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_ne_set(copy(), aff2.release());
+  if (!ptr || v.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_scale_down_val(copy(), v.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::neg() const
+isl::pw_multi_aff pw_multi_aff::scale_down(long v) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_neg(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->scale_down(isl::val(ctx(), v));
 }
 
-aff aff::pullback(multi_aff ma) const
+isl::pw_multi_aff pw_multi_aff::sub(isl::pw_multi_aff pma2) const
 {
-  if (!ptr || ma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_pullback_multi_aff(copy(), ma.release());
+  if (!ptr || pma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_sub(copy(), pma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::scale(val v) const
+isl::pw_multi_aff pw_multi_aff::subtract_domain(isl::set set) const
 {
-  if (!ptr || v.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_scale_val(copy(), v.release());
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_subtract_domain(copy(), set.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::scale_down(val v) const
+isl::pw_multi_aff pw_multi_aff::union_add(isl::pw_multi_aff pma2) const
 {
-  if (!ptr || v.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_scale_down_val(copy(), v.release());
+  if (!ptr || pma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_union_add(copy(), pma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-aff aff::sub(aff aff2) const
+isl::pw_multi_aff pw_multi_aff::zero(isl::space space)
 {
-  if (!ptr || aff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_aff_sub(copy(), aff2.release());
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_zero(space.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::ast_build
-ast_build manage(__isl_take isl_ast_build *ptr) {
+inline std::ostream &operator<<(std::ostream &os, const pw_multi_aff &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_multi_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_pw_multi_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::pw_multi_aff_list
+pw_multi_aff_list manage(__isl_take isl_pw_multi_aff_list *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return ast_build(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return pw_multi_aff_list(ptr);
 }
-ast_build manage_copy(__isl_keep isl_ast_build *ptr) {
+pw_multi_aff_list manage_copy(__isl_keep isl_pw_multi_aff_list *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_ast_build_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_ast_build_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_multi_aff_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_pw_multi_aff_list_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return ast_build(ptr);
+    exception::throw_last_error(saved_ctx);
+  return pw_multi_aff_list(ptr);
 }
 
-ast_build::ast_build()
+pw_multi_aff_list::pw_multi_aff_list()
     : ptr(nullptr) {}
 
-ast_build::ast_build(const ast_build &obj)
+pw_multi_aff_list::pw_multi_aff_list(const pw_multi_aff_list &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_ast_build_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_multi_aff_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-ast_build::ast_build(__isl_take isl_ast_build *ptr)
+pw_multi_aff_list::pw_multi_aff_list(__isl_take isl_pw_multi_aff_list *ptr)
     : ptr(ptr) {}
 
-ast_build::ast_build(ctx ctx)
+pw_multi_aff_list::pw_multi_aff_list(isl::ctx ctx, int n)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_alloc(ctx.release());
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_list_alloc(ctx.release(), n);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
 
-ast_build &ast_build::operator=(ast_build obj) {
+pw_multi_aff_list::pw_multi_aff_list(isl::pw_multi_aff el)
+{
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_list_from_pw_multi_aff(el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+pw_multi_aff_list &pw_multi_aff_list::operator=(pw_multi_aff_list obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-ast_build::~ast_build() {
+pw_multi_aff_list::~pw_multi_aff_list() {
   if (ptr)
-    isl_ast_build_free(ptr);
+    isl_pw_multi_aff_list_free(ptr);
 }
 
-__isl_give isl_ast_build *ast_build::copy() const & {
-  return isl_ast_build_copy(ptr);
+__isl_give isl_pw_multi_aff_list *pw_multi_aff_list::copy() const & {
+  return isl_pw_multi_aff_list_copy(ptr);
 }
 
-__isl_keep isl_ast_build *ast_build::get() const {
+__isl_keep isl_pw_multi_aff_list *pw_multi_aff_list::get() const {
   return ptr;
 }
 
-__isl_give isl_ast_build *ast_build::release() {
-  isl_ast_build *tmp = ptr;
+__isl_give isl_pw_multi_aff_list *pw_multi_aff_list::release() {
+  isl_pw_multi_aff_list *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool ast_build::is_null() const {
+bool pw_multi_aff_list::is_null() const {
   return ptr == nullptr;
 }
 
-ctx ast_build::get_ctx() const {
-  return ctx(isl_ast_build_get_ctx(ptr));
+isl::ctx pw_multi_aff_list::ctx() const {
+  return isl::ctx(isl_pw_multi_aff_list_get_ctx(ptr));
 }
 
-ast_expr ast_build::access_from(pw_multi_aff pma) const
+isl::pw_multi_aff_list pw_multi_aff_list::add(isl::pw_multi_aff el) const
 {
-  if (!ptr || pma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_access_from_pw_multi_aff(get(), pma.release());
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_list_add(copy(), el.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-ast_expr ast_build::access_from(multi_pw_aff mpa) const
+isl::pw_multi_aff_list pw_multi_aff_list::clear() const
 {
-  if (!ptr || mpa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_access_from_multi_pw_aff(get(), mpa.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_list_clear(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-ast_expr ast_build::call_from(pw_multi_aff pma) const
+isl::pw_multi_aff_list pw_multi_aff_list::concat(isl::pw_multi_aff_list list2) const
 {
-  if (!ptr || pma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_call_from_pw_multi_aff(get(), pma.release());
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_list_concat(copy(), list2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-ast_expr ast_build::call_from(multi_pw_aff mpa) const
+void pw_multi_aff_list::foreach(const std::function<void(isl::pw_multi_aff)> &fn) const
 {
-  if (!ptr || mpa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_call_from_multi_pw_aff(get(), mpa.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::pw_multi_aff)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_pw_multi_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_pw_multi_aff_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
 }
 
-ast_expr ast_build::expr_from(set set) const
+isl::pw_multi_aff pw_multi_aff_list::at(int index) const
 {
-  if (!ptr || set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_expr_from_set(get(), set.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_list_get_at(get(), index);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-ast_expr ast_build::expr_from(pw_aff pa) const
+isl::pw_multi_aff pw_multi_aff_list::get_at(int index) const
 {
-  if (!ptr || pa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_expr_from_pw_aff(get(), pa.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return at(index);
 }
 
-ast_build ast_build::from_context(set set)
+unsigned pw_multi_aff_list::size() const
 {
-  if (set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = set.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_from_context(set.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_pw_multi_aff_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-ast_node ast_build::node_from_schedule_map(union_map schedule) const
+inline std::ostream &operator<<(std::ostream &os, const pw_multi_aff_list &obj)
 {
-  if (!ptr || schedule.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_build_node_from_schedule_map(get(), schedule.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_pw_multi_aff_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_pw_multi_aff_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::ast_expr
-ast_expr manage(__isl_take isl_ast_expr *ptr) {
+// implementations for isl::schedule
+schedule manage(__isl_take isl_schedule *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return ast_expr(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return schedule(ptr);
 }
-ast_expr manage_copy(__isl_keep isl_ast_expr *ptr) {
+schedule manage_copy(__isl_keep isl_schedule *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_ast_expr_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_ast_expr_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_schedule_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return ast_expr(ptr);
+    exception::throw_last_error(saved_ctx);
+  return schedule(ptr);
 }
 
-ast_expr::ast_expr()
+schedule::schedule()
     : ptr(nullptr) {}
 
-ast_expr::ast_expr(const ast_expr &obj)
+schedule::schedule(const schedule &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_ast_expr_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-ast_expr::ast_expr(__isl_take isl_ast_expr *ptr)
+schedule::schedule(__isl_take isl_schedule *ptr)
     : ptr(ptr) {}
 
+schedule::schedule(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
 
-ast_expr &ast_expr::operator=(ast_expr obj) {
+schedule &schedule::operator=(schedule obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-ast_expr::~ast_expr() {
+schedule::~schedule() {
   if (ptr)
-    isl_ast_expr_free(ptr);
+    isl_schedule_free(ptr);
 }
 
-__isl_give isl_ast_expr *ast_expr::copy() const & {
-  return isl_ast_expr_copy(ptr);
+__isl_give isl_schedule *schedule::copy() const & {
+  return isl_schedule_copy(ptr);
 }
 
-__isl_keep isl_ast_expr *ast_expr::get() const {
+__isl_keep isl_schedule *schedule::get() const {
   return ptr;
 }
 
-__isl_give isl_ast_expr *ast_expr::release() {
-  isl_ast_expr *tmp = ptr;
+__isl_give isl_schedule *schedule::release() {
+  isl_schedule *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool ast_expr::is_null() const {
+bool schedule::is_null() const {
   return ptr == nullptr;
 }
 
-ctx ast_expr::get_ctx() const {
-  return ctx(isl_ast_expr_get_ctx(ptr));
+isl::ctx schedule::ctx() const {
+  return isl::ctx(isl_schedule_get_ctx(ptr));
 }
 
-std::string ast_expr::to_C_str() const
+isl::schedule schedule::from_domain(isl::union_set domain)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_expr_to_C_str(get());
-  std::string tmp(res);
-  free(res);
-  return tmp;
-}
-
-// implementations for isl::ast_node
-ast_node manage(__isl_take isl_ast_node *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return ast_node(ptr);
-}
-ast_node manage_copy(__isl_keep isl_ast_node *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_ast_node_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_ast_node_copy(ptr);
-  if (!ptr)
-    exception::throw_last_error(ctx);
-  return ast_node(ptr);
+  if (domain.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = domain.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_from_domain(domain.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-ast_node::ast_node()
-    : ptr(nullptr) {}
-
-ast_node::ast_node(const ast_node &obj)
-    : ptr(nullptr)
+isl::union_map schedule::map() const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_ast_node_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
-}
-
-ast_node::ast_node(__isl_take isl_ast_node *ptr)
-    : ptr(ptr) {}
-
-
-ast_node &ast_node::operator=(ast_node obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
-}
-
-ast_node::~ast_node() {
-  if (ptr)
-    isl_ast_node_free(ptr);
-}
-
-__isl_give isl_ast_node *ast_node::copy() const & {
-  return isl_ast_node_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_get_map(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_keep isl_ast_node *ast_node::get() const {
-  return ptr;
+isl::union_map schedule::get_map() const
+{
+  return map();
 }
 
-__isl_give isl_ast_node *ast_node::release() {
-  isl_ast_node *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::schedule_node schedule::root() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_get_root(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool ast_node::is_null() const {
-  return ptr == nullptr;
+isl::schedule_node schedule::get_root() const
+{
+  return root();
 }
 
-ctx ast_node::get_ctx() const {
-  return ctx(isl_ast_node_get_ctx(ptr));
+isl::schedule schedule::pullback(isl::union_pw_multi_aff upma) const
+{
+  if (!ptr || upma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_pullback_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-std::string ast_node::to_C_str() const
+inline std::ostream &operator<<(std::ostream &os, const schedule &obj)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_ast_node_to_C_str(get());
-  std::string tmp(res);
-  free(res);
-  return tmp;
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::basic_map
-basic_map manage(__isl_take isl_basic_map *ptr) {
+// implementations for isl::schedule_constraints
+schedule_constraints manage(__isl_take isl_schedule_constraints *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return basic_map(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return schedule_constraints(ptr);
 }
-basic_map manage_copy(__isl_keep isl_basic_map *ptr) {
+schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_basic_map_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_basic_map_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_constraints_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_schedule_constraints_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return basic_map(ptr);
+    exception::throw_last_error(saved_ctx);
+  return schedule_constraints(ptr);
 }
 
-basic_map::basic_map()
+schedule_constraints::schedule_constraints()
     : ptr(nullptr) {}
 
-basic_map::basic_map(const basic_map &obj)
+schedule_constraints::schedule_constraints(const schedule_constraints &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_basic_map_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_constraints_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-basic_map::basic_map(__isl_take isl_basic_map *ptr)
+schedule_constraints::schedule_constraints(__isl_take isl_schedule_constraints *ptr)
     : ptr(ptr) {}
 
-basic_map::basic_map(ctx ctx, const std::string &str)
+schedule_constraints::schedule_constraints(isl::ctx ctx, const std::string &str)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_read_from_str(ctx.release(), str.c_str());
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_read_from_str(ctx.release(), str.c_str());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
 
-basic_map &basic_map::operator=(basic_map obj) {
+schedule_constraints &schedule_constraints::operator=(schedule_constraints obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-basic_map::~basic_map() {
+schedule_constraints::~schedule_constraints() {
   if (ptr)
-    isl_basic_map_free(ptr);
+    isl_schedule_constraints_free(ptr);
 }
 
-__isl_give isl_basic_map *basic_map::copy() const & {
-  return isl_basic_map_copy(ptr);
+__isl_give isl_schedule_constraints *schedule_constraints::copy() const & {
+  return isl_schedule_constraints_copy(ptr);
 }
 
-__isl_keep isl_basic_map *basic_map::get() const {
+__isl_keep isl_schedule_constraints *schedule_constraints::get() const {
   return ptr;
 }
 
-__isl_give isl_basic_map *basic_map::release() {
-  isl_basic_map *tmp = ptr;
+__isl_give isl_schedule_constraints *schedule_constraints::release() {
+  isl_schedule_constraints *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool basic_map::is_null() const {
+bool schedule_constraints::is_null() const {
   return ptr == nullptr;
 }
 
-ctx basic_map::get_ctx() const {
-  return ctx(isl_basic_map_get_ctx(ptr));
+isl::ctx schedule_constraints::ctx() const {
+  return isl::ctx(isl_schedule_constraints_get_ctx(ptr));
 }
 
-basic_map basic_map::affine_hull() const
+isl::schedule schedule_constraints::compute_schedule() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_affine_hull(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_compute_schedule(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::apply_domain(basic_map bmap2) const
+isl::union_map schedule_constraints::coincidence() const
 {
-  if (!ptr || bmap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_apply_domain(copy(), bmap2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_coincidence(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::apply_range(basic_map bmap2) const
+isl::union_map schedule_constraints::get_coincidence() const
 {
-  if (!ptr || bmap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_apply_range(copy(), bmap2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return coincidence();
 }
 
-basic_set basic_map::deltas() const
+isl::union_map schedule_constraints::conditional_validity() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_deltas(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_conditional_validity(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::detect_equalities() const
+isl::union_map schedule_constraints::get_conditional_validity() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_detect_equalities(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return conditional_validity();
 }
 
-basic_map basic_map::flatten() const
+isl::union_map schedule_constraints::conditional_validity_condition() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_flatten(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_conditional_validity_condition(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::flatten_domain() const
+isl::union_map schedule_constraints::get_conditional_validity_condition() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_flatten_domain(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return conditional_validity_condition();
 }
 
-basic_map basic_map::flatten_range() const
+isl::set schedule_constraints::context() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_flatten_range(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_context(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::gist(basic_map context) const
+isl::set schedule_constraints::get_context() const
 {
-  if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_gist(copy(), context.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return context();
 }
 
-basic_map basic_map::intersect(basic_map bmap2) const
+isl::union_set schedule_constraints::domain() const
 {
-  if (!ptr || bmap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_intersect(copy(), bmap2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_domain(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::intersect_domain(basic_set bset) const
+isl::union_set schedule_constraints::get_domain() const
 {
-  if (!ptr || bset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_intersect_domain(copy(), bset.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return domain();
 }
 
-basic_map basic_map::intersect_range(basic_set bset) const
+isl::union_map schedule_constraints::proximity() const
 {
-  if (!ptr || bset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_intersect_range(copy(), bset.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_proximity(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool basic_map::is_empty() const
+isl::union_map schedule_constraints::get_proximity() const
+{
+  return proximity();
+}
+
+isl::union_map schedule_constraints::validity() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_is_empty(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_get_validity(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool basic_map::is_equal(const basic_map &bmap2) const
+isl::union_map schedule_constraints::get_validity() const
 {
-  if (!ptr || bmap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_is_equal(get(), bmap2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  return validity();
 }
 
-bool basic_map::is_subset(const basic_map &bmap2) const
+isl::schedule_constraints schedule_constraints::on_domain(isl::union_set domain)
 {
-  if (!ptr || bmap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_is_subset(get(), bmap2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  if (domain.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = domain.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_on_domain(domain.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-map basic_map::lexmax() const
+isl::schedule_constraints schedule_constraints::set_coincidence(isl::union_map coincidence) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_lexmax(copy());
+  if (!ptr || coincidence.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_coincidence(copy(), coincidence.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map basic_map::lexmin() const
+isl::schedule_constraints schedule_constraints::set_conditional_validity(isl::union_map condition, isl::union_map validity) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_lexmin(copy());
+  if (!ptr || condition.is_null() || validity.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_conditional_validity(copy(), condition.release(), validity.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::reverse() const
+isl::schedule_constraints schedule_constraints::set_context(isl::set context) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_reverse(copy());
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_context(copy(), context.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_map basic_map::sample() const
+isl::schedule_constraints schedule_constraints::set_proximity(isl::union_map proximity) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_sample(copy());
+  if (!ptr || proximity.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_proximity(copy(), proximity.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map basic_map::unite(basic_map bmap2) const
+isl::schedule_constraints schedule_constraints::set_validity(isl::union_map validity) const
 {
-  if (!ptr || bmap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_map_union(copy(), bmap2.release());
+  if (!ptr || validity.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_constraints_set_validity(copy(), validity.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::basic_set
-basic_set manage(__isl_take isl_basic_set *ptr) {
+inline std::ostream &operator<<(std::ostream &os, const schedule_constraints &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_constraints_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_constraints_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::schedule_node
+schedule_node manage(__isl_take isl_schedule_node *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return basic_set(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return schedule_node(ptr);
 }
-basic_set manage_copy(__isl_keep isl_basic_set *ptr) {
+schedule_node manage_copy(__isl_keep isl_schedule_node *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_basic_set_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_basic_set_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_schedule_node_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return basic_set(ptr);
+    exception::throw_last_error(saved_ctx);
+  return schedule_node(ptr);
 }
 
-basic_set::basic_set()
+schedule_node::schedule_node()
     : ptr(nullptr) {}
 
-basic_set::basic_set(const basic_set &obj)
+schedule_node::schedule_node(const schedule_node &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_basic_set_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-basic_set::basic_set(__isl_take isl_basic_set *ptr)
+schedule_node::schedule_node(__isl_take isl_schedule_node *ptr)
     : ptr(ptr) {}
 
-basic_set::basic_set(ctx ctx, const std::string &str)
-{
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_read_from_str(ctx.release(), str.c_str());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
-}
-basic_set::basic_set(point pnt)
-{
-  if (pnt.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pnt.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_from_point(pnt.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
-}
-
-basic_set &basic_set::operator=(basic_set obj) {
+schedule_node &schedule_node::operator=(schedule_node obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-basic_set::~basic_set() {
+schedule_node::~schedule_node() {
   if (ptr)
-    isl_basic_set_free(ptr);
+    isl_schedule_node_free(ptr);
 }
 
-__isl_give isl_basic_set *basic_set::copy() const & {
-  return isl_basic_set_copy(ptr);
+__isl_give isl_schedule_node *schedule_node::copy() const & {
+  return isl_schedule_node_copy(ptr);
 }
 
-__isl_keep isl_basic_set *basic_set::get() const {
+__isl_keep isl_schedule_node *schedule_node::get() const {
   return ptr;
 }
 
-__isl_give isl_basic_set *basic_set::release() {
-  isl_basic_set *tmp = ptr;
+__isl_give isl_schedule_node *schedule_node::release() {
+  isl_schedule_node *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool basic_set::is_null() const {
+bool schedule_node::is_null() const {
   return ptr == nullptr;
 }
 
-ctx basic_set::get_ctx() const {
-  return ctx(isl_basic_set_get_ctx(ptr));
+template <typename T, typename>
+bool schedule_node::isa_type(T subtype) const
+{
+  if (is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return isl_schedule_node_get_type(get()) == subtype;
+}
+template <class T>
+bool schedule_node::isa() const
+{
+  return isa_type<decltype(T::type)>(T::type);
+}
+template <class T>
+T schedule_node::as() const
+{
+ if (!isa<T>())
+    exception::throw_invalid("not an object of the requested subtype", __FILE__, __LINE__);
+  return T(copy());
+}
+
+isl::ctx schedule_node::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-basic_set basic_set::affine_hull() const
+isl::schedule_node schedule_node::ancestor(int generation) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_affine_hull(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_ancestor(copy(), generation);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_set basic_set::apply(basic_map bmap) const
+isl::schedule_node schedule_node::child(int pos) const
 {
-  if (!ptr || bmap.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_apply(copy(), bmap.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_child(copy(), pos);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_set basic_set::detect_equalities() const
+bool schedule_node::every_descendant(const std::function<bool(isl::schedule_node)> &test) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_detect_equalities(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct test_data {
+    std::function<bool(isl::schedule_node)> func;
+    std::exception_ptr eptr;
+  } test_data = { test };
+  auto test_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct test_data *>(arg_1);
+    ISL_CPP_TRY {
+      auto ret = (data->func)(manage_copy(arg_0));
+      return ret ? isl_bool_true : isl_bool_false;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_bool_error;
+    }
+  };
+  auto res = isl_schedule_node_every_descendant(get(), test_lambda, &test_data);
+  if (test_data.eptr)
+    std::rethrow_exception(test_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-val basic_set::dim_max_val(int pos) const
+isl::schedule_node schedule_node::first_child() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_dim_max_val(copy(), pos);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_first_child(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_set basic_set::flatten() const
+void schedule_node::foreach_ancestor_top_down(const std::function<void(isl::schedule_node)> &fn) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_flatten(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::schedule_node)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage_copy(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_schedule_node_foreach_ancestor_top_down(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
 }
 
-basic_set basic_set::gist(basic_set context) const
+void schedule_node::foreach_descendant_top_down(const std::function<bool(isl::schedule_node)> &fn) const
 {
-  if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_gist(copy(), context.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<bool(isl::schedule_node)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      auto ret = (data->func)(manage_copy(arg_0));
+      return ret ? isl_bool_true : isl_bool_false;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_bool_error;
+    }
+  };
+  auto res = isl_schedule_node_foreach_descendant_top_down(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
 }
 
-basic_set basic_set::intersect(basic_set bset2) const
+isl::schedule_node schedule_node::from_domain(isl::union_set domain)
 {
-  if (!ptr || bset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_intersect(copy(), bset2.release());
+  if (domain.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = domain.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_from_domain(domain.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_set basic_set::intersect_params(basic_set bset2) const
+isl::schedule_node schedule_node::from_extension(isl::union_map extension)
 {
-  if (!ptr || bset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_intersect_params(copy(), bset2.release());
+  if (extension.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = extension.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_from_extension(extension.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool basic_set::is_empty() const
+unsigned schedule_node::ancestor_child_position(const isl::schedule_node &ancestor) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_is_empty(get());
+  if (!ptr || ancestor.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_ancestor_child_position(get(), ancestor.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool basic_set::is_equal(const basic_set &bset2) const
+unsigned schedule_node::get_ancestor_child_position(const isl::schedule_node &ancestor) const
 {
-  if (!ptr || bset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_is_equal(get(), bset2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  return ancestor_child_position(ancestor);
 }
 
-bool basic_set::is_subset(const basic_set &bset2) const
+unsigned schedule_node::child_position() const
 {
-  if (!ptr || bset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_is_subset(get(), bset2.get());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_child_position(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool basic_set::is_wrapping() const
+unsigned schedule_node::get_child_position() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_is_wrapping(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  return child_position();
 }
 
-set basic_set::lexmax() const
+isl::multi_union_pw_aff schedule_node::prefix_schedule_multi_union_pw_aff() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_lexmax(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set basic_set::lexmin() const
+isl::multi_union_pw_aff schedule_node::get_prefix_schedule_multi_union_pw_aff() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_lexmin(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return prefix_schedule_multi_union_pw_aff();
 }
 
-basic_set basic_set::sample() const
+isl::union_map schedule_node::prefix_schedule_union_map() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_sample(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_prefix_schedule_union_map(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-point basic_set::sample_point() const
+isl::union_map schedule_node::get_prefix_schedule_union_map() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_sample_point(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return prefix_schedule_union_map();
 }
 
-set basic_set::unite(basic_set bset2) const
+isl::union_pw_multi_aff schedule_node::prefix_schedule_union_pw_multi_aff() const
 {
-  if (!ptr || bset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_basic_set_union(copy(), bset2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::map
-map manage(__isl_take isl_map *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return map(ptr);
-}
-map manage_copy(__isl_keep isl_map *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_map_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_map_copy(ptr);
-  if (!ptr)
-    exception::throw_last_error(ctx);
-  return map(ptr);
+isl::union_pw_multi_aff schedule_node::get_prefix_schedule_union_pw_multi_aff() const
+{
+  return prefix_schedule_union_pw_multi_aff();
 }
 
-map::map()
-    : ptr(nullptr) {}
-
-map::map(const map &obj)
-    : ptr(nullptr)
+isl::schedule schedule_node::schedule() const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_map_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_schedule(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-map::map(__isl_take isl_map *ptr)
-    : ptr(ptr) {}
+isl::schedule schedule_node::get_schedule() const
+{
+  return schedule();
+}
 
-map::map(ctx ctx, const std::string &str)
+isl::schedule_node schedule_node::shared_ancestor(const isl::schedule_node &node2) const
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_read_from_str(ctx.release(), str.c_str());
+  if (!ptr || node2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_shared_ancestor(get(), node2.get());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-map::map(basic_map bmap)
+
+isl::schedule_node schedule_node::get_shared_ancestor(const isl::schedule_node &node2) const
 {
-  if (bmap.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = bmap.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_from_basic_map(bmap.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+  return shared_ancestor(node2);
 }
 
-map &map::operator=(map obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+unsigned schedule_node::tree_depth() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_get_tree_depth(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-map::~map() {
-  if (ptr)
-    isl_map_free(ptr);
+unsigned schedule_node::get_tree_depth() const
+{
+  return tree_depth();
 }
 
-__isl_give isl_map *map::copy() const & {
-  return isl_map_copy(ptr);
+isl::schedule_node schedule_node::graft_after(isl::schedule_node graft) const
+{
+  if (!ptr || graft.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_graft_after(copy(), graft.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_keep isl_map *map::get() const {
-  return ptr;
+isl::schedule_node schedule_node::graft_before(isl::schedule_node graft) const
+{
+  if (!ptr || graft.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_graft_before(copy(), graft.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_give isl_map *map::release() {
-  isl_map *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+bool schedule_node::has_children() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_has_children(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-bool map::is_null() const {
-  return ptr == nullptr;
+bool schedule_node::has_next_sibling() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_has_next_sibling(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-ctx map::get_ctx() const {
-  return ctx(isl_map_get_ctx(ptr));
+bool schedule_node::has_parent() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_has_parent(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-basic_map map::affine_hull() const
+bool schedule_node::has_previous_sibling() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_affine_hull(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_has_previous_sibling(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-map map::apply_domain(map map2) const
+isl::schedule_node schedule_node::insert_context(isl::set context) const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_apply_domain(copy(), map2.release());
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_insert_context(copy(), context.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::apply_range(map map2) const
+isl::schedule_node schedule_node::insert_filter(isl::union_set filter) const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_apply_range(copy(), map2.release());
+  if (!ptr || filter.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_insert_filter(copy(), filter.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::coalesce() const
+isl::schedule_node schedule_node::insert_guard(isl::set context) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_coalesce(copy());
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_insert_guard(copy(), context.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::complement() const
+isl::schedule_node schedule_node::insert_mark(isl::id mark) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_complement(copy());
+  if (!ptr || mark.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_insert_mark(copy(), mark.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set map::deltas() const
+isl::schedule_node schedule_node::insert_mark(const std::string &mark) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_deltas(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->insert_mark(isl::id(ctx(), mark));
 }
 
-map map::detect_equalities() const
+isl::schedule_node schedule_node::insert_partial_schedule(isl::multi_union_pw_aff schedule) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_detect_equalities(copy());
+  if (!ptr || schedule.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_insert_partial_schedule(copy(), schedule.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::flatten() const
+isl::schedule_node schedule_node::insert_sequence(isl::union_set_list filters) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_flatten(copy());
+  if (!ptr || filters.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_insert_sequence(copy(), filters.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::flatten_domain() const
+isl::schedule_node schedule_node::insert_set(isl::union_set_list filters) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_flatten_domain(copy());
+  if (!ptr || filters.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_insert_set(copy(), filters.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::flatten_range() const
+bool schedule_node::is_equal(const isl::schedule_node &node2) const
+{
+  if (!ptr || node2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_is_equal(get(), node2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool schedule_node::is_subtree_anchored() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_flatten_range(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_is_subtree_anchored(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-void map::foreach_basic_map(const std::function<void(basic_map)> &fn) const
+isl::schedule_node schedule_node::map_descendant_bottom_up(const std::function<isl::schedule_node(isl::schedule_node)> &fn) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   struct fn_data {
-    const std::function<void(basic_map)> *func;
+    std::function<isl::schedule_node(isl::schedule_node)> func;
     std::exception_ptr eptr;
-  } fn_data = { &fn };
-  auto fn_lambda = [](isl_basic_map *arg_0, void *arg_1) -> isl_stat {
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_schedule_node *arg_0, void *arg_1) -> isl_schedule_node * {
     auto *data = static_cast<struct fn_data *>(arg_1);
     ISL_CPP_TRY {
-      (*data->func)(manage(arg_0));
-      return isl_stat_ok;
+      auto ret = (data->func)(manage(arg_0));
+      return ret.release();
     } ISL_CPP_CATCH_ALL {
       data->eptr = std::current_exception();
-      return isl_stat_error;
+      return NULL;
     }
   };
-  auto res = isl_map_foreach_basic_map(get(), fn_lambda, &fn_data);
+  auto res = isl_schedule_node_map_descendant_bottom_up(copy(), fn_lambda, &fn_data);
   if (fn_data.eptr)
     std::rethrow_exception(fn_data.eptr);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+unsigned schedule_node::n_children() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_n_children(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
-  return;
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-map map::gist(map context) const
+isl::schedule_node schedule_node::next_sibling() const
 {
-  if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_gist(copy(), context.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_next_sibling(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::gist_domain(set context) const
+isl::schedule_node schedule_node::order_after(isl::union_set filter) const
 {
-  if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_gist_domain(copy(), context.release());
+  if (!ptr || filter.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_order_after(copy(), filter.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::intersect(map map2) const
+isl::schedule_node schedule_node::order_before(isl::union_set filter) const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_intersect(copy(), map2.release());
+  if (!ptr || filter.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_order_before(copy(), filter.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::intersect_domain(set set) const
+isl::schedule_node schedule_node::parent() const
 {
-  if (!ptr || set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_intersect_domain(copy(), set.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_parent(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::intersect_params(set params) const
+isl::schedule_node schedule_node::previous_sibling() const
 {
-  if (!ptr || params.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_intersect_params(copy(), params.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_previous_sibling(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map map::intersect_range(set set) const
+isl::schedule_node schedule_node::root() const
 {
-  if (!ptr || set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_intersect_range(copy(), set.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_root(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool map::is_bijective() const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::schedule_node_band
+schedule_node_band::schedule_node_band()
+    : schedule_node() {}
+
+schedule_node_band::schedule_node_band(const schedule_node_band &obj)
+    : schedule_node(obj)
+{
+}
+
+schedule_node_band::schedule_node_band(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_band &schedule_node_band::operator=(schedule_node_band obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx schedule_node_band::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+isl::union_set schedule_node_band::ast_build_options() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_bijective(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_get_ast_build_options(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool map::is_disjoint(const map &map2) const
+isl::union_set schedule_node_band::get_ast_build_options() const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_disjoint(get(), map2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  return ast_build_options();
 }
 
-bool map::is_empty() const
+isl::set schedule_node_band::ast_isolate_option() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_empty(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_get_ast_isolate_option(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool map::is_equal(const map &map2) const
+isl::set schedule_node_band::get_ast_isolate_option() const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_equal(get(), map2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  return ast_isolate_option();
 }
 
-bool map::is_injective() const
+isl::multi_union_pw_aff schedule_node_band::partial_schedule() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_injective(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_get_partial_schedule(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool map::is_single_valued() const
+isl::multi_union_pw_aff schedule_node_band::get_partial_schedule() const
+{
+  return partial_schedule();
+}
+
+bool schedule_node_band::permutable() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_single_valued(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_get_permutable(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool map::is_strict_subset(const map &map2) const
+bool schedule_node_band::get_permutable() const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_strict_subset(get(), map2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  return permutable();
 }
 
-bool map::is_subset(const map &map2) const
+bool schedule_node_band::member_get_coincident(int pos) const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_is_subset(get(), map2.get());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_get_coincident(get(), pos);
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-map map::lexmax() const
+schedule_node_band schedule_node_band::member_set_coincident(int pos, int coincident) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_lexmax(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_set_coincident(copy(), pos, coincident);
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-map map::lexmin() const
+schedule_node_band schedule_node_band::mod(isl::multi_val mv) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_lexmin(copy());
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_mod(copy(), mv.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-basic_map map::polyhedral_hull() const
+unsigned schedule_node_band::n_member() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_polyhedral_hull(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_n_member(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+schedule_node_band schedule_node_band::scale(isl::multi_val mv) const
+{
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_scale(copy(), mv.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-map map::reverse() const
+schedule_node_band schedule_node_band::scale_down(isl::multi_val mv) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_reverse(copy());
+  if (!ptr || mv.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_scale_down(copy(), mv.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-basic_map map::sample() const
+schedule_node_band schedule_node_band::set_ast_build_options(isl::union_set options) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_sample(copy());
+  if (!ptr || options.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_set_ast_build_options(copy(), options.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-map map::subtract(map map2) const
+schedule_node_band schedule_node_band::set_permutable(int permutable) const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_subtract(copy(), map2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_set_permutable(copy(), permutable);
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-map map::unite(map map2) const
+schedule_node_band schedule_node_band::shift(isl::multi_union_pw_aff shift) const
 {
-  if (!ptr || map2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_union(copy(), map2.release());
+  if (!ptr || shift.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_shift(copy(), shift.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-basic_map map::unshifted_simple_hull() const
+schedule_node_band schedule_node_band::split(int pos) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_map_unshifted_simple_hull(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_split(copy(), pos);
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-// implementations for isl::multi_aff
-multi_aff manage(__isl_take isl_multi_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return multi_aff(ptr);
+schedule_node_band schedule_node_band::tile(isl::multi_val sizes) const
+{
+  if (!ptr || sizes.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_tile(copy(), sizes.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
-multi_aff manage_copy(__isl_keep isl_multi_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_multi_aff_copy(ptr);
+
+
+schedule_node_band schedule_node_band::member_set_ast_loop_default(int pos) const
+{
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return multi_aff(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_default);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-multi_aff::multi_aff()
-    : ptr(nullptr) {}
 
-multi_aff::multi_aff(const multi_aff &obj)
-    : ptr(nullptr)
+schedule_node_band schedule_node_band::member_set_ast_loop_atomic(int pos) const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_atomic);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-multi_aff::multi_aff(__isl_take isl_multi_aff *ptr)
-    : ptr(ptr) {}
 
-multi_aff::multi_aff(aff aff)
+schedule_node_band schedule_node_band::member_set_ast_loop_unroll(int pos) const
 {
-  if (aff.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = aff.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_aff_from_aff(aff.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_unroll);
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
-multi_aff::multi_aff(ctx ctx, const std::string &str)
+
+
+schedule_node_band schedule_node_band::member_set_ast_loop_separate(int pos) const
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_band_member_set_ast_loop_type(copy(), pos, isl_ast_loop_separate);
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res).as<schedule_node_band>();
 }
 
-multi_aff &multi_aff::operator=(multi_aff obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_band &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-multi_aff::~multi_aff() {
-  if (ptr)
-    isl_multi_aff_free(ptr);
-}
+// implementations for isl::schedule_node_context
+schedule_node_context::schedule_node_context()
+    : schedule_node() {}
 
-__isl_give isl_multi_aff *multi_aff::copy() const & {
-  return isl_multi_aff_copy(ptr);
+schedule_node_context::schedule_node_context(const schedule_node_context &obj)
+    : schedule_node(obj)
+{
 }
 
-__isl_keep isl_multi_aff *multi_aff::get() const {
-  return ptr;
+schedule_node_context::schedule_node_context(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_context &schedule_node_context::operator=(schedule_node_context obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-__isl_give isl_multi_aff *multi_aff::release() {
-  isl_multi_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::ctx schedule_node_context::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-bool multi_aff::is_null() const {
-  return ptr == nullptr;
+isl::set schedule_node_context::context() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_context_get_context(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-ctx multi_aff::get_ctx() const {
-  return ctx(isl_multi_aff_get_ctx(ptr));
+isl::set schedule_node_context::get_context() const
+{
+  return context();
 }
 
-multi_aff multi_aff::add(multi_aff multi2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_context &obj)
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_aff_add(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-multi_aff multi_aff::flat_range_product(multi_aff multi2) const
+// implementations for isl::schedule_node_domain
+schedule_node_domain::schedule_node_domain()
+    : schedule_node() {}
+
+schedule_node_domain::schedule_node_domain(const schedule_node_domain &obj)
+    : schedule_node(obj)
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_aff_flat_range_product(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
 }
 
-multi_aff multi_aff::product(multi_aff multi2) const
+schedule_node_domain::schedule_node_domain(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_domain &schedule_node_domain::operator=(schedule_node_domain obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx schedule_node_domain::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+isl::union_set schedule_node_domain::domain() const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_aff_product(copy(), multi2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_domain_get_domain(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-multi_aff multi_aff::pullback(multi_aff ma2) const
+isl::union_set schedule_node_domain::get_domain() const
 {
-  if (!ptr || ma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_aff_pullback_multi_aff(copy(), ma2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return domain();
 }
 
-multi_aff multi_aff::range_product(multi_aff multi2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_domain &obj)
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_aff_range_product(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::multi_pw_aff
-multi_pw_aff manage(__isl_take isl_multi_pw_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return multi_pw_aff(ptr);
+// implementations for isl::schedule_node_expansion
+schedule_node_expansion::schedule_node_expansion()
+    : schedule_node() {}
+
+schedule_node_expansion::schedule_node_expansion(const schedule_node_expansion &obj)
+    : schedule_node(obj)
+{
 }
-multi_pw_aff manage_copy(__isl_keep isl_multi_pw_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_pw_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_multi_pw_aff_copy(ptr);
-  if (!ptr)
-    exception::throw_last_error(ctx);
-  return multi_pw_aff(ptr);
+
+schedule_node_expansion::schedule_node_expansion(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_expansion &schedule_node_expansion::operator=(schedule_node_expansion obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-multi_pw_aff::multi_pw_aff()
-    : ptr(nullptr) {}
+isl::ctx schedule_node_expansion::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
+}
 
-multi_pw_aff::multi_pw_aff(const multi_pw_aff &obj)
-    : ptr(nullptr)
+isl::union_pw_multi_aff schedule_node_expansion::contraction() const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_pw_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_expansion_get_contraction(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-multi_pw_aff::multi_pw_aff(__isl_take isl_multi_pw_aff *ptr)
-    : ptr(ptr) {}
+isl::union_pw_multi_aff schedule_node_expansion::get_contraction() const
+{
+  return contraction();
+}
 
-multi_pw_aff::multi_pw_aff(multi_aff ma)
+isl::union_map schedule_node_expansion::expansion() const
 {
-  if (ma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = ma.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_from_multi_aff(ma.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_expansion_get_expansion(get());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-multi_pw_aff::multi_pw_aff(pw_aff pa)
+
+isl::union_map schedule_node_expansion::get_expansion() const
 {
-  if (pa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pa.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_from_pw_aff(pa.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+  return expansion();
 }
-multi_pw_aff::multi_pw_aff(pw_multi_aff pma)
+
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_expansion &obj)
 {
-  if (pma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pma.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_from_pw_multi_aff(pma.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
-multi_pw_aff::multi_pw_aff(ctx ctx, const std::string &str)
+
+// implementations for isl::schedule_node_extension
+schedule_node_extension::schedule_node_extension()
+    : schedule_node() {}
+
+schedule_node_extension::schedule_node_extension(const schedule_node_extension &obj)
+    : schedule_node(obj)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_read_from_str(ctx.release(), str.c_str());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
 }
 
-multi_pw_aff &multi_pw_aff::operator=(multi_pw_aff obj) {
+schedule_node_extension::schedule_node_extension(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_extension &schedule_node_extension::operator=(schedule_node_extension obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-multi_pw_aff::~multi_pw_aff() {
-  if (ptr)
-    isl_multi_pw_aff_free(ptr);
+isl::ctx schedule_node_extension::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-__isl_give isl_multi_pw_aff *multi_pw_aff::copy() const & {
-  return isl_multi_pw_aff_copy(ptr);
+isl::union_map schedule_node_extension::extension() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_extension_get_extension(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_keep isl_multi_pw_aff *multi_pw_aff::get() const {
-  return ptr;
+isl::union_map schedule_node_extension::get_extension() const
+{
+  return extension();
 }
 
-__isl_give isl_multi_pw_aff *multi_pw_aff::release() {
-  isl_multi_pw_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_extension &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-bool multi_pw_aff::is_null() const {
-  return ptr == nullptr;
+// implementations for isl::schedule_node_filter
+schedule_node_filter::schedule_node_filter()
+    : schedule_node() {}
+
+schedule_node_filter::schedule_node_filter(const schedule_node_filter &obj)
+    : schedule_node(obj)
+{
 }
 
-ctx multi_pw_aff::get_ctx() const {
-  return ctx(isl_multi_pw_aff_get_ctx(ptr));
+schedule_node_filter::schedule_node_filter(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_filter &schedule_node_filter::operator=(schedule_node_filter obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-multi_pw_aff multi_pw_aff::add(multi_pw_aff multi2) const
-{
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_add(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+isl::ctx schedule_node_filter::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-multi_pw_aff multi_pw_aff::flat_range_product(multi_pw_aff multi2) const
+isl::union_set schedule_node_filter::filter() const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_flat_range_product(copy(), multi2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_filter_get_filter(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::product(multi_pw_aff multi2) const
+isl::union_set schedule_node_filter::get_filter() const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_product(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return filter();
 }
 
-multi_pw_aff multi_pw_aff::pullback(multi_aff ma) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_filter &obj)
 {
-  if (!ptr || ma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_pullback_multi_aff(copy(), ma.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-multi_pw_aff multi_pw_aff::pullback(pw_multi_aff pma) const
+// implementations for isl::schedule_node_guard
+schedule_node_guard::schedule_node_guard()
+    : schedule_node() {}
+
+schedule_node_guard::schedule_node_guard(const schedule_node_guard &obj)
+    : schedule_node(obj)
 {
-  if (!ptr || pma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
 }
 
-multi_pw_aff multi_pw_aff::pullback(multi_pw_aff mpa2) const
-{
-  if (!ptr || mpa2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_pullback_multi_pw_aff(copy(), mpa2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+schedule_node_guard::schedule_node_guard(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_guard &schedule_node_guard::operator=(schedule_node_guard obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+isl::ctx schedule_node_guard::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-multi_pw_aff multi_pw_aff::range_product(multi_pw_aff multi2) const
+isl::set schedule_node_guard::guard() const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_pw_aff_range_product(copy(), multi2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_schedule_node_guard_get_guard(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::multi_union_pw_aff
-multi_union_pw_aff manage(__isl_take isl_multi_union_pw_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return multi_union_pw_aff(ptr);
+isl::set schedule_node_guard::get_guard() const
+{
+  return guard();
 }
-multi_union_pw_aff manage_copy(__isl_keep isl_multi_union_pw_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_union_pw_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_multi_union_pw_aff_copy(ptr);
-  if (!ptr)
-    exception::throw_last_error(ctx);
-  return multi_union_pw_aff(ptr);
+
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_guard &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-multi_union_pw_aff::multi_union_pw_aff()
-    : ptr(nullptr) {}
+// implementations for isl::schedule_node_leaf
+schedule_node_leaf::schedule_node_leaf()
+    : schedule_node() {}
 
-multi_union_pw_aff::multi_union_pw_aff(const multi_union_pw_aff &obj)
-    : ptr(nullptr)
+schedule_node_leaf::schedule_node_leaf(const schedule_node_leaf &obj)
+    : schedule_node(obj)
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_union_pw_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
-  if (!ptr)
-    exception::throw_last_error(ctx);
 }
 
-multi_union_pw_aff::multi_union_pw_aff(__isl_take isl_multi_union_pw_aff *ptr)
-    : ptr(ptr) {}
+schedule_node_leaf::schedule_node_leaf(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
 
-multi_union_pw_aff::multi_union_pw_aff(union_pw_aff upa)
-{
-  if (upa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = upa.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_from_union_pw_aff(upa.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+schedule_node_leaf &schedule_node_leaf::operator=(schedule_node_leaf obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
-multi_union_pw_aff::multi_union_pw_aff(multi_pw_aff mpa)
+
+isl::ctx schedule_node_leaf::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
+}
+
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_leaf &obj)
 {
-  if (mpa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = mpa.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_from_multi_pw_aff(mpa.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
-multi_union_pw_aff::multi_union_pw_aff(ctx ctx, const std::string &str)
+
+// implementations for isl::schedule_node_mark
+schedule_node_mark::schedule_node_mark()
+    : schedule_node() {}
+
+schedule_node_mark::schedule_node_mark(const schedule_node_mark &obj)
+    : schedule_node(obj)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_read_from_str(ctx.release(), str.c_str());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
 }
 
-multi_union_pw_aff &multi_union_pw_aff::operator=(multi_union_pw_aff obj) {
+schedule_node_mark::schedule_node_mark(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_mark &schedule_node_mark::operator=(schedule_node_mark obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-multi_union_pw_aff::~multi_union_pw_aff() {
-  if (ptr)
-    isl_multi_union_pw_aff_free(ptr);
+isl::ctx schedule_node_mark::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::copy() const & {
-  return isl_multi_union_pw_aff_copy(ptr);
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_mark &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-__isl_keep isl_multi_union_pw_aff *multi_union_pw_aff::get() const {
-  return ptr;
-}
+// implementations for isl::schedule_node_sequence
+schedule_node_sequence::schedule_node_sequence()
+    : schedule_node() {}
 
-__isl_give isl_multi_union_pw_aff *multi_union_pw_aff::release() {
-  isl_multi_union_pw_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+schedule_node_sequence::schedule_node_sequence(const schedule_node_sequence &obj)
+    : schedule_node(obj)
+{
 }
 
-bool multi_union_pw_aff::is_null() const {
-  return ptr == nullptr;
+schedule_node_sequence::schedule_node_sequence(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_sequence &schedule_node_sequence::operator=(schedule_node_sequence obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-ctx multi_union_pw_aff::get_ctx() const {
-  return ctx(isl_multi_union_pw_aff_get_ctx(ptr));
+isl::ctx schedule_node_sequence::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-multi_union_pw_aff multi_union_pw_aff::add(multi_union_pw_aff multi2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_sequence &obj)
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_add(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-multi_union_pw_aff multi_union_pw_aff::flat_range_product(multi_union_pw_aff multi2) const
+// implementations for isl::schedule_node_set
+schedule_node_set::schedule_node_set()
+    : schedule_node() {}
+
+schedule_node_set::schedule_node_set(const schedule_node_set &obj)
+    : schedule_node(obj)
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_flat_range_product(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
 }
 
-multi_union_pw_aff multi_union_pw_aff::pullback(union_pw_multi_aff upma) const
-{
-  if (!ptr || upma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+schedule_node_set::schedule_node_set(__isl_take isl_schedule_node *ptr)
+    : schedule_node(ptr) {}
+
+schedule_node_set &schedule_node_set::operator=(schedule_node_set obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-multi_union_pw_aff multi_union_pw_aff::range_product(multi_union_pw_aff multi2) const
-{
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_range_product(copy(), multi2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+isl::ctx schedule_node_set::ctx() const {
+  return isl::ctx(isl_schedule_node_get_ctx(ptr));
 }
 
-multi_union_pw_aff multi_union_pw_aff::union_add(multi_union_pw_aff mupa2) const
+inline std::ostream &operator<<(std::ostream &os, const schedule_node_set &obj)
 {
-  if (!ptr || mupa2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_union_pw_aff_union_add(copy(), mupa2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_schedule_node_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_schedule_node_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::multi_val
-multi_val manage(__isl_take isl_multi_val *ptr) {
+// implementations for isl::set
+set manage(__isl_take isl_set *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return multi_val(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return set(ptr);
 }
-multi_val manage_copy(__isl_keep isl_multi_val *ptr) {
+set manage_copy(__isl_keep isl_set *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_val_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_multi_val_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_set_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_set_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return multi_val(ptr);
+    exception::throw_last_error(saved_ctx);
+  return set(ptr);
+}
+
+set::set()
+    : ptr(nullptr) {}
+
+set::set(const set &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_set_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+set::set(__isl_take isl_set *ptr)
+    : ptr(ptr) {}
+
+set::set(isl::basic_set bset)
+{
+  if (bset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = bset.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_from_basic_set(bset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
 }
 
-multi_val::multi_val()
-    : ptr(nullptr) {}
-
-multi_val::multi_val(const multi_val &obj)
-    : ptr(nullptr)
+set::set(isl::point pnt)
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_multi_val_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
-  if (!ptr)
-    exception::throw_last_error(ctx);
+  if (pnt.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pnt.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_from_point(pnt.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
 }
 
-multi_val::multi_val(__isl_take isl_multi_val *ptr)
-    : ptr(ptr) {}
-
+set::set(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
 
-multi_val &multi_val::operator=(multi_val obj) {
+set &set::operator=(set obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-multi_val::~multi_val() {
+set::~set() {
   if (ptr)
-    isl_multi_val_free(ptr);
+    isl_set_free(ptr);
 }
 
-__isl_give isl_multi_val *multi_val::copy() const & {
-  return isl_multi_val_copy(ptr);
+__isl_give isl_set *set::copy() const & {
+  return isl_set_copy(ptr);
 }
 
-__isl_keep isl_multi_val *multi_val::get() const {
+__isl_keep isl_set *set::get() const {
   return ptr;
 }
 
-__isl_give isl_multi_val *multi_val::release() {
-  isl_multi_val *tmp = ptr;
+__isl_give isl_set *set::release() {
+  isl_set *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool multi_val::is_null() const {
+bool set::is_null() const {
   return ptr == nullptr;
 }
 
-ctx multi_val::get_ctx() const {
-  return ctx(isl_multi_val_get_ctx(ptr));
+isl::ctx set::ctx() const {
+  return isl::ctx(isl_set_get_ctx(ptr));
 }
 
-multi_val multi_val::add(multi_val multi2) const
+isl::basic_set set::affine_hull() const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_val_add(copy(), multi2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_affine_hull(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-multi_val multi_val::flat_range_product(multi_val multi2) const
+isl::set set::apply(isl::map map) const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_val_flat_range_product(copy(), multi2.release());
+  if (!ptr || map.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_apply(copy(), map.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-multi_val multi_val::product(multi_val multi2) const
+isl::set set::bind(isl::multi_id tuple) const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_val_product(copy(), multi2.release());
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_bind(copy(), tuple.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-multi_val multi_val::range_product(multi_val multi2) const
+isl::set set::coalesce() const
 {
-  if (!ptr || multi2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_multi_val_range_product(copy(), multi2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_coalesce(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::point
-point manage(__isl_take isl_point *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return point(ptr);
-}
-point manage_copy(__isl_keep isl_point *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_point_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_point_copy(ptr);
+isl::set set::complement() const
+{
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return point(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_complement(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-point::point()
-    : ptr(nullptr) {}
-
-point::point(const point &obj)
-    : ptr(nullptr)
+isl::set set::detect_equalities() const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_point_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
-}
-
-point::point(__isl_take isl_point *ptr)
-    : ptr(ptr) {}
-
-
-point &point::operator=(point obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
-}
-
-point::~point() {
-  if (ptr)
-    isl_point_free(ptr);
-}
-
-__isl_give isl_point *point::copy() const & {
-  return isl_point_copy(ptr);
-}
-
-__isl_keep isl_point *point::get() const {
-  return ptr;
-}
-
-__isl_give isl_point *point::release() {
-  isl_point *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
-}
-
-bool point::is_null() const {
-  return ptr == nullptr;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_detect_equalities(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-ctx point::get_ctx() const {
-  return ctx(isl_point_get_ctx(ptr));
+isl::set set::empty(isl::space space)
+{
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_empty(space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-
-// implementations for isl::pw_aff
-pw_aff manage(__isl_take isl_pw_aff *ptr) {
+isl::set set::flatten() const
+{
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return pw_aff(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_flatten(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-pw_aff manage_copy(__isl_keep isl_pw_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_pw_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_pw_aff_copy(ptr);
+
+void set::foreach_basic_set(const std::function<void(isl::basic_set)> &fn) const
+{
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return pw_aff(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::basic_set)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_basic_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_set_foreach_basic_set(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
 }
 
-pw_aff::pw_aff()
-    : ptr(nullptr) {}
-
-pw_aff::pw_aff(const pw_aff &obj)
-    : ptr(nullptr)
+void set::foreach_point(const std::function<void(isl::point)> &fn) const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_pw_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::point)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_point *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_set_foreach_point(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
 }
 
-pw_aff::pw_aff(__isl_take isl_pw_aff *ptr)
-    : ptr(ptr) {}
-
-pw_aff::pw_aff(aff aff)
+isl::multi_val set::plain_multi_val_if_fixed() const
 {
-  if (aff.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = aff.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_from_aff(aff.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_get_plain_multi_val_if_fixed(get());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-pw_aff::pw_aff(ctx ctx, const std::string &str)
+
+isl::multi_val set::get_plain_multi_val_if_fixed() const
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_read_from_str(ctx.release(), str.c_str());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+  return plain_multi_val_if_fixed();
 }
 
-pw_aff &pw_aff::operator=(pw_aff obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::fixed_box set::simple_fixed_box_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_get_simple_fixed_box_hull(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-pw_aff::~pw_aff() {
-  if (ptr)
-    isl_pw_aff_free(ptr);
+isl::fixed_box set::get_simple_fixed_box_hull() const
+{
+  return simple_fixed_box_hull();
 }
 
-__isl_give isl_pw_aff *pw_aff::copy() const & {
-  return isl_pw_aff_copy(ptr);
+isl::space set::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_keep isl_pw_aff *pw_aff::get() const {
-  return ptr;
+isl::space set::get_space() const
+{
+  return space();
 }
 
-__isl_give isl_pw_aff *pw_aff::release() {
-  isl_pw_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::val set::stride(int pos) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_get_stride(get(), pos);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool pw_aff::is_null() const {
-  return ptr == nullptr;
+isl::val set::get_stride(int pos) const
+{
+  return stride(pos);
 }
 
-ctx pw_aff::get_ctx() const {
-  return ctx(isl_pw_aff_get_ctx(ptr));
+isl::set set::gist(isl::set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-pw_aff pw_aff::add(pw_aff pwaff2) const
+isl::map set::identity() const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_add(copy(), pwaff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_identity(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::ceil() const
+isl::pw_aff set::indicator_function() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_ceil(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_indicator_function(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::cond(pw_aff pwaff_true, pw_aff pwaff_false) const
+isl::set set::intersect(isl::set set2) const
 {
-  if (!ptr || pwaff_true.is_null() || pwaff_false.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_cond(copy(), pwaff_true.release(), pwaff_false.release());
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_intersect(copy(), set2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::div(pw_aff pa2) const
+isl::set set::intersect_params(isl::set params) const
 {
-  if (!ptr || pa2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_div(copy(), pa2.release());
+  if (!ptr || params.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_intersect_params(copy(), params.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set pw_aff::eq_set(pw_aff pwaff2) const
+bool set::is_disjoint(const isl::set &set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_is_disjoint(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool set::is_empty() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool set::is_equal(const isl::set &set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_is_equal(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool set::is_singleton() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_is_singleton(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool set::is_strict_subset(const isl::set &set2) const
+{
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_is_strict_subset(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool set::is_subset(const isl::set &set2) const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_eq_set(copy(), pwaff2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_is_subset(get(), set2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-pw_aff pw_aff::floor() const
+bool set::is_wrapping() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_floor(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_is_wrapping(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-set pw_aff::ge_set(pw_aff pwaff2) const
+isl::set set::lexmax() const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_ge_set(copy(), pwaff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_lexmax(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set pw_aff::gt_set(pw_aff pwaff2) const
+isl::pw_multi_aff set::lexmax_pw_multi_aff() const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_gt_set(copy(), pwaff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_lexmax_pw_multi_aff(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set pw_aff::le_set(pw_aff pwaff2) const
+isl::set set::lexmin() const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_le_set(copy(), pwaff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_lexmin(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set pw_aff::lt_set(pw_aff pwaff2) const
+isl::pw_multi_aff set::lexmin_pw_multi_aff() const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_lt_set(copy(), pwaff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_lexmin_pw_multi_aff(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::max(pw_aff pwaff2) const
+isl::set set::lower_bound(isl::multi_pw_aff lower) const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_max(copy(), pwaff2.release());
+  if (!ptr || lower.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_lower_bound_multi_pw_aff(copy(), lower.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::min(pw_aff pwaff2) const
+isl::set set::lower_bound(isl::multi_val lower) const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_min(copy(), pwaff2.release());
+  if (!ptr || lower.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_lower_bound_multi_val(copy(), lower.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::mod(val mod) const
+isl::val set::max_val(const isl::aff &obj) const
 {
-  if (!ptr || mod.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_mod_val(copy(), mod.release());
+  if (!ptr || obj.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_max_val(get(), obj.get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::mul(pw_aff pwaff2) const
+isl::val set::min_val(const isl::aff &obj) const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_mul(copy(), pwaff2.release());
+  if (!ptr || obj.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_min_val(get(), obj.get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set pw_aff::ne_set(pw_aff pwaff2) const
+isl::set set::params() const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_ne_set(copy(), pwaff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_params(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::neg() const
+isl::basic_set set::polyhedral_hull() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_neg(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_polyhedral_hull(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::pullback(multi_aff ma) const
+isl::set set::preimage(isl::multi_aff ma) const
 {
   if (!ptr || ma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_pullback_multi_aff(copy(), ma.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_preimage_multi_aff(copy(), ma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::pullback(pw_multi_aff pma) const
+isl::set set::preimage(isl::multi_pw_aff mpa) const
 {
-  if (!ptr || pma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_pullback_pw_multi_aff(copy(), pma.release());
+  if (!ptr || mpa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_preimage_multi_pw_aff(copy(), mpa.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::pullback(multi_pw_aff mpa) const
+isl::set set::preimage(isl::pw_multi_aff pma) const
 {
-  if (!ptr || mpa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_pullback_multi_pw_aff(copy(), mpa.release());
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_preimage_pw_multi_aff(copy(), pma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::scale(val v) const
+isl::set set::product(isl::set set2) const
 {
-  if (!ptr || v.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_scale_val(copy(), v.release());
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_product(copy(), set2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::scale_down(val f) const
+isl::set set::project_out_all_params() const
 {
-  if (!ptr || f.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_scale_down_val(copy(), f.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_project_out_all_params(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::sub(pw_aff pwaff2) const
+isl::set set::project_out_param(isl::id id) const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_sub(copy(), pwaff2.release());
+  if (!ptr || id.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_project_out_param_id(copy(), id.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::tdiv_q(pw_aff pa2) const
+isl::set set::project_out_param(const std::string &id) const
 {
-  if (!ptr || pa2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_tdiv_q(copy(), pa2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->project_out_param(isl::id(ctx(), id));
 }
 
-pw_aff pw_aff::tdiv_r(pw_aff pa2) const
+isl::set set::project_out_param(isl::id_list list) const
 {
-  if (!ptr || pa2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_tdiv_r(copy(), pa2.release());
+  if (!ptr || list.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_project_out_param_id_list(copy(), list.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_aff pw_aff::union_add(pw_aff pwaff2) const
+isl::basic_set set::sample() const
 {
-  if (!ptr || pwaff2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_aff_union_add(copy(), pwaff2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_sample(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::pw_multi_aff
-pw_multi_aff manage(__isl_take isl_pw_multi_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return pw_multi_aff(ptr);
-}
-pw_multi_aff manage_copy(__isl_keep isl_pw_multi_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_pw_multi_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_pw_multi_aff_copy(ptr);
-  if (!ptr)
-    exception::throw_last_error(ctx);
-  return pw_multi_aff(ptr);
-}
-
-pw_multi_aff::pw_multi_aff()
-    : ptr(nullptr) {}
-
-pw_multi_aff::pw_multi_aff(const pw_multi_aff &obj)
-    : ptr(nullptr)
+isl::point set::sample_point() const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_pw_multi_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_sample_point(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-pw_multi_aff::pw_multi_aff(__isl_take isl_pw_multi_aff *ptr)
-    : ptr(ptr) {}
-
-pw_multi_aff::pw_multi_aff(multi_aff ma)
+isl::set set::subtract(isl::set set2) const
 {
-  if (ma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = ma.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_from_multi_aff(ma.release());
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_subtract(copy(), set2.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-pw_multi_aff::pw_multi_aff(pw_aff pa)
+
+isl::set set::unbind_params(isl::multi_id tuple) const
 {
-  if (pa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pa.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_from_pw_aff(pa.release());
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_unbind_params(copy(), tuple.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-pw_multi_aff::pw_multi_aff(ctx ctx, const std::string &str)
+
+isl::map set::unbind_params_insert_domain(isl::multi_id domain) const
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!ptr || domain.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_unbind_params_insert_domain(copy(), domain.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
-}
-
-pw_multi_aff &pw_multi_aff::operator=(pw_multi_aff obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
-}
-
-pw_multi_aff::~pw_multi_aff() {
-  if (ptr)
-    isl_pw_multi_aff_free(ptr);
-}
-
-__isl_give isl_pw_multi_aff *pw_multi_aff::copy() const & {
-  return isl_pw_multi_aff_copy(ptr);
-}
-
-__isl_keep isl_pw_multi_aff *pw_multi_aff::get() const {
-  return ptr;
-}
-
-__isl_give isl_pw_multi_aff *pw_multi_aff::release() {
-  isl_pw_multi_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
-}
-
-bool pw_multi_aff::is_null() const {
-  return ptr == nullptr;
-}
-
-ctx pw_multi_aff::get_ctx() const {
-  return ctx(isl_pw_multi_aff_get_ctx(ptr));
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::add(pw_multi_aff pma2) const
+isl::set set::unite(isl::set set2) const
 {
-  if (!ptr || pma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_add(copy(), pma2.release());
+  if (!ptr || set2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_union(copy(), set2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::flat_range_product(pw_multi_aff pma2) const
+isl::set set::universe(isl::space space)
 {
-  if (!ptr || pma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_flat_range_product(copy(), pma2.release());
+  if (space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = space.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_universe(space.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::product(pw_multi_aff pma2) const
+isl::basic_set set::unshifted_simple_hull() const
 {
-  if (!ptr || pma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_product(copy(), pma2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_unshifted_simple_hull(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::pullback(multi_aff ma) const
+isl::map set::unwrap() const
 {
-  if (!ptr || ma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_pullback_multi_aff(copy(), ma.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_unwrap(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::pullback(pw_multi_aff pma2) const
+isl::set set::upper_bound(isl::multi_pw_aff upper) const
 {
-  if (!ptr || pma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_pullback_pw_multi_aff(copy(), pma2.release());
+  if (!ptr || upper.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_upper_bound_multi_pw_aff(copy(), upper.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::range_product(pw_multi_aff pma2) const
+isl::set set::upper_bound(isl::multi_val upper) const
 {
-  if (!ptr || pma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_range_product(copy(), pma2.release());
+  if (!ptr || upper.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_set_upper_bound_multi_val(copy(), upper.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-pw_multi_aff pw_multi_aff::union_add(pw_multi_aff pma2) const
+inline std::ostream &operator<<(std::ostream &os, const set &obj)
 {
-  if (!ptr || pma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_pw_multi_aff_union_add(copy(), pma2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_set_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_set_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::schedule
-schedule manage(__isl_take isl_schedule *ptr) {
+// implementations for isl::space
+space manage(__isl_take isl_space *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return schedule(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return space(ptr);
 }
-schedule manage_copy(__isl_keep isl_schedule *ptr) {
+space manage_copy(__isl_keep isl_space *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_schedule_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_schedule_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_space_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_space_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return schedule(ptr);
+    exception::throw_last_error(saved_ctx);
+  return space(ptr);
 }
 
-schedule::schedule()
+space::space()
     : ptr(nullptr) {}
 
-schedule::schedule(const schedule &obj)
+space::space(const space &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_schedule_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_space_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-schedule::schedule(__isl_take isl_schedule *ptr)
+space::space(__isl_take isl_space *ptr)
     : ptr(ptr) {}
 
-schedule::schedule(ctx ctx, const std::string &str)
-{
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_read_from_str(ctx.release(), str.c_str());
-  if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
-}
-
-schedule &schedule::operator=(schedule obj) {
+space &space::operator=(space obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-schedule::~schedule() {
+space::~space() {
   if (ptr)
-    isl_schedule_free(ptr);
+    isl_space_free(ptr);
 }
 
-__isl_give isl_schedule *schedule::copy() const & {
-  return isl_schedule_copy(ptr);
+__isl_give isl_space *space::copy() const & {
+  return isl_space_copy(ptr);
 }
 
-__isl_keep isl_schedule *schedule::get() const {
+__isl_keep isl_space *space::get() const {
   return ptr;
 }
 
-__isl_give isl_schedule *schedule::release() {
-  isl_schedule *tmp = ptr;
+__isl_give isl_space *space::release() {
+  isl_space *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool schedule::is_null() const {
+bool space::is_null() const {
   return ptr == nullptr;
 }
 
-ctx schedule::get_ctx() const {
-  return ctx(isl_schedule_get_ctx(ptr));
+isl::ctx space::ctx() const {
+  return isl::ctx(isl_space_get_ctx(ptr));
 }
 
-union_map schedule::get_map() const
+isl::space space::add_named_tuple(isl::id tuple_id, unsigned int dim) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_get_map(get());
+  if (!ptr || tuple_id.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_add_named_tuple_id_ui(copy(), tuple_id.release(), dim);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule_node schedule::get_root() const
+isl::space space::add_named_tuple(const std::string &tuple_id, unsigned int dim) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_get_root(get());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add_named_tuple(isl::id(ctx(), tuple_id), dim);
 }
 
-schedule schedule::pullback(union_pw_multi_aff upma) const
+isl::space space::add_unnamed_tuple(unsigned int dim) const
 {
-  if (!ptr || upma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_pullback_union_pw_multi_aff(copy(), upma.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_add_unnamed_tuple_ui(copy(), dim);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::schedule_constraints
-schedule_constraints manage(__isl_take isl_schedule_constraints *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return schedule_constraints(ptr);
-}
-schedule_constraints manage_copy(__isl_keep isl_schedule_constraints *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_schedule_constraints_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_schedule_constraints_copy(ptr);
+isl::space space::domain() const
+{
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return schedule_constraints(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-schedule_constraints::schedule_constraints()
-    : ptr(nullptr) {}
-
-schedule_constraints::schedule_constraints(const schedule_constraints &obj)
-    : ptr(nullptr)
+isl::space space::flatten_domain() const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_schedule_constraints_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_flatten_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-schedule_constraints::schedule_constraints(__isl_take isl_schedule_constraints *ptr)
-    : ptr(ptr) {}
-
-schedule_constraints::schedule_constraints(ctx ctx, const std::string &str)
+isl::space space::flatten_range() const
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_read_from_str(ctx.release(), str.c_str());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_flatten_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
-}
-
-schedule_constraints &schedule_constraints::operator=(schedule_constraints obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
-}
-
-schedule_constraints::~schedule_constraints() {
-  if (ptr)
-    isl_schedule_constraints_free(ptr);
-}
-
-__isl_give isl_schedule_constraints *schedule_constraints::copy() const & {
-  return isl_schedule_constraints_copy(ptr);
-}
-
-__isl_keep isl_schedule_constraints *schedule_constraints::get() const {
-  return ptr;
-}
-
-__isl_give isl_schedule_constraints *schedule_constraints::release() {
-  isl_schedule_constraints *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool schedule_constraints::is_null() const {
-  return ptr == nullptr;
+bool space::is_equal(const isl::space &space2) const
+{
+  if (!ptr || space2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_is_equal(get(), space2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-ctx schedule_constraints::get_ctx() const {
-  return ctx(isl_schedule_constraints_get_ctx(ptr));
+bool space::is_wrapping() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_is_wrapping(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-schedule schedule_constraints::compute_schedule() const
+isl::space space::map_from_set() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_compute_schedule(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_map_from_set(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map schedule_constraints::get_coincidence() const
+isl::space space::params() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_get_coincidence(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_params(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map schedule_constraints::get_conditional_validity() const
+isl::space space::range() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_get_conditional_validity(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map schedule_constraints::get_conditional_validity_condition() const
+isl::space space::unit(isl::ctx ctx)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_get_conditional_validity_condition(get());
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_unit(ctx.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set schedule_constraints::get_context() const
+isl::space space::unwrap() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_get_context(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_unwrap(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set schedule_constraints::get_domain() const
+isl::space space::wrap() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_get_domain(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_space_wrap(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map schedule_constraints::get_proximity() const
+inline std::ostream &operator<<(std::ostream &os, const space &obj)
 {
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_space_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_space_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::union_access_info
+union_access_info manage(__isl_take isl_union_access_info *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_get_proximity(get());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return union_access_info(ptr);
+}
+union_access_info manage_copy(__isl_keep isl_union_access_info *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_access_info_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_union_access_info_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return union_access_info(ptr);
 }
 
-union_map schedule_constraints::get_validity() const
+union_access_info::union_access_info()
+    : ptr(nullptr) {}
+
+union_access_info::union_access_info(const union_access_info &obj)
+    : ptr(nullptr)
 {
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_access_info_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_get_validity(get());
+    exception::throw_last_error(saved_ctx);
+}
+
+union_access_info::union_access_info(__isl_take isl_union_access_info *ptr)
+    : ptr(ptr) {}
+
+union_access_info::union_access_info(isl::union_map sink)
+{
+  if (sink.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = sink.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_access_info_from_sink(sink.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+union_access_info &union_access_info::operator=(union_access_info obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_access_info::~union_access_info() {
+  if (ptr)
+    isl_union_access_info_free(ptr);
+}
+
+__isl_give isl_union_access_info *union_access_info::copy() const & {
+  return isl_union_access_info_copy(ptr);
+}
+
+__isl_keep isl_union_access_info *union_access_info::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_access_info *union_access_info::release() {
+  isl_union_access_info *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_access_info::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx union_access_info::ctx() const {
+  return isl::ctx(isl_union_access_info_get_ctx(ptr));
 }
 
-schedule_constraints schedule_constraints::on_domain(union_set domain)
+isl::union_flow union_access_info::compute_flow() const
 {
-  if (domain.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = domain.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_on_domain(domain.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_access_info_compute_flow(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_coincidence(union_map coincidence) const
+isl::union_access_info union_access_info::set_kill(isl::union_map kill) const
 {
-  if (!ptr || coincidence.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_set_coincidence(copy(), coincidence.release());
+  if (!ptr || kill.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_access_info_set_kill(copy(), kill.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_conditional_validity(union_map condition, union_map validity) const
+isl::union_access_info union_access_info::set_may_source(isl::union_map may_source) const
 {
-  if (!ptr || condition.is_null() || validity.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_set_conditional_validity(copy(), condition.release(), validity.release());
+  if (!ptr || may_source.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_access_info_set_may_source(copy(), may_source.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_context(set context) const
+isl::union_access_info union_access_info::set_must_source(isl::union_map must_source) const
 {
-  if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_set_context(copy(), context.release());
+  if (!ptr || must_source.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_access_info_set_must_source(copy(), must_source.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_proximity(union_map proximity) const
+isl::union_access_info union_access_info::set_schedule(isl::schedule schedule) const
 {
-  if (!ptr || proximity.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_set_proximity(copy(), proximity.release());
+  if (!ptr || schedule.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_access_info_set_schedule(copy(), schedule.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule_constraints schedule_constraints::set_validity(union_map validity) const
+isl::union_access_info union_access_info::set_schedule_map(isl::union_map schedule_map) const
 {
-  if (!ptr || validity.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_constraints_set_validity(copy(), validity.release());
+  if (!ptr || schedule_map.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_access_info_set_schedule_map(copy(), schedule_map.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::schedule_node
-schedule_node manage(__isl_take isl_schedule_node *ptr) {
+inline std::ostream &operator<<(std::ostream &os, const union_access_info &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_access_info_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_access_info_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::union_flow
+union_flow manage(__isl_take isl_union_flow *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return schedule_node(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return union_flow(ptr);
 }
-schedule_node manage_copy(__isl_keep isl_schedule_node *ptr) {
+union_flow manage_copy(__isl_keep isl_union_flow *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_schedule_node_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_schedule_node_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_flow_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_union_flow_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return schedule_node(ptr);
+    exception::throw_last_error(saved_ctx);
+  return union_flow(ptr);
 }
 
-schedule_node::schedule_node()
+union_flow::union_flow()
     : ptr(nullptr) {}
 
-schedule_node::schedule_node(const schedule_node &obj)
+union_flow::union_flow(const union_flow &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_schedule_node_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_flow_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-schedule_node::schedule_node(__isl_take isl_schedule_node *ptr)
+union_flow::union_flow(__isl_take isl_union_flow *ptr)
     : ptr(ptr) {}
 
-
-schedule_node &schedule_node::operator=(schedule_node obj) {
+union_flow &union_flow::operator=(union_flow obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-schedule_node::~schedule_node() {
+union_flow::~union_flow() {
   if (ptr)
-    isl_schedule_node_free(ptr);
+    isl_union_flow_free(ptr);
 }
 
-__isl_give isl_schedule_node *schedule_node::copy() const & {
-  return isl_schedule_node_copy(ptr);
+__isl_give isl_union_flow *union_flow::copy() const & {
+  return isl_union_flow_copy(ptr);
 }
 
-__isl_keep isl_schedule_node *schedule_node::get() const {
+__isl_keep isl_union_flow *union_flow::get() const {
   return ptr;
 }
 
-__isl_give isl_schedule_node *schedule_node::release() {
-  isl_schedule_node *tmp = ptr;
+__isl_give isl_union_flow *union_flow::release() {
+  isl_union_flow *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool schedule_node::is_null() const {
+bool union_flow::is_null() const {
   return ptr == nullptr;
 }
 
-ctx schedule_node::get_ctx() const {
-  return ctx(isl_schedule_node_get_ctx(ptr));
+isl::ctx union_flow::ctx() const {
+  return isl::ctx(isl_union_flow_get_ctx(ptr));
 }
 
-bool schedule_node::band_member_get_coincident(int pos) const
+isl::union_map union_flow::full_may_dependence() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_band_member_get_coincident(get(), pos);
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_flow_get_full_may_dependence(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-schedule_node schedule_node::band_member_set_coincident(int pos, int coincident) const
+isl::union_map union_flow::get_full_may_dependence() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_band_member_set_coincident(copy(), pos, coincident);
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return full_may_dependence();
 }
 
-schedule_node schedule_node::child(int pos) const
+isl::union_map union_flow::full_must_dependence() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_child(copy(), pos);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_flow_get_full_must_dependence(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-multi_union_pw_aff schedule_node::get_prefix_schedule_multi_union_pw_aff() const
+isl::union_map union_flow::get_full_must_dependence() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(get());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return full_must_dependence();
 }
 
-union_map schedule_node::get_prefix_schedule_union_map() const
+isl::union_map union_flow::may_dependence() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_get_prefix_schedule_union_map(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_flow_get_may_dependence(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_pw_multi_aff schedule_node::get_prefix_schedule_union_pw_multi_aff() const
+isl::union_map union_flow::get_may_dependence() const
+{
+  return may_dependence();
+}
+
+isl::union_map union_flow::may_no_source() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_flow_get_may_no_source(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule schedule_node::get_schedule() const
+isl::union_map union_flow::get_may_no_source() const
+{
+  return may_no_source();
+}
+
+isl::union_map union_flow::must_dependence() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_get_schedule(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_flow_get_must_dependence(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-schedule_node schedule_node::parent() const
+isl::union_map union_flow::get_must_dependence() const
+{
+  return must_dependence();
+}
+
+isl::union_map union_flow::must_no_source() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_schedule_node_parent(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_flow_get_must_no_source(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::set
-set manage(__isl_take isl_set *ptr) {
+isl::union_map union_flow::get_must_no_source() const
+{
+  return must_no_source();
+}
+
+inline std::ostream &operator<<(std::ostream &os, const union_flow &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_flow_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_flow_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::union_map
+union_map manage(__isl_take isl_union_map *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return set(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return union_map(ptr);
 }
-set manage_copy(__isl_keep isl_set *ptr) {
+union_map manage_copy(__isl_keep isl_union_map *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_set_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_set_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_map_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_union_map_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return set(ptr);
+    exception::throw_last_error(saved_ctx);
+  return union_map(ptr);
 }
 
-set::set()
+union_map::union_map()
     : ptr(nullptr) {}
 
-set::set(const set &obj)
+union_map::union_map(const union_map &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_set_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_map_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-set::set(__isl_take isl_set *ptr)
+union_map::union_map(__isl_take isl_union_map *ptr)
     : ptr(ptr) {}
 
-set::set(ctx ctx, const std::string &str)
+union_map::union_map(isl::basic_map bmap)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_read_from_str(ctx.release(), str.c_str());
+  if (bmap.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = bmap.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_from_basic_map(bmap.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
-set::set(basic_set bset)
+
+union_map::union_map(isl::map map)
 {
-  if (bset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = bset.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_from_basic_set(bset.release());
+  if (map.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = map.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_from_map(map.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
-set::set(point pnt)
+
+union_map::union_map(isl::ctx ctx, const std::string &str)
 {
-  if (pnt.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pnt.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_from_point(pnt.release());
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_read_from_str(ctx.release(), str.c_str());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
 
-set &set::operator=(set obj) {
+union_map &union_map::operator=(union_map obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-set::~set() {
+union_map::~union_map() {
   if (ptr)
-    isl_set_free(ptr);
+    isl_union_map_free(ptr);
 }
 
-__isl_give isl_set *set::copy() const & {
-  return isl_set_copy(ptr);
+__isl_give isl_union_map *union_map::copy() const & {
+  return isl_union_map_copy(ptr);
 }
 
-__isl_keep isl_set *set::get() const {
+__isl_keep isl_union_map *union_map::get() const {
   return ptr;
 }
 
-__isl_give isl_set *set::release() {
-  isl_set *tmp = ptr;
+__isl_give isl_union_map *union_map::release() {
+  isl_union_map *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool set::is_null() const {
+bool union_map::is_null() const {
   return ptr == nullptr;
 }
 
-ctx set::get_ctx() const {
-  return ctx(isl_set_get_ctx(ptr));
+isl::ctx union_map::ctx() const {
+  return isl::ctx(isl_union_map_get_ctx(ptr));
 }
 
-basic_set set::affine_hull() const
+isl::union_map union_map::affine_hull() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_affine_hull(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_affine_hull(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::apply(map map) const
+isl::union_map union_map::apply_domain(isl::union_map umap2) const
 {
-  if (!ptr || map.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_apply(copy(), map.release());
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_apply_domain(copy(), umap2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::coalesce() const
+isl::union_map union_map::apply_range(isl::union_map umap2) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_coalesce(copy());
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_apply_range(copy(), umap2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::complement() const
+isl::union_set union_map::bind_range(isl::multi_id tuple) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_complement(copy());
+  if (!ptr || tuple.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_bind_range(copy(), tuple.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::detect_equalities() const
+isl::union_map union_map::coalesce() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_detect_equalities(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_coalesce(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::flatten() const
+isl::union_map union_map::compute_divs() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_flatten(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_compute_divs(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-void set::foreach_basic_set(const std::function<void(basic_set)> &fn) const
+isl::union_map union_map::curry() const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  struct fn_data {
-    const std::function<void(basic_set)> *func;
-    std::exception_ptr eptr;
-  } fn_data = { &fn };
-  auto fn_lambda = [](isl_basic_set *arg_0, void *arg_1) -> isl_stat {
-    auto *data = static_cast<struct fn_data *>(arg_1);
-    ISL_CPP_TRY {
-      (*data->func)(manage(arg_0));
-      return isl_stat_ok;
-    } ISL_CPP_CATCH_ALL {
-      data->eptr = std::current_exception();
-      return isl_stat_error;
-    }
-  };
-  auto res = isl_set_foreach_basic_set(get(), fn_lambda, &fn_data);
-  if (fn_data.eptr)
-    std::rethrow_exception(fn_data.eptr);
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return;
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_curry(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-val set::get_stride(int pos) const
+isl::union_set union_map::deltas() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_get_stride(get(), pos);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_deltas(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::gist(set context) const
+isl::union_map union_map::detect_equalities() const
 {
-  if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_gist(copy(), context.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_detect_equalities(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-map set::identity() const
+isl::union_set union_map::domain() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_identity(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_domain(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::intersect(set set2) const
+isl::union_map union_map::domain_factor_domain() const
 {
-  if (!ptr || set2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_intersect(copy(), set2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_domain_factor_domain(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::intersect_params(set params) const
+isl::union_map union_map::domain_factor_range() const
 {
-  if (!ptr || params.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_intersect_params(copy(), params.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_domain_factor_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool set::is_disjoint(const set &set2) const
+isl::union_map union_map::domain_map() const
 {
-  if (!ptr || set2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_is_disjoint(get(), set2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_domain_map(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool set::is_empty() const
+isl::union_pw_multi_aff union_map::domain_map_union_pw_multi_aff() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_is_empty(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_domain_map_union_pw_multi_aff(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool set::is_equal(const set &set2) const
+isl::union_map union_map::domain_product(isl::union_map umap2) const
 {
-  if (!ptr || set2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_is_equal(get(), set2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_domain_product(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool set::is_strict_subset(const set &set2) const
+isl::union_map union_map::empty(isl::ctx ctx)
 {
-  if (!ptr || set2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_is_strict_subset(get(), set2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_empty_ctx(ctx.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool set::is_subset(const set &set2) const
+isl::union_map union_map::eq_at(isl::multi_union_pw_aff mupa) const
 {
-  if (!ptr || set2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_is_subset(get(), set2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  if (!ptr || mupa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_eq_at_multi_union_pw_aff(copy(), mupa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool set::is_wrapping() const
+bool union_map::every_map(const std::function<bool(isl::map)> &test) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_is_wrapping(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct test_data {
+    std::function<bool(isl::map)> func;
+    std::exception_ptr eptr;
+  } test_data = { test };
+  auto test_lambda = [](isl_map *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct test_data *>(arg_1);
+    ISL_CPP_TRY {
+      auto ret = (data->func)(manage_copy(arg_0));
+      return ret ? isl_bool_true : isl_bool_false;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_bool_error;
+    }
+  };
+  auto res = isl_union_map_every_map(get(), test_lambda, &test_data);
+  if (test_data.eptr)
+    std::rethrow_exception(test_data.eptr);
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-set set::lexmax() const
+isl::map union_map::extract_map(isl::space space) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_lexmax(copy());
+  if (!ptr || space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_extract_map(get(), space.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::lexmin() const
+isl::union_map union_map::factor_domain() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_lexmin(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_factor_domain(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val set::max_val(const aff &obj) const
+isl::union_map union_map::factor_range() const
 {
-  if (!ptr || obj.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_max_val(get(), obj.get());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_factor_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val set::min_val(const aff &obj) const
+isl::union_map union_map::fixed_power(isl::val exp) const
 {
-  if (!ptr || obj.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_min_val(get(), obj.get());
+  if (!ptr || exp.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_fixed_power_val(copy(), exp.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_set set::polyhedral_hull() const
+isl::union_map union_map::fixed_power(long exp) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_polyhedral_hull(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->fixed_power(isl::val(ctx(), exp));
 }
 
-basic_set set::sample() const
+void union_map::foreach_map(const std::function<void(isl::map)> &fn) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_sample(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::map)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_union_map_foreach_map(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
+
+isl::union_map union_map::from(isl::multi_union_pw_aff mupa)
+{
+  if (mupa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = mupa.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_from_multi_union_pw_aff(mupa.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-point set::sample_point() const
+isl::union_map union_map::from(isl::union_pw_multi_aff upma)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_sample_point(copy());
+  if (upma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = upma.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_from_union_pw_multi_aff(upma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::subtract(set set2) const
+isl::union_map union_map::from_domain(isl::union_set uset)
 {
-  if (!ptr || set2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_subtract(copy(), set2.release());
+  if (uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = uset.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_from_domain(uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-set set::unite(set set2) const
+isl::union_map union_map::from_domain_and_range(isl::union_set domain, isl::union_set range)
 {
-  if (!ptr || set2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_union(copy(), set2.release());
+  if (domain.is_null() || range.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = domain.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_from_domain_and_range(domain.release(), range.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-basic_set set::unshifted_simple_hull() const
+isl::union_map union_map::from_range(isl::union_set uset)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_set_unshifted_simple_hull(copy());
+  if (uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = uset.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_from_range(uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::union_access_info
-union_access_info manage(__isl_take isl_union_access_info *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return union_access_info(ptr);
-}
-union_access_info manage_copy(__isl_keep isl_union_access_info *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_access_info_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_union_access_info_copy(ptr);
+isl::space union_map::space() const
+{
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return union_access_info(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-union_access_info::union_access_info()
-    : ptr(nullptr) {}
-
-union_access_info::union_access_info(const union_access_info &obj)
-    : ptr(nullptr)
+isl::space union_map::get_space() const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_access_info_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
-  if (!ptr)
-    exception::throw_last_error(ctx);
+  return space();
 }
 
-union_access_info::union_access_info(__isl_take isl_union_access_info *ptr)
-    : ptr(ptr) {}
-
-union_access_info::union_access_info(union_map sink)
+isl::union_map union_map::gist(isl::union_map context) const
 {
-  if (sink.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = sink.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_access_info_from_sink(sink.release());
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_gist(copy(), context.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
-}
-
-union_access_info &union_access_info::operator=(union_access_info obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
-}
-
-union_access_info::~union_access_info() {
-  if (ptr)
-    isl_union_access_info_free(ptr);
-}
-
-__isl_give isl_union_access_info *union_access_info::copy() const & {
-  return isl_union_access_info_copy(ptr);
-}
-
-__isl_keep isl_union_access_info *union_access_info::get() const {
-  return ptr;
-}
-
-__isl_give isl_union_access_info *union_access_info::release() {
-  isl_union_access_info *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
-}
-
-bool union_access_info::is_null() const {
-  return ptr == nullptr;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-ctx union_access_info::get_ctx() const {
-  return ctx(isl_union_access_info_get_ctx(ptr));
+isl::union_map union_map::gist_domain(isl::union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_gist_domain(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-union_flow union_access_info::compute_flow() const
+isl::union_map union_map::gist_params(isl::set set) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_access_info_compute_flow(copy());
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_gist_params(copy(), set.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_access_info union_access_info::set_kill(union_map kill) const
+isl::union_map union_map::gist_range(isl::union_set uset) const
 {
-  if (!ptr || kill.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_access_info_set_kill(copy(), kill.release());
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_gist_range(copy(), uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_access_info union_access_info::set_may_source(union_map may_source) const
+isl::union_map union_map::intersect(isl::union_map umap2) const
 {
-  if (!ptr || may_source.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_access_info_set_may_source(copy(), may_source.release());
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_intersect(copy(), umap2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_access_info union_access_info::set_must_source(union_map must_source) const
+isl::union_map union_map::intersect_domain(isl::union_set uset) const
 {
-  if (!ptr || must_source.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_access_info_set_must_source(copy(), must_source.release());
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_intersect_domain(copy(), uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_access_info union_access_info::set_schedule(schedule schedule) const
+isl::union_map union_map::intersect_params(isl::set set) const
 {
-  if (!ptr || schedule.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_access_info_set_schedule(copy(), schedule.release());
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_intersect_params(copy(), set.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_access_info union_access_info::set_schedule_map(union_map schedule_map) const
+isl::union_map union_map::intersect_range(isl::union_set uset) const
 {
-  if (!ptr || schedule_map.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_access_info_set_schedule_map(copy(), schedule_map.release());
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_intersect_range(copy(), uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::union_flow
-union_flow manage(__isl_take isl_union_flow *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return union_flow(ptr);
-}
-union_flow manage_copy(__isl_keep isl_union_flow *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_flow_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_union_flow_copy(ptr);
+bool union_map::is_bijective() const
+{
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return union_flow(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_bijective(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-union_flow::union_flow()
-    : ptr(nullptr) {}
-
-union_flow::union_flow(const union_flow &obj)
-    : ptr(nullptr)
+bool union_map::is_disjoint(const isl::union_map &umap2) const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_flow_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
-  if (!ptr)
-    exception::throw_last_error(ctx);
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_disjoint(get(), umap2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-union_flow::union_flow(__isl_take isl_union_flow *ptr)
-    : ptr(ptr) {}
-
-
-union_flow &union_flow::operator=(union_flow obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+bool union_map::is_empty() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_empty(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-union_flow::~union_flow() {
-  if (ptr)
-    isl_union_flow_free(ptr);
+bool union_map::is_equal(const isl::union_map &umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_equal(get(), umap2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-__isl_give isl_union_flow *union_flow::copy() const & {
-  return isl_union_flow_copy(ptr);
+bool union_map::is_injective() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_injective(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-__isl_keep isl_union_flow *union_flow::get() const {
-  return ptr;
+bool union_map::is_single_valued() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_single_valued(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-__isl_give isl_union_flow *union_flow::release() {
-  isl_union_flow *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+bool union_map::is_strict_subset(const isl::union_map &umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_strict_subset(get(), umap2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-bool union_flow::is_null() const {
-  return ptr == nullptr;
+bool union_map::is_subset(const isl::union_map &umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_is_subset(get(), umap2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-ctx union_flow::get_ctx() const {
-  return ctx(isl_union_flow_get_ctx(ptr));
+bool union_map::isa_map() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_isa_map(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-union_map union_flow::get_full_may_dependence() const
+isl::union_map union_map::lexmax() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_flow_get_full_may_dependence(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_lexmax(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_flow::get_full_must_dependence() const
+isl::union_map union_map::lexmin() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_flow_get_full_must_dependence(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_lexmin(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_flow::get_may_dependence() const
+isl::union_map union_map::polyhedral_hull() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_flow_get_may_dependence(get());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_polyhedral_hull(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_flow::get_may_no_source() const
+isl::union_map union_map::preimage_domain(isl::multi_aff ma) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_flow_get_may_no_source(get());
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_preimage_domain_multi_aff(copy(), ma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_flow::get_must_dependence() const
+isl::union_map union_map::preimage_domain(isl::multi_pw_aff mpa) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_flow_get_must_dependence(get());
+  if (!ptr || mpa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_preimage_domain_multi_pw_aff(copy(), mpa.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_flow::get_must_no_source() const
+isl::union_map union_map::preimage_domain(isl::pw_multi_aff pma) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_flow_get_must_no_source(get());
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_preimage_domain_pw_multi_aff(copy(), pma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::union_map
-union_map manage(__isl_take isl_union_map *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return union_map(ptr);
-}
-union_map manage_copy(__isl_keep isl_union_map *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_map_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_union_map_copy(ptr);
-  if (!ptr)
-    exception::throw_last_error(ctx);
-  return union_map(ptr);
-}
-
-union_map::union_map()
-    : ptr(nullptr) {}
-
-union_map::union_map(const union_map &obj)
-    : ptr(nullptr)
+isl::union_map union_map::preimage_domain(isl::union_pw_multi_aff upma) const
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_map_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
-  if (!ptr)
-    exception::throw_last_error(ctx);
+  if (!ptr || upma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_preimage_domain_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-union_map::union_map(__isl_take isl_union_map *ptr)
-    : ptr(ptr) {}
-
-union_map::union_map(basic_map bmap)
+isl::union_map union_map::preimage_range(isl::multi_aff ma) const
 {
-  if (bmap.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = bmap.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_from_basic_map(bmap.release());
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_preimage_range_multi_aff(copy(), ma.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-union_map::union_map(map map)
+
+isl::union_map union_map::preimage_range(isl::pw_multi_aff pma) const
 {
-  if (map.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = map.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_from_map(map.release());
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_preimage_range_pw_multi_aff(copy(), pma.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-union_map::union_map(ctx ctx, const std::string &str)
+
+isl::union_map union_map::preimage_range(isl::union_pw_multi_aff upma) const
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_read_from_str(ctx.release(), str.c_str());
+  if (!ptr || upma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_preimage_range_union_pw_multi_aff(copy(), upma.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
-}
-
-union_map &union_map::operator=(union_map obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
-}
-
-union_map::~union_map() {
-  if (ptr)
-    isl_union_map_free(ptr);
-}
-
-__isl_give isl_union_map *union_map::copy() const & {
-  return isl_union_map_copy(ptr);
-}
-
-__isl_keep isl_union_map *union_map::get() const {
-  return ptr;
-}
-
-__isl_give isl_union_map *union_map::release() {
-  isl_union_map *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
-}
-
-bool union_map::is_null() const {
-  return ptr == nullptr;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-ctx union_map::get_ctx() const {
-  return ctx(isl_union_map_get_ctx(ptr));
+isl::union_map union_map::product(isl::union_map umap2) const
+{
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_product(copy(), umap2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-union_map union_map::affine_hull() const
+isl::union_map union_map::project_out_all_params() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_affine_hull(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_project_out_all_params(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::apply_domain(union_map umap2) const
+isl::union_set union_map::range() const
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_apply_domain(copy(), umap2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::apply_range(union_map umap2) const
+isl::union_map union_map::range_factor_domain() const
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_apply_range(copy(), umap2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_range_factor_domain(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::coalesce() const
+isl::union_map union_map::range_factor_range() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_coalesce(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_range_factor_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::compute_divs() const
+isl::union_map union_map::range_map() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_compute_divs(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_range_map(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_map::deltas() const
+isl::union_map union_map::range_product(isl::union_map umap2) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_deltas(copy());
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_range_product(copy(), umap2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::detect_equalities() const
+isl::union_map union_map::range_reverse() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_detect_equalities(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_range_reverse(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_map::domain() const
+isl::union_map union_map::reverse() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_domain(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_reverse(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::domain_factor_domain() const
+isl::union_map union_map::subtract(isl::union_map umap2) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_domain_factor_domain(copy());
+  if (!ptr || umap2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_subtract(copy(), umap2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::domain_factor_range() const
+isl::union_map union_map::subtract_domain(isl::union_set dom) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_domain_factor_range(copy());
+  if (!ptr || dom.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_subtract_domain(copy(), dom.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::domain_map() const
+isl::union_map union_map::subtract_range(isl::union_set dom) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_domain_map(copy());
+  if (!ptr || dom.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_subtract_range(copy(), dom.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_pw_multi_aff union_map::domain_map_union_pw_multi_aff() const
+isl::union_map union_map::uncurry() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_domain_map_union_pw_multi_aff(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_uncurry(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::domain_product(union_map umap2) const
+isl::union_map union_map::unite(isl::union_map umap2) const
 {
   if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_domain_product(copy(), umap2.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_union(copy(), umap2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::eq_at(multi_union_pw_aff mupa) const
+isl::union_map union_map::universe() const
 {
-  if (!ptr || mupa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_eq_at_multi_union_pw_aff(copy(), mupa.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_universe(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::factor_domain() const
+isl::union_set union_map::wrap() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_factor_domain(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_wrap(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::factor_range() const
+isl::union_map union_map::zip() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_factor_range(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_map_zip(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::fixed_power(val exp) const
+inline std::ostream &operator<<(std::ostream &os, const union_map &obj)
 {
-  if (!ptr || exp.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_fixed_power_val(copy(), exp.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_map_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_map_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::union_pw_aff
+union_pw_aff manage(__isl_take isl_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return union_pw_aff(ptr);
+}
+union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_union_pw_aff_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return union_pw_aff(ptr);
 }
 
-void union_map::foreach_map(const std::function<void(map)> &fn) const
+union_pw_aff::union_pw_aff()
+    : ptr(nullptr) {}
+
+union_pw_aff::union_pw_aff(const union_pw_aff &obj)
+    : ptr(nullptr)
 {
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  struct fn_data {
-    const std::function<void(map)> *func;
-    std::exception_ptr eptr;
-  } fn_data = { &fn };
-  auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
-    auto *data = static_cast<struct fn_data *>(arg_1);
-    ISL_CPP_TRY {
-      (*data->func)(manage(arg_0));
-      return isl_stat_ok;
-    } ISL_CPP_CATCH_ALL {
-      data->eptr = std::current_exception();
-      return isl_stat_error;
-    }
-  };
-  auto res = isl_union_map_foreach_map(get(), fn_lambda, &fn_data);
-  if (fn_data.eptr)
-    std::rethrow_exception(fn_data.eptr);
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return;
+    exception::throw_last_error(saved_ctx);
 }
 
-union_map union_map::from(union_pw_multi_aff upma)
+union_pw_aff::union_pw_aff(__isl_take isl_union_pw_aff *ptr)
+    : ptr(ptr) {}
+
+union_pw_aff::union_pw_aff(isl::pw_aff pa)
 {
-  if (upma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = upma.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_from_union_pw_multi_aff(upma.release());
+  if (pa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pa.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_from_pw_aff(pa.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+union_pw_aff::union_pw_aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+union_pw_aff &union_pw_aff::operator=(union_pw_aff obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_pw_aff::~union_pw_aff() {
+  if (ptr)
+    isl_union_pw_aff_free(ptr);
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::copy() const & {
+  return isl_union_pw_aff_copy(ptr);
+}
+
+__isl_keep isl_union_pw_aff *union_pw_aff::get() const {
+  return ptr;
+}
+
+__isl_give isl_union_pw_aff *union_pw_aff::release() {
+  isl_union_pw_aff *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool union_pw_aff::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx union_pw_aff::ctx() const {
+  return isl::ctx(isl_union_pw_aff_get_ctx(ptr));
+}
+
+isl::union_pw_aff union_pw_aff::add(isl::union_pw_aff upa2) const
+{
+  if (!ptr || upa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_add(copy(), upa2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_pw_aff::bind(isl::id id) const
+{
+  if (!ptr || id.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_bind_id(copy(), id.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::from(multi_union_pw_aff mupa)
+isl::union_set union_pw_aff::bind(const std::string &id) const
 {
-  if (mupa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = mupa.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_from_multi_union_pw_aff(mupa.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->bind(isl::id(ctx(), id));
 }
 
-union_map union_map::from_domain(union_set uset)
+isl::union_pw_aff union_pw_aff::coalesce() const
 {
-  if (uset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = uset.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_from_domain(uset.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_coalesce(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::from_domain_and_range(union_set domain, union_set range)
+isl::union_set union_pw_aff::domain() const
 {
-  if (domain.is_null() || range.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = domain.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_from_domain_and_range(domain.release(), range.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_domain(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::from_range(union_set uset)
+isl::space union_pw_aff::space() const
 {
-  if (uset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = uset.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_from_range(uset.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_get_space(get());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::gist(union_map context) const
+isl::space union_pw_aff::get_space() const
+{
+  return space();
+}
+
+isl::union_pw_aff union_pw_aff::gist(isl::union_set context) const
 {
   if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_gist(copy(), context.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_gist(copy(), context.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::gist_domain(union_set uset) const
+isl::union_pw_aff union_pw_aff::intersect_domain(isl::union_set uset) const
 {
   if (!ptr || uset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_gist_domain(copy(), uset.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_intersect_domain(copy(), uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::gist_params(set set) const
+isl::union_pw_aff union_pw_aff::intersect_domain_wrapped_domain(isl::union_set uset) const
 {
-  if (!ptr || set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_gist_params(copy(), set.release());
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_intersect_domain_wrapped_domain(copy(), uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::gist_range(union_set uset) const
+isl::union_pw_aff union_pw_aff::intersect_domain_wrapped_range(isl::union_set uset) const
 {
   if (!ptr || uset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_gist_range(copy(), uset.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_intersect_domain_wrapped_range(copy(), uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::intersect(union_map umap2) const
+isl::union_pw_aff union_pw_aff::intersect_params(isl::set set) const
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_intersect(copy(), umap2.release());
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_intersect_params(copy(), set.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::intersect_domain(union_set uset) const
+isl::union_pw_aff union_pw_aff::pullback(isl::union_pw_multi_aff upma) const
 {
-  if (!ptr || uset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_intersect_domain(copy(), uset.release());
+  if (!ptr || upma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::intersect_params(set set) const
+isl::union_pw_aff union_pw_aff::sub(isl::union_pw_aff upa2) const
 {
-  if (!ptr || set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_intersect_params(copy(), set.release());
+  if (!ptr || upa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_sub(copy(), upa2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::intersect_range(union_set uset) const
+isl::union_pw_aff union_pw_aff::subtract_domain(isl::union_set uset) const
 {
   if (!ptr || uset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_intersect_range(copy(), uset.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_subtract_domain(copy(), uset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool union_map::is_bijective() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_is_bijective(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
-}
-
-bool union_map::is_empty() const
+isl::union_pw_aff union_pw_aff::union_add(isl::union_pw_aff upa2) const
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_is_empty(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  if (!ptr || upa2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_union_add(copy(), upa2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool union_map::is_equal(const union_map &umap2) const
+inline std::ostream &operator<<(std::ostream &os, const union_pw_aff &obj)
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_is_equal(get(), umap2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_pw_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-bool union_map::is_injective() const
-{
+// implementations for isl::union_pw_aff_list
+union_pw_aff_list manage(__isl_take isl_union_pw_aff_list *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_is_injective(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return union_pw_aff_list(ptr);
 }
-
-bool union_map::is_single_valued() const
-{
+union_pw_aff_list manage_copy(__isl_keep isl_union_pw_aff_list *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_is_single_valued(get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_aff_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_union_pw_aff_list_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return union_pw_aff_list(ptr);
 }
 
-bool union_map::is_strict_subset(const union_map &umap2) const
-{
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_is_strict_subset(get(), umap2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
-}
+union_pw_aff_list::union_pw_aff_list()
+    : ptr(nullptr) {}
 
-bool union_map::is_subset(const union_map &umap2) const
+union_pw_aff_list::union_pw_aff_list(const union_pw_aff_list &obj)
+    : ptr(nullptr)
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_is_subset(get(), umap2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_aff_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
 }
 
-union_map union_map::lexmax() const
+union_pw_aff_list::union_pw_aff_list(__isl_take isl_union_pw_aff_list *ptr)
+    : ptr(ptr) {}
+
+union_pw_aff_list::union_pw_aff_list(isl::ctx ctx, int n)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_lexmax(copy());
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_list_alloc(ctx.release(), n);
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
 }
 
-union_map union_map::lexmin() const
+union_pw_aff_list::union_pw_aff_list(isl::union_pw_aff el)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_lexmin(copy());
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_list_from_union_pw_aff(el.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
 }
 
-union_map union_map::polyhedral_hull() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_polyhedral_hull(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+union_pw_aff_list &union_pw_aff_list::operator=(union_pw_aff_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
 }
 
-union_map union_map::product(union_map umap2) const
-{
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_product(copy(), umap2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+union_pw_aff_list::~union_pw_aff_list() {
+  if (ptr)
+    isl_union_pw_aff_list_free(ptr);
 }
 
-union_map union_map::project_out_all_params() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_project_out_all_params(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+__isl_give isl_union_pw_aff_list *union_pw_aff_list::copy() const & {
+  return isl_union_pw_aff_list_copy(ptr);
 }
 
-union_set union_map::range() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_range(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+__isl_keep isl_union_pw_aff_list *union_pw_aff_list::get() const {
+  return ptr;
 }
 
-union_map union_map::range_factor_domain() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_range_factor_domain(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+__isl_give isl_union_pw_aff_list *union_pw_aff_list::release() {
+  isl_union_pw_aff_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
 }
 
-union_map union_map::range_factor_range() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_range_factor_range(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+bool union_pw_aff_list::is_null() const {
+  return ptr == nullptr;
 }
 
-union_map union_map::range_map() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_range_map(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+isl::ctx union_pw_aff_list::ctx() const {
+  return isl::ctx(isl_union_pw_aff_list_get_ctx(ptr));
 }
 
-union_map union_map::range_product(union_map umap2) const
+isl::union_pw_aff_list union_pw_aff_list::add(isl::union_pw_aff el) const
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_range_product(copy(), umap2.release());
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_list_add(copy(), el.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::reverse() const
+isl::union_pw_aff_list union_pw_aff_list::clear() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_reverse(copy());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_list_clear(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::subtract(union_map umap2) const
+isl::union_pw_aff_list union_pw_aff_list::concat(isl::union_pw_aff_list list2) const
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_subtract(copy(), umap2.release());
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_list_concat(copy(), list2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::subtract_domain(union_set dom) const
+void union_pw_aff_list::foreach(const std::function<void(isl::union_pw_aff)> &fn) const
 {
-  if (!ptr || dom.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_subtract_domain(copy(), dom.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::union_pw_aff)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_union_pw_aff *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_union_pw_aff_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
 }
 
-union_map union_map::subtract_range(union_set dom) const
+isl::union_pw_aff union_pw_aff_list::at(int index) const
 {
-  if (!ptr || dom.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_subtract_range(copy(), dom.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_list_get_at(get(), index);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_map::unite(union_map umap2) const
+isl::union_pw_aff union_pw_aff_list::get_at(int index) const
 {
-  if (!ptr || umap2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_union(copy(), umap2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return at(index);
 }
 
-union_set union_map::wrap() const
+unsigned union_pw_aff_list::size() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_wrap(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_aff_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-union_map union_map::zip() const
+inline std::ostream &operator<<(std::ostream &os, const union_pw_aff_list &obj)
 {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_map_zip(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_aff_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_pw_aff_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
-// implementations for isl::union_pw_aff
-union_pw_aff manage(__isl_take isl_union_pw_aff *ptr) {
+// implementations for isl::union_pw_multi_aff
+union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return union_pw_aff(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return union_pw_multi_aff(ptr);
 }
-union_pw_aff manage_copy(__isl_keep isl_union_pw_aff *ptr) {
+union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_pw_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_union_pw_aff_copy(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_multi_aff_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_union_pw_multi_aff_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return union_pw_aff(ptr);
+    exception::throw_last_error(saved_ctx);
+  return union_pw_multi_aff(ptr);
 }
 
-union_pw_aff::union_pw_aff()
+union_pw_multi_aff::union_pw_multi_aff()
     : ptr(nullptr) {}
 
-union_pw_aff::union_pw_aff(const union_pw_aff &obj)
+union_pw_multi_aff::union_pw_multi_aff(const union_pw_multi_aff &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_pw_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_multi_aff_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
-union_pw_aff::union_pw_aff(__isl_take isl_union_pw_aff *ptr)
+union_pw_multi_aff::union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr)
     : ptr(ptr) {}
 
-union_pw_aff::union_pw_aff(pw_aff pa)
+union_pw_multi_aff::union_pw_multi_aff(isl::pw_multi_aff pma)
 {
-  if (pa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pa.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_aff_from_pw_aff(pa.release());
+  if (pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pma.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_from_pw_multi_aff(pma.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
-union_pw_aff::union_pw_aff(ctx ctx, const std::string &str)
+
+union_pw_multi_aff::union_pw_multi_aff(isl::union_pw_aff upa)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_aff_read_from_str(ctx.release(), str.c_str());
+  if (upa.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = upa.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_from_union_pw_aff(upa.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
 
-union_pw_aff &union_pw_aff::operator=(union_pw_aff obj) {
+union_pw_multi_aff::union_pw_multi_aff(isl::ctx ctx, const std::string &str)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+union_pw_multi_aff &union_pw_multi_aff::operator=(union_pw_multi_aff obj) {
   std::swap(this->ptr, obj.ptr);
   return *this;
 }
 
-union_pw_aff::~union_pw_aff() {
+union_pw_multi_aff::~union_pw_multi_aff() {
   if (ptr)
-    isl_union_pw_aff_free(ptr);
+    isl_union_pw_multi_aff_free(ptr);
 }
 
-__isl_give isl_union_pw_aff *union_pw_aff::copy() const & {
-  return isl_union_pw_aff_copy(ptr);
+__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::copy() const & {
+  return isl_union_pw_multi_aff_copy(ptr);
 }
 
-__isl_keep isl_union_pw_aff *union_pw_aff::get() const {
+__isl_keep isl_union_pw_multi_aff *union_pw_multi_aff::get() const {
   return ptr;
 }
 
-__isl_give isl_union_pw_aff *union_pw_aff::release() {
-  isl_union_pw_aff *tmp = ptr;
+__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::release() {
+  isl_union_pw_multi_aff *tmp = ptr;
   ptr = nullptr;
   return tmp;
 }
 
-bool union_pw_aff::is_null() const {
+bool union_pw_multi_aff::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_pw_aff::get_ctx() const {
-  return ctx(isl_union_pw_aff_get_ctx(ptr));
+isl::ctx union_pw_multi_aff::ctx() const {
+  return isl::ctx(isl_union_pw_multi_aff_get_ctx(ptr));
 }
 
-union_pw_aff union_pw_aff::add(union_pw_aff upa2) const
+isl::union_pw_multi_aff union_pw_multi_aff::add(isl::union_pw_multi_aff upma2) const
 {
-  if (!ptr || upa2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_aff_add(copy(), upa2.release());
+  if (!ptr || upma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_add(copy(), upma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_pw_aff union_pw_aff::pullback(union_pw_multi_aff upma) const
+isl::pw_multi_aff union_pw_multi_aff::as_pw_multi_aff() const
 {
-  if (!ptr || upma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_aff_pullback_union_pw_multi_aff(copy(), upma.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_as_pw_multi_aff(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_pw_aff union_pw_aff::union_add(union_pw_aff upa2) const
+isl::union_pw_multi_aff union_pw_multi_aff::coalesce() const
 {
-  if (!ptr || upa2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_aff_union_add(copy(), upa2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_coalesce(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-// implementations for isl::union_pw_multi_aff
-union_pw_multi_aff manage(__isl_take isl_union_pw_multi_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  return union_pw_multi_aff(ptr);
-}
-union_pw_multi_aff manage_copy(__isl_keep isl_union_pw_multi_aff *ptr) {
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_pw_multi_aff_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = isl_union_pw_multi_aff_copy(ptr);
+isl::union_set union_pw_multi_aff::domain() const
+{
   if (!ptr)
-    exception::throw_last_error(ctx);
-  return union_pw_multi_aff(ptr);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-union_pw_multi_aff::union_pw_multi_aff()
-    : ptr(nullptr) {}
-
-union_pw_multi_aff::union_pw_multi_aff(const union_pw_multi_aff &obj)
-    : ptr(nullptr)
+isl::union_pw_multi_aff union_pw_multi_aff::empty(isl::ctx ctx)
 {
-  if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_pw_multi_aff_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  ptr = obj.copy();
-  if (!ptr)
-    exception::throw_last_error(ctx);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_empty_ctx(ctx.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-union_pw_multi_aff::union_pw_multi_aff(__isl_take isl_union_pw_multi_aff *ptr)
-    : ptr(ptr) {}
-
-union_pw_multi_aff::union_pw_multi_aff(pw_multi_aff pma)
+isl::pw_multi_aff union_pw_multi_aff::extract_pw_multi_aff(isl::space space) const
 {
-  if (pma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pma.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_multi_aff_from_pw_multi_aff(pma.release());
+  if (!ptr || space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_extract_pw_multi_aff(get(), space.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-union_pw_multi_aff::union_pw_multi_aff(ctx ctx, const std::string &str)
+
+isl::union_pw_multi_aff union_pw_multi_aff::flat_range_product(isl::union_pw_multi_aff upma2) const
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_multi_aff_read_from_str(ctx.release(), str.c_str());
+  if (!ptr || upma2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_flat_range_product(copy(), upma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
-union_pw_multi_aff::union_pw_multi_aff(union_pw_aff upa)
+
+isl::space union_pw_multi_aff::space() const
 {
-  if (upa.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = upa.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_multi_aff_from_union_pw_aff(upa.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_get_space(get());
   if (!res)
-    exception::throw_last_error(ctx);
-  ptr = res;
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-union_pw_multi_aff &union_pw_multi_aff::operator=(union_pw_multi_aff obj) {
-  std::swap(this->ptr, obj.ptr);
-  return *this;
+isl::space union_pw_multi_aff::get_space() const
+{
+  return space();
 }
 
-union_pw_multi_aff::~union_pw_multi_aff() {
-  if (ptr)
-    isl_union_pw_multi_aff_free(ptr);
+isl::union_pw_multi_aff union_pw_multi_aff::gist(isl::union_set context) const
+{
+  if (!ptr || context.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_gist(copy(), context.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::copy() const & {
-  return isl_union_pw_multi_aff_copy(ptr);
+isl::union_pw_multi_aff union_pw_multi_aff::intersect_domain(isl::union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_intersect_domain(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_keep isl_union_pw_multi_aff *union_pw_multi_aff::get() const {
-  return ptr;
+isl::union_pw_multi_aff union_pw_multi_aff::intersect_domain_wrapped_domain(isl::union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_intersect_domain_wrapped_domain(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-__isl_give isl_union_pw_multi_aff *union_pw_multi_aff::release() {
-  isl_union_pw_multi_aff *tmp = ptr;
-  ptr = nullptr;
-  return tmp;
+isl::union_pw_multi_aff union_pw_multi_aff::intersect_domain_wrapped_range(isl::union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_intersect_domain_wrapped_range(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-bool union_pw_multi_aff::is_null() const {
-  return ptr == nullptr;
+isl::union_pw_multi_aff union_pw_multi_aff::intersect_params(isl::set set) const
+{
+  if (!ptr || set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_intersect_params(copy(), set.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
 }
 
-ctx union_pw_multi_aff::get_ctx() const {
-  return ctx(isl_union_pw_multi_aff_get_ctx(ptr));
+bool union_pw_multi_aff::isa_pw_multi_aff() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_isa_pw_multi_aff(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
 }
 
-union_pw_multi_aff union_pw_multi_aff::add(union_pw_multi_aff upma2) const
+isl::union_pw_multi_aff union_pw_multi_aff::pullback(isl::union_pw_multi_aff upma2) const
 {
   if (!ptr || upma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_multi_aff_add(copy(), upma2.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_pullback_union_pw_multi_aff(copy(), upma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_pw_multi_aff union_pw_multi_aff::flat_range_product(union_pw_multi_aff upma2) const
+isl::union_pw_multi_aff union_pw_multi_aff::range_factor_domain() const
 {
-  if (!ptr || upma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_multi_aff_flat_range_product(copy(), upma2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_range_factor_domain(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_pw_multi_aff union_pw_multi_aff::range_factor_range() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_range_factor_range(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_pw_multi_aff union_pw_multi_aff::pullback(union_pw_multi_aff upma2) const
+isl::union_pw_multi_aff union_pw_multi_aff::sub(isl::union_pw_multi_aff upma2) const
 {
   if (!ptr || upma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_pw_multi_aff_pullback_union_pw_multi_aff(copy(), upma2.release());
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_sub(copy(), upma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_pw_multi_aff union_pw_multi_aff::union_add(union_pw_multi_aff upma2) const
+isl::union_pw_multi_aff union_pw_multi_aff::subtract_domain(isl::union_set uset) const
+{
+  if (!ptr || uset.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_pw_multi_aff_subtract_domain(copy(), uset.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_pw_multi_aff union_pw_multi_aff::union_add(isl::union_pw_multi_aff upma2) const
 {
   if (!ptr || upma2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_pw_multi_aff_union_add(copy(), upma2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
+inline std::ostream &operator<<(std::ostream &os, const union_pw_multi_aff &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_pw_multi_aff_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_pw_multi_aff_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
 // implementations for isl::union_set
 union_set manage(__isl_take isl_union_set *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
   return union_set(ptr);
 }
 union_set manage_copy(__isl_keep isl_union_set *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_set_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_set_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = isl_union_set_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return union_set(ptr);
 }
 
@@ -6627,56 +16842,60 @@ union_set::union_set(const union_set &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_union_set_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_set_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
 union_set::union_set(__isl_take isl_union_set *ptr)
     : ptr(ptr) {}
 
-union_set::union_set(basic_set bset)
+union_set::union_set(isl::basic_set bset)
 {
   if (bset.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = bset.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = bset.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_from_basic_set(bset.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
-union_set::union_set(set set)
+
+union_set::union_set(isl::point pnt)
 {
-  if (set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = set.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_from_set(set.release());
+  if (pnt.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = pnt.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_from_point(pnt.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
-union_set::union_set(point pnt)
+
+union_set::union_set(isl::set set)
 {
-  if (pnt.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = pnt.get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_from_point(pnt.release());
+  if (set.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = set.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_from_set(set.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
-union_set::union_set(ctx ctx, const std::string &str)
+
+union_set::union_set(isl::ctx ctx, const std::string &str)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_read_from_str(ctx.release(), str.c_str());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
 
@@ -6708,84 +16927,134 @@ bool union_set::is_null() const {
   return ptr == nullptr;
 }
 
-ctx union_set::get_ctx() const {
-  return ctx(isl_union_set_get_ctx(ptr));
+isl::ctx union_set::ctx() const {
+  return isl::ctx(isl_union_set_get_ctx(ptr));
 }
 
-union_set union_set::affine_hull() const
+isl::union_set union_set::affine_hull() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_affine_hull(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::apply(union_map umap) const
+isl::union_set union_set::apply(isl::union_map umap) const
 {
   if (!ptr || umap.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_apply(copy(), umap.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::coalesce() const
+isl::union_set union_set::coalesce() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_coalesce(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::compute_divs() const
+isl::union_set union_set::compute_divs() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_compute_divs(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::detect_equalities() const
+isl::union_set union_set::detect_equalities() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_detect_equalities(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::empty(isl::ctx ctx)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_empty_ctx(ctx.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+bool union_set::every_set(const std::function<bool(isl::set)> &test) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct test_data {
+    std::function<bool(isl::set)> func;
+    std::exception_ptr eptr;
+  } test_data = { test };
+  auto test_lambda = [](isl_set *arg_0, void *arg_1) -> isl_bool {
+    auto *data = static_cast<struct test_data *>(arg_1);
+    ISL_CPP_TRY {
+      auto ret = (data->func)(manage_copy(arg_0));
+      return ret ? isl_bool_true : isl_bool_false;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_bool_error;
+    }
+  };
+  auto res = isl_union_set_every_set(get(), test_lambda, &test_data);
+  if (test_data.eptr)
+    std::rethrow_exception(test_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::set union_set::extract_set(isl::space space) const
+{
+  if (!ptr || space.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_extract_set(get(), space.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-void union_set::foreach_point(const std::function<void(point)> &fn) const
+void union_set::foreach_point(const std::function<void(isl::point)> &fn) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   struct fn_data {
-    const std::function<void(point)> *func;
+    std::function<void(isl::point)> func;
     std::exception_ptr eptr;
-  } fn_data = { &fn };
+  } fn_data = { fn };
   auto fn_lambda = [](isl_point *arg_0, void *arg_1) -> isl_stat {
     auto *data = static_cast<struct fn_data *>(arg_1);
     ISL_CPP_TRY {
-      (*data->func)(manage(arg_0));
+      (data->func)(manage(arg_0));
       return isl_stat_ok;
     } ISL_CPP_CATCH_ALL {
       data->eptr = std::current_exception();
@@ -6796,24 +17065,24 @@ void union_set::foreach_point(const std::function<void(point)> &fn) const
   if (fn_data.eptr)
     std::rethrow_exception(fn_data.eptr);
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return;
 }
 
-void union_set::foreach_set(const std::function<void(set)> &fn) const
+void union_set::foreach_set(const std::function<void(isl::set)> &fn) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   struct fn_data {
-    const std::function<void(set)> *func;
+    std::function<void(isl::set)> func;
     std::exception_ptr eptr;
-  } fn_data = { &fn };
+  } fn_data = { fn };
   auto fn_lambda = [](isl_set *arg_0, void *arg_1) -> isl_stat {
     auto *data = static_cast<struct fn_data *>(arg_1);
     ISL_CPP_TRY {
-      (*data->func)(manage(arg_0));
+      (data->func)(manage(arg_0));
       return isl_stat_ok;
     } ISL_CPP_CATCH_ALL {
       data->eptr = std::current_exception();
@@ -6824,252 +17093,515 @@ void union_set::foreach_set(const std::function<void(set)> &fn) const
   if (fn_data.eptr)
     std::rethrow_exception(fn_data.eptr);
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return;
 }
 
-union_set union_set::gist(union_set context) const
+isl::space union_set::space() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_get_space(get());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::space union_set::get_space() const
+{
+  return space();
+}
+
+isl::union_set union_set::gist(isl::union_set context) const
 {
   if (!ptr || context.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_gist(copy(), context.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::gist_params(set set) const
+isl::union_set union_set::gist_params(isl::set set) const
 {
   if (!ptr || set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_gist_params(copy(), set.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_map union_set::identity() const
+isl::union_map union_set::identity() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_identity(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::intersect(union_set uset2) const
+isl::union_set union_set::intersect(isl::union_set uset2) const
 {
   if (!ptr || uset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_intersect(copy(), uset2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::intersect_params(set set) const
+isl::union_set union_set::intersect_params(isl::set set) const
 {
   if (!ptr || set.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_intersect_params(copy(), set.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
+bool union_set::is_disjoint(const isl::union_set &uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_is_disjoint(get(), uset2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
 bool union_set::is_empty() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_is_empty(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool union_set::is_equal(const union_set &uset2) const
+bool union_set::is_equal(const isl::union_set &uset2) const
 {
   if (!ptr || uset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_is_equal(get(), uset2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool union_set::is_strict_subset(const union_set &uset2) const
+bool union_set::is_strict_subset(const isl::union_set &uset2) const
 {
   if (!ptr || uset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_union_set_is_strict_subset(get(), uset2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool union_set::is_subset(const isl::union_set &uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_is_subset(get(), uset2.get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool union_set::is_subset(const union_set &uset2) const
-{
-  if (!ptr || uset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_is_subset(get(), uset2.get());
-  if (res < 0)
-    exception::throw_last_error(ctx);
-  return res;
+bool union_set::isa_set() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_isa_set(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+isl::union_set union_set::lexmax() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_lexmax(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::lexmin() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_lexmin(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::polyhedral_hull() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_polyhedral_hull(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::preimage(isl::multi_aff ma) const
+{
+  if (!ptr || ma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_preimage_multi_aff(copy(), ma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::preimage(isl::pw_multi_aff pma) const
+{
+  if (!ptr || pma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_preimage_pw_multi_aff(copy(), pma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::preimage(isl::union_pw_multi_aff upma) const
+{
+  if (!ptr || upma.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_preimage_union_pw_multi_aff(copy(), upma.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::point union_set::sample_point() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_sample_point(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::subtract(isl::union_set uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_subtract(copy(), uset2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::unite(isl::union_set uset2) const
+{
+  if (!ptr || uset2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_union(copy(), uset2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_set union_set::universe() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_universe(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::union_map union_set::unwrap() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_unwrap(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const union_set &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_set_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_set_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::union_set_list
+union_set_list manage(__isl_take isl_union_set_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return union_set_list(ptr);
+}
+union_set_list manage_copy(__isl_keep isl_union_set_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_set_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_union_set_list_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return union_set_list(ptr);
+}
+
+union_set_list::union_set_list()
+    : ptr(nullptr) {}
+
+union_set_list::union_set_list(const union_set_list &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_set_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+union_set_list::union_set_list(__isl_take isl_union_set_list *ptr)
+    : ptr(ptr) {}
+
+union_set_list::union_set_list(isl::ctx ctx, int n)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_list_alloc(ctx.release(), n);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+union_set_list::union_set_list(isl::union_set el)
+{
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_list_from_union_set(el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+union_set_list &union_set_list::operator=(union_set_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+union_set_list::~union_set_list() {
+  if (ptr)
+    isl_union_set_list_free(ptr);
+}
+
+__isl_give isl_union_set_list *union_set_list::copy() const & {
+  return isl_union_set_list_copy(ptr);
+}
+
+__isl_keep isl_union_set_list *union_set_list::get() const {
+  return ptr;
 }
 
-union_set union_set::lexmax() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_lexmax(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+__isl_give isl_union_set_list *union_set_list::release() {
+  isl_union_set_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
 }
 
-union_set union_set::lexmin() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_lexmin(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+bool union_set_list::is_null() const {
+  return ptr == nullptr;
 }
 
-union_set union_set::polyhedral_hull() const
-{
-  if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_polyhedral_hull(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+isl::ctx union_set_list::ctx() const {
+  return isl::ctx(isl_union_set_list_get_ctx(ptr));
 }
 
-union_set union_set::preimage(multi_aff ma) const
+isl::union_set_list union_set_list::add(isl::union_set el) const
 {
-  if (!ptr || ma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_preimage_multi_aff(copy(), ma.release());
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_list_add(copy(), el.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::preimage(pw_multi_aff pma) const
+isl::union_set_list union_set_list::clear() const
 {
-  if (!ptr || pma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_preimage_pw_multi_aff(copy(), pma.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_list_clear(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::preimage(union_pw_multi_aff upma) const
+isl::union_set_list union_set_list::concat(isl::union_set_list list2) const
 {
-  if (!ptr || upma.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_preimage_union_pw_multi_aff(copy(), upma.release());
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_list_concat(copy(), list2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-point union_set::sample_point() const
+void union_set_list::foreach(const std::function<void(isl::union_set)> &fn) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_sample_point(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::union_set)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_union_set *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_union_set_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
 }
 
-union_set union_set::subtract(union_set uset2) const
+isl::union_set union_set_list::at(int index) const
 {
-  if (!ptr || uset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_subtract(copy(), uset2.release());
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_list_get_at(get(), index);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-union_set union_set::unite(union_set uset2) const
+isl::union_set union_set_list::get_at(int index) const
 {
-  if (!ptr || uset2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_union(copy(), uset2.release());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+  return at(index);
 }
 
-union_map union_set::unwrap() const
+unsigned union_set_list::size() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_union_set_unwrap(copy());
-  if (!res)
-    exception::throw_last_error(ctx);
-  return manage(res);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_union_set_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const union_set_list &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_union_set_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_union_set_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
 }
 
 // implementations for isl::val
 val manage(__isl_take isl_val *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
   return val(ptr);
 }
 val manage_copy(__isl_keep isl_val *ptr) {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_val_get_ctx(ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_val_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = isl_val_copy(ptr);
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return val(ptr);
 }
 
@@ -7080,31 +17612,34 @@ val::val(const val &obj)
     : ptr(nullptr)
 {
   if (!obj.ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = isl_val_get_ctx(obj.ptr);
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_val_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   ptr = obj.copy();
   if (!ptr)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
 }
 
 val::val(__isl_take isl_val *ptr)
     : ptr(ptr) {}
 
-val::val(ctx ctx, const std::string &str)
+val::val(isl::ctx ctx, long i)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_val_read_from_str(ctx.release(), str.c_str());
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_int_from_si(ctx.release(), i);
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
-val::val(ctx ctx, long i)
+
+val::val(isl::ctx ctx, const std::string &str)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
-  auto res = isl_val_int_from_si(ctx.release(), i);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_read_from_str(ctx.release(), str.c_str());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   ptr = res;
 }
 
@@ -7136,503 +17671,868 @@ bool val::is_null() const {
   return ptr == nullptr;
 }
 
-ctx val::get_ctx() const {
-  return ctx(isl_val_get_ctx(ptr));
+isl::ctx val::ctx() const {
+  return isl::ctx(isl_val_get_ctx(ptr));
 }
 
-val val::abs() const
+isl::val val::abs() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_abs(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool val::abs_eq(const val &v2) const
+bool val::abs_eq(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_abs_eq(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-val val::add(val v2) const
+bool val::abs_eq(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->abs_eq(isl::val(ctx(), v2));
+}
+
+isl::val val::add(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_add(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::ceil() const
+isl::val val::add(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add(isl::val(ctx(), v2));
+}
+
+isl::val val::ceil() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_ceil(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
 int val::cmp_si(long i) const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_cmp_si(get(), i);
   return res;
 }
 
-val val::div(val v2) const
+isl::val val::div(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_div(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool val::eq(const val &v2) const
+isl::val val::div(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->div(isl::val(ctx(), v2));
+}
+
+bool val::eq(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_eq(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-val val::floor() const
+bool val::eq(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->eq(isl::val(ctx(), v2));
+}
+
+isl::val val::floor() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_floor(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::gcd(val v2) const
+isl::val val::gcd(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_gcd(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool val::ge(const val &v2) const
+isl::val val::gcd(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->gcd(isl::val(ctx(), v2));
+}
+
+bool val::ge(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_ge(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+bool val::ge(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->ge(isl::val(ctx(), v2));
+}
+
+long val::den_si() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_get_den_si(get());
+  return res;
+}
+
+long val::get_den_si() const
+{
+  return den_si();
+}
+
+long val::num_si() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_get_num_si(get());
   return res;
 }
 
-bool val::gt(const val &v2) const
+long val::get_num_si() const
+{
+  return num_si();
+}
+
+bool val::gt(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_gt(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-val val::infty(ctx ctx)
+bool val::gt(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->gt(isl::val(ctx(), v2));
+}
+
+isl::val val::infty(isl::ctx ctx)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_infty(ctx.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::inv() const
+isl::val val::inv() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_inv(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool val::is_divisible_by(const val &v2) const
+bool val::is_divisible_by(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_divisible_by(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
+bool val::is_divisible_by(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->is_divisible_by(isl::val(ctx(), v2));
+}
+
 bool val::is_infty() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_infty(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_int() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_int(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_nan() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_nan(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_neg() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_neg(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_neginfty() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_neginfty(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_negone() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_negone(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_nonneg() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_nonneg(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_nonpos() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_nonpos(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_one() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_one(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_pos() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_pos(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_rat() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_rat(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
 bool val::is_zero() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_is_zero(get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool val::le(const val &v2) const
+bool val::le(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_le(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-bool val::lt(const val &v2) const
+bool val::le(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->le(isl::val(ctx(), v2));
+}
+
+bool val::lt(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_lt(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-val val::max(val v2) const
+bool val::lt(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->lt(isl::val(ctx(), v2));
+}
+
+isl::val val::max(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_max(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::min(val v2) const
+isl::val val::max(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->max(isl::val(ctx(), v2));
+}
+
+isl::val val::min(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_min(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::mod(val v2) const
+isl::val val::min(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->min(isl::val(ctx(), v2));
+}
+
+isl::val val::mod(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_mod(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::mul(val v2) const
+isl::val val::mod(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->mod(isl::val(ctx(), v2));
+}
+
+isl::val val::mul(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_mul(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::nan(ctx ctx)
+isl::val val::mul(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->mul(isl::val(ctx(), v2));
+}
+
+isl::val val::nan(isl::ctx ctx)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_nan(ctx.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-bool val::ne(const val &v2) const
+bool val::ne(const isl::val &v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_ne(get(), v2.get());
   if (res < 0)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return res;
 }
 
-val val::neg() const
+bool val::ne(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->ne(isl::val(ctx(), v2));
+}
+
+isl::val val::neg() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_neg(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::neginfty(ctx ctx)
+isl::val val::neginfty(isl::ctx ctx)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_neginfty(ctx.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::negone(ctx ctx)
+isl::val val::negone(isl::ctx ctx)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_negone(ctx.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::one(ctx ctx)
+isl::val val::one(isl::ctx ctx)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_one(ctx.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::pow2() const
+isl::val val::pow2() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_pow2(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
 int val::sgn() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_sgn(get());
   return res;
 }
 
-val val::sub(val v2) const
+isl::val val::sub(isl::val v2) const
 {
   if (!ptr || v2.is_null())
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_sub(copy(), v2.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::trunc() const
+isl::val val::sub(long v2) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->sub(isl::val(ctx(), v2));
+}
+
+isl::val val::trunc() const
 {
   if (!ptr)
-    exception::throw_NULL_input(__FILE__, __LINE__);
-  auto ctx = get_ctx();
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_trunc(copy());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
 
-val val::zero(ctx ctx)
+isl::val val::zero(isl::ctx ctx)
 {
-  options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
   auto res = isl_val_zero(ctx.release());
   if (!res)
-    exception::throw_last_error(ctx);
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+inline std::ostream &operator<<(std::ostream &os, const val &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_val_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_val_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
+
+// implementations for isl::val_list
+val_list manage(__isl_take isl_val_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return val_list(ptr);
+}
+val_list manage_copy(__isl_keep isl_val_list *ptr) {
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_val_list_get_ctx(ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = isl_val_list_copy(ptr);
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+  return val_list(ptr);
+}
+
+val_list::val_list()
+    : ptr(nullptr) {}
+
+val_list::val_list(const val_list &obj)
+    : ptr(nullptr)
+{
+  if (!obj.ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_val_list_get_ctx(obj.ptr);
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  ptr = obj.copy();
+  if (!ptr)
+    exception::throw_last_error(saved_ctx);
+}
+
+val_list::val_list(__isl_take isl_val_list *ptr)
+    : ptr(ptr) {}
+
+val_list::val_list(isl::ctx ctx, int n)
+{
+  auto saved_ctx = ctx;
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_list_alloc(ctx.release(), n);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+val_list::val_list(isl::val el)
+{
+  if (el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = el.ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_list_from_val(el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  ptr = res;
+}
+
+val_list &val_list::operator=(val_list obj) {
+  std::swap(this->ptr, obj.ptr);
+  return *this;
+}
+
+val_list::~val_list() {
+  if (ptr)
+    isl_val_list_free(ptr);
+}
+
+__isl_give isl_val_list *val_list::copy() const & {
+  return isl_val_list_copy(ptr);
+}
+
+__isl_keep isl_val_list *val_list::get() const {
+  return ptr;
+}
+
+__isl_give isl_val_list *val_list::release() {
+  isl_val_list *tmp = ptr;
+  ptr = nullptr;
+  return tmp;
+}
+
+bool val_list::is_null() const {
+  return ptr == nullptr;
+}
+
+isl::ctx val_list::ctx() const {
+  return isl::ctx(isl_val_list_get_ctx(ptr));
+}
+
+isl::val_list val_list::add(isl::val el) const
+{
+  if (!ptr || el.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_list_add(copy(), el.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val_list val_list::add(long el) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  return this->add(isl::val(ctx(), el));
+}
+
+isl::val_list val_list::clear() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_list_clear(copy());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+isl::val_list val_list::concat(isl::val_list list2) const
+{
+  if (!ptr || list2.is_null())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_list_concat(copy(), list2.release());
+  if (!res)
+    exception::throw_last_error(saved_ctx);
+  return manage(res);
+}
+
+void val_list::foreach(const std::function<void(isl::val)> &fn) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  struct fn_data {
+    std::function<void(isl::val)> func;
+    std::exception_ptr eptr;
+  } fn_data = { fn };
+  auto fn_lambda = [](isl_val *arg_0, void *arg_1) -> isl_stat {
+    auto *data = static_cast<struct fn_data *>(arg_1);
+    ISL_CPP_TRY {
+      (data->func)(manage(arg_0));
+      return isl_stat_ok;
+    } ISL_CPP_CATCH_ALL {
+      data->eptr = std::current_exception();
+      return isl_stat_error;
+    }
+  };
+  auto res = isl_val_list_foreach(get(), fn_lambda, &fn_data);
+  if (fn_data.eptr)
+    std::rethrow_exception(fn_data.eptr);
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return;
+}
+
+isl::val val_list::at(int index) const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_list_get_at(get(), index);
+  if (!res)
+    exception::throw_last_error(saved_ctx);
   return manage(res);
 }
+
+isl::val val_list::get_at(int index) const
+{
+  return at(index);
+}
+
+unsigned val_list::size() const
+{
+  if (!ptr)
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = ctx();
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  auto res = isl_val_list_size(get());
+  if (res < 0)
+    exception::throw_last_error(saved_ctx);
+  return res;
+}
+
+inline std::ostream &operator<<(std::ostream &os, const val_list &obj)
+{
+  if (!obj.get())
+    exception::throw_invalid("NULL input", __FILE__, __LINE__);
+  auto saved_ctx = isl_val_list_get_ctx(obj.get());
+  options_scoped_set_on_error saved_on_error(saved_ctx, exception::on_error);
+  char *str = isl_val_list_to_str(obj.get());
+  if (!str)
+    exception::throw_last_error(saved_ctx);
+  os << str;
+  free(str);
+  return os;
+}
 } // namespace isl
 
 #endif /* ISL_CPP */

diff  --git a/polly/lib/External/isl/include/isl/ctx.h b/polly/lib/External/isl/include/isl/ctx.h
index 13c98c84738a..ecd9272e4efa 100644
--- a/polly/lib/External/isl/include/isl/ctx.h
+++ b/polly/lib/External/isl/include/isl/ctx.h
@@ -85,12 +85,16 @@ typedef enum {
 	isl_stat_error = -1,
 	isl_stat_ok = 0
 } isl_stat;
+isl_stat isl_stat_non_null(void *obj);
 typedef enum {
 	isl_bool_error = -1,
 	isl_bool_false = 0,
 	isl_bool_true = 1
 } isl_bool;
 isl_bool isl_bool_not(isl_bool b);
+isl_bool isl_bool_ok(int b);
+typedef int	isl_size;
+#define isl_size_error	((int) -1)
 struct isl_ctx;
 typedef struct isl_ctx isl_ctx;
 

diff  --git a/polly/lib/External/isl/include/isl/fixed_box.h b/polly/lib/External/isl/include/isl/fixed_box.h
index 5a40a6f0ac70..d8c78e323bfc 100644
--- a/polly/lib/External/isl/include/isl/fixed_box.h
+++ b/polly/lib/External/isl/include/isl/fixed_box.h
@@ -14,19 +14,28 @@
 extern "C" {
 #endif
 
-struct isl_fixed_box;
+struct __isl_export isl_fixed_box;
 typedef struct isl_fixed_box isl_fixed_box;
 
 isl_ctx *isl_fixed_box_get_ctx(__isl_keep isl_fixed_box *box);
+__isl_export
 __isl_give isl_space *isl_fixed_box_get_space(__isl_keep isl_fixed_box *box);
+__isl_export
 isl_bool isl_fixed_box_is_valid(__isl_keep isl_fixed_box *box);
+__isl_export
 __isl_give isl_multi_aff *isl_fixed_box_get_offset(
 	__isl_keep isl_fixed_box *box);
+__isl_export
 __isl_give isl_multi_val *isl_fixed_box_get_size(__isl_keep isl_fixed_box *box);
 
 __isl_give isl_fixed_box *isl_fixed_box_copy(__isl_keep isl_fixed_box *box);
 __isl_null isl_fixed_box *isl_fixed_box_free(__isl_take isl_fixed_box *box);
 
+__isl_give isl_printer *isl_printer_print_fixed_box(
+	__isl_take isl_printer *p, __isl_keep isl_fixed_box *box);
+__isl_give char *isl_fixed_box_to_str(__isl_keep isl_fixed_box *box);
+void isl_fixed_box_dump(__isl_keep isl_fixed_box *box);
+
 #if defined(__cplusplus)
 }
 #endif

diff  --git a/polly/lib/External/isl/include/isl/flow.h b/polly/lib/External/isl/include/isl/flow.h
index f606549dc160..be2f6c577f15 100644
--- a/polly/lib/External/isl/include/isl/flow.h
+++ b/polly/lib/External/isl/include/isl/flow.h
@@ -63,7 +63,7 @@ isl_stat isl_flow_foreach(__isl_keep isl_flow *deps,
 		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_null isl_flow *isl_flow_free(__isl_take isl_flow *deps);
 
 isl_ctx *isl_flow_get_ctx(__isl_keep isl_flow *deps);
 

diff  --git a/polly/lib/External/isl/include/isl/hash.h b/polly/lib/External/isl/include/isl/hash.h
index d5de9ba29925..7ef3d2e03e04 100644
--- a/polly/lib/External/isl/include/isl/hash.h
+++ b/polly/lib/External/isl/include/isl/hash.h
@@ -59,11 +59,12 @@ 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);
+extern struct isl_hash_table_entry *isl_hash_table_entry_none;
 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);
+			    struct isl_hash_table *table,
+			    uint32_t key_hash,
+			    isl_bool (*eq)(const void *entry, const void *val),
+			    const void *val, int reserve);
 isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table,
 	isl_stat (*fn)(void **entry, void *user), void *user);
 void isl_hash_table_remove(struct isl_ctx *ctx,

diff  --git a/polly/lib/External/isl/include/isl/hmap_templ.c b/polly/lib/External/isl/include/isl/hmap_templ.c
index 3519a8d8decd..ceb52bd69373 100644
--- a/polly/lib/External/isl/include/isl/hmap_templ.c
+++ b/polly/lib/External/isl/include/isl/hmap_templ.c
@@ -128,7 +128,7 @@ __isl_give ISL_HMAP *ISL_FN(ISL_HMAP,copy)(__isl_keep ISL_HMAP *hmap)
 	return hmap;
 }
 
-static int has_key(const void *entry, const void *c_key)
+static isl_bool has_key(const void *entry, const void *c_key)
 {
 	const ISL_S(pair) *pair = entry;
 	ISL_KEY *key = (ISL_KEY *) c_key;
@@ -159,6 +159,8 @@ __isl_give ISL_MAYBE(ISL_VAL) ISL_FN(ISL_HMAP,try_get)(
 					&has_key, key, 0);
 
 	if (!entry)
+		goto error;
+	if (entry == isl_hash_table_entry_none)
 		return res;
 
 	pair = entry->data;
@@ -221,7 +223,9 @@ __isl_give ISL_HMAP *ISL_FN(ISL_HMAP,drop)(__isl_take ISL_HMAP *hmap,
 	hash = ISL_FN(ISL_KEY,get_hash)(key);
 	entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
 					&has_key, key, 0);
-	if (!entry) {
+	if (!entry)
+		goto error;
+	if (entry == isl_hash_table_entry_none) {
 		ISL_FN(ISL_KEY,free)(key);
 		return hmap;
 	}
@@ -234,8 +238,10 @@ __isl_give ISL_HMAP *ISL_FN(ISL_HMAP,drop)(__isl_take ISL_HMAP *hmap,
 	ISL_FN(ISL_KEY,free)(key);
 
 	if (!entry)
+		return ISL_FN(ISL_HMAP,free)(hmap);
+	if (entry == isl_hash_table_entry_none)
 		isl_die(hmap->ctx, isl_error_internal,
-			"missing entry" , goto error);
+			"missing entry" , return ISL_FN(ISL_HMAP,free)(hmap));
 
 	pair = entry->data;
 	isl_hash_table_remove(hmap->ctx, &hmap->table, entry);
@@ -269,8 +275,10 @@ __isl_give ISL_HMAP *ISL_FN(ISL_HMAP,set)(__isl_take ISL_HMAP *hmap,
 	hash = ISL_FN(ISL_KEY,get_hash)(key);
 	entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
 					&has_key, key, 0);
-	if (entry) {
-		int equal;
+	if (!entry)
+		goto error;
+	if (entry != isl_hash_table_entry_none) {
+		isl_bool equal;
 		pair = entry->data;
 		equal = ISL_VAL_IS_EQUAL(pair->val, val);
 		if (equal < 0)

diff  --git a/polly/lib/External/isl/include/isl/id.h b/polly/lib/External/isl/include/isl/id.h
index 33aa4b090956..956b962ef1b2 100644
--- a/polly/lib/External/isl/include/isl/id.h
+++ b/polly/lib/External/isl/include/isl/id.h
@@ -4,6 +4,7 @@
 #include <isl/ctx.h>
 #include <isl/id_type.h>
 #include <isl/list.h>
+#include <isl/multi.h>
 #include <isl/printer_type.h>
 #include <isl/stdint.h>
 
@@ -11,7 +12,9 @@
 extern "C" {
 #endif
 
-ISL_DECLARE_LIST_FN(id)
+ISL_DECLARE_EXPORTED_LIST_FN(id)
+
+ISL_DECLARE_MULTI(id)
 
 isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id);
 uint32_t isl_id_get_hash(__isl_keep isl_id *id);
@@ -22,16 +25,27 @@ __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_export
 __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,
 	void (*free_user)(void *user));
 
+__isl_constructor
+__isl_give isl_id *isl_id_read_from_str(isl_ctx *ctx, const char *str);
 __isl_give char *isl_id_to_str(__isl_keep isl_id *id);
 __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);
 
+__isl_constructor
+__isl_give isl_multi_id *isl_multi_id_read_from_str(isl_ctx *ctx,
+	const char *str);
+__isl_give isl_printer *isl_printer_print_multi_id(__isl_take isl_printer *p,
+	__isl_keep isl_multi_id *mi);
+void isl_multi_id_dump(__isl_keep isl_multi_id *mi);
+__isl_give char *isl_multi_id_to_str(__isl_keep isl_multi_id *mi);
+
 #if defined(__cplusplus)
 }
 #endif

diff  --git a/polly/lib/External/isl/include/isl/id_type.h b/polly/lib/External/isl/include/isl/id_type.h
index e87f8437ec9c..0cb3c1c43b25 100644
--- a/polly/lib/External/isl/include/isl/id_type.h
+++ b/polly/lib/External/isl/include/isl/id_type.h
@@ -7,10 +7,13 @@
 extern "C" {
 #endif
 
-struct isl_id;
+struct __isl_export isl_id;
 typedef struct isl_id isl_id;
 
-ISL_DECLARE_LIST_TYPE(id)
+ISL_DECLARE_EXPORTED_LIST_TYPE(id)
+
+struct __isl_export isl_multi_id;
+typedef struct isl_multi_id isl_multi_id;
 
 #if defined(__cplusplus)
 }

diff  --git a/polly/lib/External/isl/include/isl/list.h b/polly/lib/External/isl/include/isl/list.h
index 49d2f9147c81..b5ffe499f0b6 100644
--- a/polly/lib/External/isl/include/isl/list.h
+++ b/polly/lib/External/isl/include/isl/list.h
@@ -17,37 +17,50 @@
 extern "C" {
 #endif
 
-#define ISL_DECLARE_LIST_TYPE(EL)					\
+#define ISL_DECLARE_LIST_TYPE2(EL,EXPORT)				\
 struct isl_##EL;							\
-struct isl_##EL##_list;							\
+struct EXPORT isl_##EL##_list;						\
 typedef struct isl_##EL##_list isl_##EL##_list;
-#define ISL_DECLARE_LIST_FN(EL)						\
+#define ISL_DECLARE_LIST_TYPE(EL)					\
+	ISL_DECLARE_LIST_TYPE2(EL,)
+#define ISL_DECLARE_EXPORTED_LIST_TYPE(EL)				\
+	ISL_DECLARE_LIST_TYPE2(EL,__isl_export)
+#define ISL_DECLARE_LIST_FN3(EL,CONSTRUCTOR,EXPORT)			\
 isl_ctx *isl_##EL##_list_get_ctx(__isl_keep isl_##EL##_list *list);	\
+CONSTRUCTOR								\
 __isl_give isl_##EL##_list *isl_##EL##_list_from_##EL(			\
-	__isl_take struct isl_##EL *el);				\
+	__isl_take isl_##EL *el);					\
+CONSTRUCTOR								\
 __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);				\
+EXPORT									\
 __isl_give isl_##EL##_list *isl_##EL##_list_add(			\
 	__isl_take isl_##EL##_list *list,				\
-	__isl_take struct isl_##EL *el);				\
+	__isl_take 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);	\
+EXPORT									\
+__isl_give isl_##EL##_list *isl_##EL##_list_clear(			\
+	__isl_take isl_##EL##_list *list);				\
 __isl_give isl_##EL##_list *isl_##EL##_list_swap(			\
 	__isl_take isl_##EL##_list *list, unsigned pos1,		\
 	unsigned pos2);							\
 __isl_give isl_##EL##_list *isl_##EL##_list_reverse(			\
 	__isl_take isl_##EL##_list *list);				\
+EXPORT									\
 __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_size(__isl_keep isl_##EL##_list *list);		\
-int isl_##EL##_list_n_##EL(__isl_keep isl_##EL##_list *list);		\
+EXPORT									\
+isl_size isl_##EL##_list_size(__isl_keep isl_##EL##_list *list);	\
+isl_size isl_##EL##_list_n_##EL(__isl_keep isl_##EL##_list *list);	\
+EXPORT									\
 __isl_give isl_##EL *isl_##EL##_list_get_at(				\
 	__isl_keep isl_##EL##_list *list, int index);			\
 __isl_give struct isl_##EL *isl_##EL##_list_get_##EL(			\
@@ -55,8 +68,9 @@ __isl_give struct isl_##EL *isl_##EL##_list_get_##EL(			\
 __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);				\
+EXPORT									\
 isl_stat isl_##EL##_list_foreach(__isl_keep isl_##EL##_list *list,	\
-	isl_stat (*fn)(__isl_take struct isl_##EL *el, void *user),	\
+	isl_stat (*fn)(__isl_take isl_##EL *el, void *user),		\
 	void *user);							\
 __isl_give isl_##EL##_list *isl_##EL##_list_map(			\
 	__isl_take isl_##EL##_list *list,				\
@@ -74,13 +88,22 @@ isl_stat isl_##EL##_list_foreach_scc(__isl_keep isl_##EL##_list *list,	\
 	void *follows_user,						\
 	isl_stat (*fn)(__isl_take isl_##EL##_list *scc, void *user),	\
 	void *fn_user);							\
+__isl_give char *isl_##EL##_list_to_str(				\
+	__isl_keep isl_##EL##_list *list);				\
 __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_FN(EL)						\
+	ISL_DECLARE_LIST_FN3(EL,,)
+#define ISL_DECLARE_EXPORTED_LIST_FN(EL)				\
+	ISL_DECLARE_LIST_FN3(EL,__isl_constructor,__isl_export)
 
 #define ISL_DECLARE_LIST(EL)						\
 	ISL_DECLARE_LIST_TYPE(EL)					\
 	ISL_DECLARE_LIST_FN(EL)
+#define ISL_DECLARE_EXPORTED_LIST(EL)					\
+	ISL_DECLARE_EXPORTED_LIST_TYPE(EL)				\
+	ISL_DECLARE_EXPORTED_LIST_FN(EL)
 
 #if defined(__cplusplus)
 }

diff  --git a/polly/lib/External/isl/include/isl/local_space.h b/polly/lib/External/isl/include/isl/local_space.h
index a7201b05201a..cf2fe179d02b 100644
--- a/polly/lib/External/isl/include/isl/local_space.h
+++ b/polly/lib/External/isl/include/isl/local_space.h
@@ -29,7 +29,7 @@ __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,
+isl_size isl_local_space_dim(__isl_keep isl_local_space *ls,
 	enum isl_dim_type type);
 isl_bool isl_local_space_has_dim_name(__isl_keep isl_local_space *ls,
 	enum isl_dim_type type, unsigned pos);

diff  --git a/polly/lib/External/isl/include/isl/map.h b/polly/lib/External/isl/include/isl/map.h
index f04fb26688e0..ba531b6a75b2 100644
--- a/polly/lib/External/isl/include/isl/map.h
+++ b/polly/lib/External/isl/include/isl/map.h
@@ -30,29 +30,16 @@
 extern "C" {
 #endif
 
-ISL_DEPRECATED
-unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap);
-ISL_DEPRECATED
-unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap);
-ISL_DEPRECATED
-unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap);
-ISL_DEPRECATED
-unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap);
-unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap);
-unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
+isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap);
+isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
 				enum isl_dim_type type);
 
-ISL_DEPRECATED
-unsigned isl_map_n_in(__isl_keep const isl_map *map);
-ISL_DEPRECATED
-unsigned isl_map_n_out(__isl_keep const isl_map *map);
-ISL_DEPRECATED
-unsigned isl_map_n_param(__isl_keep const isl_map *map);
-unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type);
+isl_size 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_export
 __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,
@@ -112,18 +99,19 @@ int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
 
 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap);
 
-__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim);
+__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space);
 __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);
 __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,
+	__isl_take isl_space *space, unsigned n_equal);
+__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
 	unsigned pos);
-__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
+__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
 	unsigned pos);
 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space);
 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space);
-__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_map *isl_basic_map_nat_universe(
+	__isl_take isl_space *space);
 __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);
@@ -214,6 +202,18 @@ __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
 __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);
+__isl_overload
+__isl_give isl_map *isl_map_lower_bound_multi_val(__isl_take isl_map *map,
+	__isl_take isl_multi_val *lower);
+__isl_overload
+__isl_give isl_map *isl_map_upper_bound_multi_val(__isl_take isl_map *map,
+	__isl_take isl_multi_val *upper);
+__isl_overload
+__isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
+	__isl_take isl_multi_pw_aff *lower);
+__isl_overload
+__isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
+	__isl_take isl_multi_pw_aff *upper);
 
 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
 	__isl_take isl_basic_map *bmap2);
@@ -259,8 +259,10 @@ __isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
 	__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_export
 __isl_give isl_pw_multi_aff *isl_map_lexmin_pw_multi_aff(
 	__isl_take isl_map *map);
+__isl_export
 __isl_give isl_pw_multi_aff *isl_map_lexmax_pw_multi_aff(
 	__isl_take isl_map *map);
 
@@ -283,8 +285,10 @@ isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
 isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
 		__isl_keep isl_basic_map *bmap2);
 
+__isl_export
 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space);
 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim);
+__isl_export
 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space);
 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim);
 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n);
@@ -300,6 +304,8 @@ __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map);
 __isl_export
 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map);
 __isl_export
+__isl_give isl_map *isl_map_range_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);
@@ -315,6 +321,8 @@ __isl_give isl_map *isl_map_intersect_range(
 		__isl_take isl_set *set);
 __isl_give isl_map *isl_map_intersect_domain_factor_range(
 	__isl_take isl_map *map, __isl_take isl_map *factor);
+__isl_give isl_map *isl_map_intersect_range_factor_domain(
+	__isl_take isl_map *map, __isl_take isl_map *factor);
 __isl_give isl_map *isl_map_intersect_range_factor_range(
 	__isl_take isl_map *map, __isl_take isl_map *factor);
 __isl_export
@@ -325,14 +333,19 @@ __isl_export
 __isl_give isl_map *isl_map_apply_range(
 		__isl_take isl_map *map1,
 		__isl_take isl_map *map2);
+__isl_overload
 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
 	__isl_take isl_multi_aff *ma);
+__isl_overload
 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
 	__isl_take isl_multi_aff *ma);
+__isl_overload
 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma);
+__isl_overload
 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
 	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma);
+__isl_overload
 __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(
@@ -343,8 +356,10 @@ __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_export
 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
 	__isl_take isl_map *map2);
+__isl_export
 __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(
@@ -360,11 +375,17 @@ __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map);
 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map);
 isl_bool isl_map_is_product(__isl_keep isl_map *map);
+__isl_export
 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map);
+__isl_export
 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map);
+__isl_export
 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map);
+__isl_export
 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map);
+__isl_export
 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map);
+__isl_export
 __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,
@@ -390,8 +411,12 @@ __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_lower_bound_val(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *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_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value);
 __isl_export
 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap);
 __isl_export
@@ -427,6 +452,8 @@ __isl_give isl_basic_map *isl_basic_map_project_out(
 		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_export
+__isl_give isl_map *isl_map_project_out_all_params(__isl_take isl_map *map);
 __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);
@@ -470,8 +497,10 @@ isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset);
 __isl_export
 isl_bool 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_export
 __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_export
 __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);
@@ -493,7 +522,9 @@ __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_export
 __isl_give isl_set *isl_map_domain(__isl_take isl_map *bmap);
+__isl_export
 __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);
@@ -513,6 +544,13 @@ __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
 __isl_export
 __isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map);
 
+__isl_export
+__isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
+	__isl_take isl_multi_id *tuple);
+__isl_export
+__isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
+	__isl_take isl_multi_id *tuple);
+
 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map);
 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map);
 __isl_export
@@ -549,6 +587,7 @@ __isl_give isl_map *isl_map_zip(__isl_take isl_map *map);
 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap);
 isl_bool 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_export
 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map);
 
 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map);
@@ -557,6 +596,7 @@ __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map);
 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap);
 isl_bool 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_export
 __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);
@@ -608,6 +648,7 @@ __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
 
 __isl_give isl_stride_info *isl_map_get_range_stride_info(
 	__isl_keep isl_map *map, int pos);
+__isl_export
 __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull(
 	__isl_keep isl_map *map);
 
@@ -619,7 +660,7 @@ isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
 
 uint32_t isl_map_get_hash(__isl_keep isl_map *map);
 
-int isl_map_n_basic_map(__isl_keep isl_map *map);
+isl_size isl_map_n_basic_map(__isl_keep isl_map *map);
 __isl_export
 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
 	isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user);
@@ -628,11 +669,11 @@ __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
 
 __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_power(__isl_take isl_map *map, isl_bool *exact);
 __isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
-	int *exact);
+	isl_bool *exact);
 __isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
-	int *exact);
+	isl_bool *exact);
 
 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
 	__isl_take isl_map *map2);

diff  --git a/polly/lib/External/isl/include/isl/mat.h b/polly/lib/External/isl/include/isl/mat.h
index ed3ee34960af..38983da816b8 100644
--- a/polly/lib/External/isl/include/isl/mat.h
+++ b/polly/lib/External/isl/include/isl/mat.h
@@ -33,8 +33,8 @@ 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);
 __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_size isl_mat_rows(__isl_keep isl_mat *mat);
+isl_size 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,
@@ -106,7 +106,7 @@ isl_bool isl_mat_is_equal(__isl_keep isl_mat *mat1, __isl_keep isl_mat *mat2);
 isl_bool isl_mat_has_linearly_independent_rows(__isl_keep isl_mat *mat1,
 	__isl_keep isl_mat *mat2);
 
-int isl_mat_rank(__isl_keep isl_mat *mat);
+isl_size isl_mat_rank(__isl_keep isl_mat *mat);
 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);

diff  --git a/polly/lib/External/isl/include/isl/multi.h b/polly/lib/External/isl/include/isl/multi.h
index f643f9e707ea..8a02b5818a9f 100644
--- a/polly/lib/External/isl/include/isl/multi.h
+++ b/polly/lib/External/isl/include/isl/multi.h
@@ -11,63 +11,37 @@ 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_export								\
 __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_constructor							\
 __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);				\
+__isl_export								\
 isl_bool isl_multi_##BASE##_plain_is_equal(				\
 	__isl_keep isl_multi_##BASE *multi1,				\
 	__isl_keep isl_multi_##BASE *multi2);				\
-isl_bool isl_multi_##BASE##_involves_nan(				\
-	__isl_keep isl_multi_##BASE *multi);				\
-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_keep 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);	\
-isl_bool 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);				\
-__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_export								\
+isl_size isl_multi_##BASE##_size(__isl_keep isl_multi_##BASE *multi);	\
+__isl_export								\
+__isl_give isl_##BASE *isl_multi_##BASE##_get_at(			\
+	__isl_keep isl_multi_##BASE *multi, int pos);			\
 __isl_give isl_##BASE *isl_multi_##BASE##_get_##BASE(			\
 	__isl_keep isl_multi_##BASE *multi, int pos);			\
+__isl_export								\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_at(			\
+	__isl_take isl_multi_##BASE *multi, int pos,			\
+	__isl_take isl_##BASE *el);					\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_set_##BASE(		\
 	__isl_take isl_multi_##BASE *multi, int pos,			\
 	__isl_take isl_##BASE *el);					\
@@ -92,13 +66,39 @@ __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##_align_params(		\
+	__isl_take isl_multi_##BASE *multi,				\
+	__isl_take isl_space *model);					\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_from_range(		\
+	__isl_take isl_multi_##BASE *multi);
+
+#define ISL_DECLARE_MULTI_IDENTITY(BASE)				\
+__isl_overload								\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_identity_multi_##BASE(	\
+	__isl_take isl_multi_##BASE *multi);				\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_identity(		\
+	__isl_take isl_space *space);					\
+__isl_overload								\
+__isl_give isl_multi_##BASE *						\
+isl_multi_##BASE##_identity_on_domain_space(				\
+	__isl_take isl_space *space);
+
+#define ISL_DECLARE_MULTI_CMP(BASE)					\
+int isl_multi_##BASE##_plain_cmp(__isl_keep isl_multi_##BASE *multi1,	\
+	__isl_keep isl_multi_##BASE *multi2);
+
+#define ISL_DECLARE_MULTI_ARITH(BASE)					\
+__isl_overload								\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_val(		\
 	__isl_take isl_multi_##BASE *multi, __isl_take isl_val *v);	\
+__isl_overload								\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_down_val(		\
 	__isl_take isl_multi_##BASE *multi, __isl_take isl_val *v);	\
+__isl_overload								\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_multi_val(	\
 	__isl_take isl_multi_##BASE *multi,				\
 	__isl_take isl_multi_val *mv);					\
+__isl_overload								\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_down_multi_val(	\
 	__isl_take isl_multi_##BASE *multi,				\
 	__isl_take isl_multi_val *mv);					\
@@ -109,24 +109,39 @@ __isl_export								\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_add(			\
 	__isl_take isl_multi_##BASE *multi1,				\
 	__isl_take isl_multi_##BASE *multi2);				\
+__isl_export								\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_sub(			\
 	__isl_take isl_multi_##BASE *multi1,				\
 	__isl_take isl_multi_##BASE *multi2);				\
-__isl_give isl_multi_##BASE *isl_multi_##BASE##_align_params(		\
-	__isl_take isl_multi_##BASE *multi,				\
-	__isl_take isl_space *model);					\
-__isl_give isl_multi_##BASE *isl_multi_##BASE##_from_range(		\
+__isl_export								\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_neg(		 	\
 	__isl_take isl_multi_##BASE *multi);
 
-#define ISL_DECLARE_MULTI_CMP(BASE)					\
-int isl_multi_##BASE##_plain_cmp(__isl_keep isl_multi_##BASE *multi1,	\
-	__isl_keep isl_multi_##BASE *multi2);
+#define ISL_DECLARE_MULTI_ADD_CONSTANT(BASE)				\
+__isl_overload								\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_add_constant_val(	\
+	__isl_take isl_multi_##BASE *mpa, __isl_take isl_val *v);	\
+__isl_overload								\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_add_constant_multi_val(	\
+	__isl_take isl_multi_##BASE *mpa, __isl_take isl_multi_val *mv);
 
-#define ISL_DECLARE_MULTI_NEG(BASE)					\
-__isl_give isl_multi_##BASE *isl_multi_##BASE##_neg(		 	\
-	__isl_take isl_multi_##BASE *multi);
+#define ISL_DECLARE_MULTI_ZERO(BASE)					\
+__isl_export								\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_zero(			\
+	__isl_take isl_space *space);
+
+#define ISL_DECLARE_MULTI_NAN(BASE)					\
+isl_bool isl_multi_##BASE##_involves_nan(				\
+	__isl_keep isl_multi_##BASE *multi);
 
+#define ISL_DECLARE_MULTI_DROP_DIMS(BASE)				\
+isl_size isl_multi_##BASE##_dim(__isl_keep isl_multi_##BASE *multi,	\
+	enum isl_dim_type type);					\
+__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);
 #define ISL_DECLARE_MULTI_DIMS(BASE)					\
+ISL_DECLARE_MULTI_DROP_DIMS(BASE)					\
 isl_bool isl_multi_##BASE##_involves_dims(				\
 	__isl_keep isl_multi_##BASE *multi, enum isl_dim_type type,	\
 	unsigned first, unsigned n);					\
@@ -140,6 +155,44 @@ __isl_give isl_multi_##BASE *						\
 isl_multi_##BASE##_project_domain_on_params(				\
 	__isl_take isl_multi_##BASE *multi);
 
+#define ISL_DECLARE_MULTI_LOCALS(BASE)					\
+__isl_export								\
+isl_bool isl_multi_##BASE##_involves_locals(				\
+	__isl_keep isl_multi_##BASE *multi);
+
+#define ISL_DECLARE_MULTI_DIM_ID(BASE)					\
+int isl_multi_##BASE##_find_dim_by_name(				\
+	__isl_keep isl_multi_##BASE *multi,				\
+	enum isl_dim_type type, const char *name);			\
+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_keep 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);
+
+#define ISL_DECLARE_MULTI_TUPLE_ID(BASE)				\
+const char *isl_multi_##BASE##_get_tuple_name(				\
+	__isl_keep isl_multi_##BASE *multi, enum isl_dim_type type);	\
+isl_bool 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);
+
 #define ISL_DECLARE_MULTI_WITH_DOMAIN(BASE)				\
 __isl_export								\
 __isl_give isl_multi_##BASE *isl_multi_##BASE##_product(		\
@@ -149,6 +202,26 @@ __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);
 
+#define ISL_DECLARE_MULTI_BIND_DOMAIN(BASE)				\
+__isl_export								\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_bind_domain(		\
+	__isl_take isl_multi_##BASE *multi,				\
+	__isl_take isl_multi_id *tuple);				\
+__isl_export								\
+__isl_give isl_multi_##BASE *						\
+isl_multi_##BASE##_bind_domain_wrapped_domain(				\
+	__isl_take isl_multi_##BASE *multi,				\
+	__isl_take isl_multi_id *tuple);
+
+#define ISL_DECLARE_MULTI_PARAM(BASE)					\
+__isl_overload								\
+isl_bool isl_multi_##BASE##_involves_param_id(				\
+	__isl_keep isl_multi_##BASE *multi, __isl_keep isl_id *id);	\
+__isl_overload								\
+isl_bool isl_multi_##BASE##_involves_param_id_list(			\
+	__isl_keep isl_multi_##BASE *multi,				\
+	__isl_keep isl_id_list *list);
+
 #if defined(__cplusplus)
 }
 #endif

diff  --git a/polly/lib/External/isl/include/isl/point.h b/polly/lib/External/isl/include/isl/point.h
index 1dddc628f4b5..0f907ed718ef 100644
--- a/polly/lib/External/isl/include/isl/point.h
+++ b/polly/lib/External/isl/include/isl/point.h
@@ -15,7 +15,7 @@ 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_zero(__isl_take isl_space *space);
 __isl_give isl_point *isl_point_copy(__isl_keep isl_point *pnt);
 __isl_null isl_point *isl_point_free(__isl_take isl_point *pnt);
 
@@ -23,13 +23,15 @@ __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_export
+__isl_give isl_multi_val *isl_point_get_multi_val(__isl_keep isl_point *pnt);
 
 __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);
+__isl_give isl_point *isl_point_void(__isl_take isl_space *space);
 isl_bool isl_point_is_void(__isl_keep isl_point *pnt);
 
 __isl_give isl_printer *isl_printer_print_point(

diff  --git a/polly/lib/External/isl/include/isl/polynomial.h b/polly/lib/External/isl/include/isl/polynomial.h
index 8f478c001d37..3a1b623deee2 100644
--- a/polly/lib/External/isl/include/isl/polynomial.h
+++ b/polly/lib/External/isl/include/isl/polynomial.h
@@ -20,7 +20,7 @@ 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,
+isl_size isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,
 	enum isl_dim_type type);
 isl_bool isl_qpolynomial_involves_dims(__isl_keep isl_qpolynomial *qp,
 	enum isl_dim_type type, unsigned first, unsigned n);
@@ -32,14 +32,20 @@ __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_zero_on_domain(
+	__isl_take isl_space *domain);
+__isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(
+	__isl_take isl_space *domain);
+__isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(
+	__isl_take isl_space *domain);
+__isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(
+	__isl_take isl_space *domain);
+__isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(
+	__isl_take isl_space *domain);
 __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,
+__isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain(
+	__isl_take isl_space *domain,
 	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(
@@ -101,11 +107,11 @@ __isl_give isl_qpolynomial *isl_qpolynomial_align_params(
 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);
+__isl_null isl_term *isl_term_free(__isl_take isl_term *term);
 
-unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type);
+isl_size 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,
+isl_size 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);
 
@@ -139,7 +145,8 @@ isl_bool isl_pw_qpolynomial_involves_nan(__isl_keep isl_pw_qpolynomial *pwqp);
 isl_bool 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_zero(
+	__isl_take isl_space *space);
 __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(
@@ -157,8 +164,10 @@ __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,
+isl_size isl_pw_qpolynomial_dim(__isl_keep isl_pw_qpolynomial *pwqp,
 	enum isl_dim_type type);
+isl_bool isl_pw_qpolynomial_involves_param_id(
+	__isl_keep isl_pw_qpolynomial *pwqp, __isl_keep isl_id *id);
 isl_bool isl_pw_qpolynomial_involves_dims(__isl_keep isl_pw_qpolynomial *pwqp,
 	enum isl_dim_type type, unsigned first, unsigned n);
 isl_bool isl_pw_qpolynomial_has_equal_space(
@@ -179,6 +188,12 @@ __isl_export
 __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_domain_wrapped_domain(
+	__isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
+__isl_give isl_pw_qpolynomial *
+isl_pw_qpolynomial_intersect_domain_wrapped_range(
+	__isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_intersect_params(
 	__isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_subtract_domain(
@@ -241,7 +256,7 @@ __isl_give isl_val *isl_pw_qpolynomial_eval(
 __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_n_piece(__isl_keep isl_pw_qpolynomial *pwqp);
+isl_size isl_pw_qpolynomial_n_piece(__isl_keep isl_pw_qpolynomial *pwqp);
 isl_stat isl_pw_qpolynomial_foreach_piece(__isl_keep isl_pw_qpolynomial *pwqp,
 	isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
 		    void *user), void *user);
@@ -249,6 +264,10 @@ isl_stat isl_pw_qpolynomial_foreach_lifted_piece(
 	__isl_keep isl_pw_qpolynomial *pwqp,
 	isl_stat (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
 		    void *user), void *user);
+isl_bool isl_pw_qpolynomial_isa_qpolynomial(
+	__isl_keep isl_pw_qpolynomial *pwqp);
+__isl_give isl_qpolynomial *isl_pw_qpolynomial_as_qpolynomial(
+	__isl_take isl_pw_qpolynomial *pwqp);
 
 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_pw_aff(
 	__isl_take isl_pw_aff *pwaff);
@@ -288,9 +307,10 @@ __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);
+__isl_null isl_qpolynomial_fold *isl_qpolynomial_fold_free(
+	__isl_take isl_qpolynomial_fold *fold);
 
-int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold);
+isl_bool isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold);
 isl_bool isl_qpolynomial_fold_is_nan(__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);
@@ -342,6 +362,8 @@ void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold, FILE *out
 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);
+enum isl_fold isl_pw_qpolynomial_fold_get_type(
+	__isl_keep isl_pw_qpolynomial_fold *pwf);
 
 isl_bool isl_pw_qpolynomial_fold_involves_nan(
 	__isl_keep isl_pw_qpolynomial_fold *pwf);
@@ -355,6 +377,9 @@ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
 __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_from_qpolynomial_fold(
+	__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(
@@ -369,8 +394,10 @@ __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,
+isl_size isl_pw_qpolynomial_fold_dim(__isl_keep isl_pw_qpolynomial_fold *pwf,
 	enum isl_dim_type type);
+isl_bool isl_pw_qpolynomial_fold_involves_param_id(
+	__isl_keep isl_pw_qpolynomial_fold *pwf, __isl_keep isl_id *id);
 isl_bool isl_pw_qpolynomial_fold_has_equal_space(
 	__isl_keep isl_pw_qpolynomial_fold *pwf1,
 	__isl_keep isl_pw_qpolynomial_fold *pwf2);
@@ -378,7 +405,7 @@ isl_bool isl_pw_qpolynomial_fold_has_equal_space(
 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_take isl_space *space, enum isl_fold type);
 
 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_set_dim_name(
 	__isl_take isl_pw_qpolynomial_fold *pwf,
@@ -395,6 +422,12 @@ __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_domain_wrapped_domain(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
+__isl_give isl_pw_qpolynomial_fold *
+isl_pw_qpolynomial_fold_intersect_domain_wrapped_range(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_intersect_params(
 	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_subtract_domain(
@@ -432,7 +465,8 @@ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_drop_unused_params(
 __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_n_piece(__isl_keep isl_pw_qpolynomial_fold *pwf);
+isl_size isl_pw_qpolynomial_fold_n_piece(
+	__isl_keep isl_pw_qpolynomial_fold *pwf);
 isl_stat isl_pw_qpolynomial_fold_foreach_piece(
 	__isl_keep isl_pw_qpolynomial_fold *pwf,
 	isl_stat (*fn)(__isl_take isl_set *set,
@@ -441,6 +475,10 @@ isl_stat isl_pw_qpolynomial_fold_foreach_lifted_piece(
 	__isl_keep isl_pw_qpolynomial_fold *pwf,
 	isl_stat (*fn)(__isl_take isl_set *set,
 		__isl_take isl_qpolynomial_fold *fold, void *user), void *user);
+isl_bool isl_pw_qpolynomial_fold_isa_qpolynomial_fold(
+	__isl_keep isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_qpolynomial_fold *isl_pw_qpolynomial_fold_as_qpolynomial_fold(
+	__isl_take isl_pw_qpolynomial_fold *pwf);
 
 __isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold(
 	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf);
@@ -461,15 +499,16 @@ __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_take isl_pw_qpolynomial *pwqp, enum isl_fold type,
+	isl_bool *tight);
 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
-	__isl_take isl_pw_qpolynomial_fold *pwf, int *tight);
+	__isl_take isl_pw_qpolynomial_fold *pwf, isl_bool *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_bool *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_bool *tight);
 
 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(
 	__isl_take isl_pw_qpolynomial *pwqp, int sign);
@@ -477,7 +516,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(
 isl_ctx *isl_union_pw_qpolynomial_get_ctx(
 	__isl_keep isl_union_pw_qpolynomial *upwqp);
 
-unsigned isl_union_pw_qpolynomial_dim(
+isl_size isl_union_pw_qpolynomial_dim(
 	__isl_keep isl_union_pw_qpolynomial *upwqp, enum isl_dim_type type);
 
 isl_bool isl_union_pw_qpolynomial_involves_nan(
@@ -487,8 +526,12 @@ isl_bool isl_union_pw_qpolynomial_plain_is_equal(
 	__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_ctx(
+	isl_ctx *ctx);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_zero_space(
+	__isl_take isl_space *space);
 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_zero(
-	__isl_take isl_space *dim);
+	__isl_take isl_space *space);
 __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);
@@ -526,6 +569,14 @@ __isl_give isl_union_set *isl_union_pw_qpolynomial_domain(
 __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_domain_wrapped_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_domain_wrapped_range(
+	__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);
@@ -570,7 +621,7 @@ __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_n_pw_qpolynomial(
+isl_size isl_union_pw_qpolynomial_n_pw_qpolynomial(
 	__isl_keep isl_union_pw_qpolynomial *upwqp);
 isl_stat isl_union_pw_qpolynomial_foreach_pw_qpolynomial(
 	__isl_keep isl_union_pw_qpolynomial *upwqp,
@@ -585,7 +636,7 @@ __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
 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_size isl_union_pw_qpolynomial_fold_dim(
 	__isl_keep isl_union_pw_qpolynomial_fold *upwf, enum isl_dim_type type);
 
 isl_bool isl_union_pw_qpolynomial_fold_involves_nan(
@@ -595,8 +646,13 @@ isl_bool isl_union_pw_qpolynomial_fold_plain_is_equal(
 	__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_ctx(isl_ctx *ctx, enum isl_fold type);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_zero_space(__isl_take isl_space *space,
+	enum isl_fold type);
 __isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_zero(
-	__isl_take isl_space *dim, enum isl_fold type);
+	__isl_take isl_space *space, 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);
@@ -624,6 +680,14 @@ __isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_intersec
 	__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_domain_wrapped_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_domain_wrapped_range(
+	__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);
@@ -675,7 +739,7 @@ __isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_align_pa
 	__isl_take isl_union_pw_qpolynomial_fold *upwf,
 	__isl_take isl_space *model);
 
-int isl_union_pw_qpolynomial_fold_n_pw_qpolynomial_fold(
+isl_size isl_union_pw_qpolynomial_fold_n_pw_qpolynomial_fold(
 	__isl_keep isl_union_pw_qpolynomial_fold *upwf);
 isl_stat isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
 	__isl_keep isl_union_pw_qpolynomial_fold *upwf,
@@ -690,13 +754,13 @@ __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(
 
 __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);
+	enum isl_fold type, isl_bool *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_take isl_union_pw_qpolynomial_fold *upwf, isl_bool *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_take isl_union_pw_qpolynomial_fold *upwf, isl_bool *tight);
 
 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(
 	__isl_take isl_union_pw_qpolynomial *upwqp, int sign);

diff  --git a/polly/lib/External/isl/include/isl/polynomial_type.h b/polly/lib/External/isl/include/isl/polynomial_type.h
index a8fe3cdf2433..f260219218e7 100644
--- a/polly/lib/External/isl/include/isl/polynomial_type.h
+++ b/polly/lib/External/isl/include/isl/polynomial_type.h
@@ -13,6 +13,7 @@ typedef struct isl_pw_qpolynomial isl_pw_qpolynomial;
 ISL_DECLARE_LIST_TYPE(pw_qpolynomial)
 
 enum isl_fold {
+	isl_fold_error = -1,
 	isl_fold_min,
 	isl_fold_max,
 	isl_fold_list

diff  --git a/polly/lib/External/isl/include/isl/schedule.h b/polly/lib/External/isl/include/isl/schedule.h
index 4c5de1bff45f..3792f94c00aa 100644
--- a/polly/lib/External/isl/include/isl/schedule.h
+++ b/polly/lib/External/isl/include/isl/schedule.h
@@ -129,6 +129,7 @@ __isl_give isl_schedule *isl_union_set_compute_schedule(
 	__isl_take isl_union_map *proximity);
 
 __isl_give isl_schedule *isl_schedule_empty(__isl_take isl_space *space);
+__isl_export
 __isl_give isl_schedule *isl_schedule_from_domain(
 	__isl_take isl_union_set *domain);
 __isl_give isl_schedule *isl_schedule_copy(__isl_keep isl_schedule *sched);

diff  --git a/polly/lib/External/isl/include/isl/schedule_node.h b/polly/lib/External/isl/include/isl/schedule_node.h
index 1ad55152ad0f..b336003222b0 100644
--- a/polly/lib/External/isl/include/isl/schedule_node.h
+++ b/polly/lib/External/isl/include/isl/schedule_node.h
@@ -7,13 +7,16 @@
 #include <isl/ast_type.h>
 #include <isl/val_type.h>
 #include <isl/space_type.h>
+#include <isl/id_type.h>
 
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_from_domain(
 	__isl_take isl_union_set *domain);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_from_extension(
 	__isl_take isl_union_map *extension);
 __isl_give isl_schedule_node *isl_schedule_node_copy(
@@ -21,10 +24,12 @@ __isl_give isl_schedule_node *isl_schedule_node_copy(
 __isl_null isl_schedule_node *isl_schedule_node_free(
 	__isl_take isl_schedule_node *node);
 
+__isl_export
 isl_bool isl_schedule_node_is_equal(__isl_keep isl_schedule_node *node1,
 	__isl_keep isl_schedule_node *node2);
 
 isl_ctx *isl_schedule_node_get_ctx(__isl_keep isl_schedule_node *node);
+__isl_subclass(isl_schedule_node)
 enum isl_schedule_node_type isl_schedule_node_get_type(
 	__isl_keep isl_schedule_node *node);
 enum isl_schedule_node_type isl_schedule_node_get_parent_type(
@@ -33,56 +38,76 @@ __isl_export
 __isl_give isl_schedule *isl_schedule_node_get_schedule(
 	__isl_keep isl_schedule_node *node);
 
+__isl_export
 isl_stat isl_schedule_node_foreach_descendant_top_down(
 	__isl_keep isl_schedule_node *node,
 	isl_bool (*fn)(__isl_keep isl_schedule_node *node, void *user),
 	void *user);
+__isl_export
 isl_bool isl_schedule_node_every_descendant(__isl_keep isl_schedule_node *node,
 	isl_bool (*test)(__isl_keep isl_schedule_node *node, void *user),
 	void *user);
+__isl_export
 isl_stat isl_schedule_node_foreach_ancestor_top_down(
 	__isl_keep isl_schedule_node *node,
 	isl_stat (*fn)(__isl_keep isl_schedule_node *node, void *user),
 	void *user);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_map_descendant_bottom_up(
 	__isl_take isl_schedule_node *node,
 	__isl_give isl_schedule_node *(*fn)(__isl_take isl_schedule_node *node,
 		void *user), void *user);
 
-int isl_schedule_node_get_tree_depth(__isl_keep isl_schedule_node *node);
+__isl_export
+isl_size isl_schedule_node_get_tree_depth(__isl_keep isl_schedule_node *node);
+__isl_export
 isl_bool isl_schedule_node_has_parent(__isl_keep isl_schedule_node *node);
+__isl_export
 isl_bool isl_schedule_node_has_children(__isl_keep isl_schedule_node *node);
+__isl_export
 isl_bool isl_schedule_node_has_previous_sibling(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 isl_bool isl_schedule_node_has_next_sibling(__isl_keep isl_schedule_node *node);
-int isl_schedule_node_n_children(__isl_keep isl_schedule_node *node);
-int isl_schedule_node_get_child_position(__isl_keep isl_schedule_node *node);
-int isl_schedule_node_get_ancestor_child_position(
+__isl_export
+isl_size isl_schedule_node_n_children(__isl_keep isl_schedule_node *node);
+__isl_export
+isl_size isl_schedule_node_get_child_position(
+	__isl_keep isl_schedule_node *node);
+__isl_export
+isl_size isl_schedule_node_get_ancestor_child_position(
 	__isl_keep isl_schedule_node *node,
 	__isl_keep isl_schedule_node *ancestor);
 __isl_give isl_schedule_node *isl_schedule_node_get_child(
 	__isl_keep isl_schedule_node *node, int pos);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_get_shared_ancestor(
 	__isl_keep isl_schedule_node *node1,
 	__isl_keep isl_schedule_node *node2);
 
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_root(
 	__isl_take isl_schedule_node *node);
 __isl_export
 __isl_give isl_schedule_node *isl_schedule_node_parent(
 	__isl_take isl_schedule_node *node);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_ancestor(
 	__isl_take isl_schedule_node *node, int generation);
 __isl_export
 __isl_give isl_schedule_node *isl_schedule_node_child(
 	__isl_take isl_schedule_node *node, int pos);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_first_child(
 	__isl_take isl_schedule_node *node);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_previous_sibling(
 	__isl_take isl_schedule_node *node);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_next_sibling(
 	__isl_take isl_schedule_node *node);
 
+__isl_export
 isl_bool isl_schedule_node_is_subtree_anchored(
 	__isl_keep isl_schedule_node *node);
 
@@ -94,12 +119,14 @@ __isl_give isl_schedule_node *isl_schedule_node_sequence_splice_child(
 
 __isl_give isl_space *isl_schedule_node_band_get_space(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_multi_union_pw_aff *isl_schedule_node_band_get_partial_schedule(
 	__isl_keep isl_schedule_node *node);
 __isl_give isl_union_map *isl_schedule_node_band_get_partial_schedule_union_map(
 	__isl_keep isl_schedule_node *node);
 enum isl_ast_loop_type isl_schedule_node_band_member_get_ast_loop_type(
 	__isl_keep isl_schedule_node *node, int pos);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_member_set_ast_loop_type(
 	__isl_take isl_schedule_node *node, int pos,
 	enum isl_ast_loop_type type);
@@ -109,21 +136,27 @@ __isl_give isl_schedule_node *
 isl_schedule_node_band_member_set_isolate_ast_loop_type(
 	__isl_take isl_schedule_node *node, int pos,
 	enum isl_ast_loop_type type);
+__isl_export
 __isl_give isl_union_set *isl_schedule_node_band_get_ast_build_options(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_set_ast_build_options(
 	__isl_take isl_schedule_node *node, __isl_take isl_union_set *options);
+__isl_export
 __isl_give isl_set *isl_schedule_node_band_get_ast_isolate_option(
 	__isl_keep isl_schedule_node *node);
-unsigned isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node);
+__isl_export
+isl_size isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node);
 __isl_export
 isl_bool isl_schedule_node_band_member_get_coincident(
 	__isl_keep isl_schedule_node *node, int pos);
 __isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_member_set_coincident(
 	__isl_take isl_schedule_node *node, int pos, int coincident);
+__isl_export
 isl_bool isl_schedule_node_band_get_permutable(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_set_permutable(
 	__isl_take isl_schedule_node *node, int permutable);
 
@@ -132,40 +165,54 @@ int isl_options_get_tile_scale_tile_loops(isl_ctx *ctx);
 isl_stat isl_options_set_tile_shift_point_loops(isl_ctx *ctx, int val);
 int isl_options_get_tile_shift_point_loops(isl_ctx *ctx);
 
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_scale(
 	__isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_scale_down(
 	__isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_mod(
 	__isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_shift(
 	__isl_take isl_schedule_node *node,
 	__isl_take isl_multi_union_pw_aff *shift);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_tile(
 	__isl_take isl_schedule_node *node, __isl_take isl_multi_val *sizes);
 __isl_give isl_schedule_node *isl_schedule_node_band_sink(
 	__isl_take isl_schedule_node *node);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_band_split(
 	__isl_take isl_schedule_node *node, int pos);
 
+__isl_export
 __isl_give isl_set *isl_schedule_node_context_get_context(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_union_set *isl_schedule_node_domain_get_domain(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_union_map *isl_schedule_node_expansion_get_expansion(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_union_pw_multi_aff *isl_schedule_node_expansion_get_contraction(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_union_map *isl_schedule_node_extension_get_extension(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_union_set *isl_schedule_node_filter_get_filter(
 	__isl_keep isl_schedule_node *node);
+__isl_export
 __isl_give isl_set *isl_schedule_node_guard_get_guard(
 	__isl_keep isl_schedule_node *node);
 __isl_give isl_id *isl_schedule_node_mark_get_id(
 	__isl_keep isl_schedule_node *node);
 
-int isl_schedule_node_get_schedule_depth(__isl_keep isl_schedule_node *node);
+isl_size isl_schedule_node_get_schedule_depth(
+	__isl_keep isl_schedule_node *node);
 __isl_give isl_union_set *isl_schedule_node_get_domain(
 	__isl_keep isl_schedule_node *node);
 __isl_give isl_union_set *isl_schedule_node_get_universe_domain(
@@ -190,20 +237,27 @@ __isl_give isl_union_map *isl_schedule_node_get_subtree_expansion(
 __isl_give isl_union_pw_multi_aff *isl_schedule_node_get_subtree_contraction(
 	__isl_keep isl_schedule_node *node);
 
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_insert_context(
 	__isl_take isl_schedule_node *node, __isl_take isl_set *context);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_insert_partial_schedule(
 	__isl_take isl_schedule_node *node,
 	__isl_take isl_multi_union_pw_aff *schedule);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_insert_filter(
 	__isl_take isl_schedule_node *node, __isl_take isl_union_set *filter);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_insert_guard(
 	__isl_take isl_schedule_node *node, __isl_take isl_set *context);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_insert_mark(
 	__isl_take isl_schedule_node *node, __isl_take isl_id *mark);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_insert_sequence(
 	__isl_take isl_schedule_node *node,
 	__isl_take isl_union_set_list *filters);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_insert_set(
 	__isl_take isl_schedule_node *node,
 	__isl_take isl_union_set_list *filters);
@@ -213,14 +267,18 @@ __isl_give isl_schedule_node *isl_schedule_node_cut(
 __isl_give isl_schedule_node *isl_schedule_node_delete(
 	__isl_take isl_schedule_node *node);
 
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_order_before(
 	__isl_take isl_schedule_node *node, __isl_take isl_union_set *filter);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_order_after(
 	__isl_take isl_schedule_node *node, __isl_take isl_union_set *filter);
 
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_graft_before(
 	__isl_take isl_schedule_node *node,
 	__isl_take isl_schedule_node *graft);
+__isl_export
 __isl_give isl_schedule_node *isl_schedule_node_graft_after(
 	__isl_take isl_schedule_node *node,
 	__isl_take isl_schedule_node *graft);

diff  --git a/polly/lib/External/isl/include/isl/set.h b/polly/lib/External/isl/include/isl/set.h
index 50c71d03b7e8..d86daadcb969 100644
--- a/polly/lib/External/isl/include/isl/set.h
+++ b/polly/lib/External/isl/include/isl/set.h
@@ -20,24 +20,26 @@
 #include <isl/val_type.h>
 #include <isl/stdint.h>
 #include <isl/stride_info.h>
+#include <isl/fixed_box.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(__isl_keep const isl_basic_set *bset);
-unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
+isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset);
+isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset);
+isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset);
+isl_size 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_size isl_set_n_dim(__isl_keep isl_set *set);
+isl_size isl_set_n_param(__isl_keep isl_set *set);
+isl_size 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_export
 __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);
@@ -95,7 +97,8 @@ __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);
 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space);
 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space);
-__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_set *isl_basic_set_nat_universe(
+	__isl_take isl_space *space);
 __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,
@@ -166,6 +169,18 @@ __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
 	__isl_take isl_val *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_overload
+__isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
+	__isl_take isl_multi_val *lower);
+__isl_overload
+__isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
+	__isl_take isl_multi_val *upper);
+__isl_overload
+__isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
+	__isl_take isl_multi_pw_aff *lower);
+__isl_overload
+__isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
+	__isl_take isl_multi_pw_aff *upper);
 
 __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);
@@ -202,8 +217,10 @@ __isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
 __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_export
 __isl_give isl_pw_multi_aff *isl_set_lexmin_pw_multi_aff(
 	__isl_take isl_set *set);
+__isl_export
 __isl_give isl_pw_multi_aff *isl_set_lexmax_pw_multi_aff(
 	__isl_take isl_set *set);
 
@@ -212,17 +229,29 @@ __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_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
+	__isl_keep isl_basic_set *bset2, int pos);
 int isl_set_follows_at(__isl_keep isl_set *set1,
 	__isl_keep isl_set *set2, int pos);
 
+__isl_export
 __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_export
 __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);
 
+__isl_export
+__isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
+	__isl_take isl_multi_id *tuple);
+__isl_export
+__isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
+	__isl_take isl_multi_id *tuple);
+__isl_export
+__isl_give isl_map *isl_set_unbind_params_insert_domain(
+	__isl_take isl_set *set, __isl_take isl_multi_id *domain);
+
 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
 	enum isl_dim_type type, unsigned pos, unsigned n, int *signs);
 
@@ -238,7 +267,9 @@ isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
 	__isl_keep isl_basic_set *bset2);
 
+__isl_export
 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space);
+__isl_export
 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space);
 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim);
 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set);
@@ -274,6 +305,7 @@ __isl_export
 __isl_give isl_set *isl_set_union(
 		__isl_take isl_set *set1,
 		__isl_take isl_set *set2);
+__isl_export
 __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(
@@ -287,6 +319,10 @@ __isl_give isl_set *isl_set_intersect(
 __isl_export
 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
 		__isl_take isl_set *params);
+__isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
+	__isl_take isl_set *domain);
+__isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
+	__isl_take isl_set *range);
 __isl_export
 __isl_give isl_set *isl_set_subtract(
 		__isl_take isl_set *set1,
@@ -297,10 +333,13 @@ __isl_export
 __isl_give isl_set *isl_set_apply(
 		__isl_take isl_set *set,
 		__isl_take isl_map *map);
+__isl_overload
 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
 	__isl_take isl_multi_aff *ma);
+__isl_overload
 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
 	__isl_take isl_pw_multi_aff *pma);
+__isl_overload
 __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,
@@ -325,8 +364,16 @@ __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
 __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_overload
+__isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
+	__isl_take isl_id *id);
+__isl_overload
+__isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
+	__isl_take isl_id_list *list);
 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
 		enum isl_dim_type type, unsigned first, unsigned n);
+__isl_export
+__isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set);
 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
 	enum isl_dim_type type, unsigned first, unsigned n);
 __isl_give isl_basic_set *isl_basic_set_remove_divs(
@@ -387,6 +434,7 @@ isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
 __isl_export
 isl_bool isl_set_is_disjoint(__isl_keep isl_set *set1,
 	__isl_keep isl_set *set2);
+__isl_export
 isl_bool isl_set_is_singleton(__isl_keep isl_set *set);
 isl_bool isl_set_is_box(__isl_keep isl_set *set);
 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
@@ -403,6 +451,9 @@ __isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set);
 ISL_DEPRECATED
 __isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set);
 
+__isl_export
+__isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
+	__isl_keep isl_set *set);
 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
 	enum isl_dim_type type, unsigned pos);
 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
@@ -433,6 +484,9 @@ __isl_give isl_stride_info *isl_set_get_stride_info(__isl_keep isl_set *set,
 	int pos);
 __isl_export
 __isl_give isl_val *isl_set_get_stride(__isl_keep isl_set *set, int pos);
+__isl_export
+__isl_give isl_fixed_box *isl_set_get_simple_fixed_box_hull(
+	__isl_keep isl_set *set);
 
 __isl_export
 __isl_give isl_set *isl_set_coalesce(__isl_take isl_set *set);
@@ -445,13 +499,14 @@ isl_bool isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
 
 uint32_t isl_set_get_hash(struct isl_set *set);
 
-int isl_set_n_basic_set(__isl_keep isl_set *set);
+isl_size isl_set_n_basic_set(__isl_keep isl_set *set);
 __isl_export
 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
 	isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user);
 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
 	__isl_keep isl_set *set);
 
+__isl_export
 isl_stat isl_set_foreach_point(__isl_keep isl_set *set,
 	isl_stat (*fn)(__isl_take isl_point *pnt, void *user), void *user);
 __isl_give isl_val *isl_set_count_val(__isl_keep isl_set *set);

diff  --git a/polly/lib/External/isl/include/isl/space.h b/polly/lib/External/isl/include/isl/space.h
index 40a333ea9692..4a43c2566d15 100644
--- a/polly/lib/External/isl/include/isl/space.h
+++ b/polly/lib/External/isl/include/isl/space.h
@@ -19,13 +19,15 @@
 extern "C" {
 #endif
 
-isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim);
+isl_ctx *isl_space_get_ctx(__isl_keep isl_space *space);
+__isl_export
+__isl_give isl_space *isl_space_unit(isl_ctx *ctx);
 __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_give isl_space *isl_space_copy(__isl_keep isl_space *space);
 __isl_null isl_space *isl_space_free(__isl_take isl_space *space);
 
 isl_bool isl_space_is_params(__isl_keep isl_space *space);
@@ -35,40 +37,40 @@ isl_bool isl_space_is_map(__isl_keep isl_space *space);
 __isl_give isl_space *isl_space_add_param_id(__isl_take isl_space *space,
 	__isl_take isl_id *id);
 
-__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *space,
 	enum isl_dim_type type, const char *s);
 isl_bool isl_space_has_tuple_name(__isl_keep isl_space *space,
 	enum isl_dim_type type);
-__isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
+__isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *space,
 				 enum isl_dim_type type);
-__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *space,
 	enum isl_dim_type type, __isl_take isl_id *id);
-__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *space,
 	enum isl_dim_type type);
-isl_bool isl_space_has_tuple_id(__isl_keep isl_space *dim,
+isl_bool isl_space_has_tuple_id(__isl_keep isl_space *space,
 	enum isl_dim_type type);
-__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
+__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *space,
 	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);
-isl_bool isl_space_has_dim_id(__isl_keep isl_space *dim,
+isl_bool isl_space_has_dim_id(__isl_keep isl_space *space,
 	enum isl_dim_type type, unsigned pos);
-__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim,
+__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *space,
 	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_id(__isl_keep isl_space *space,
+	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);
 
 isl_bool 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,
+__isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *space,
 				 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,
+__isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *space,
 				 enum isl_dim_type type, unsigned pos);
 
 ISL_DEPRECATED
@@ -99,11 +101,13 @@ __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_export
 __isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *space);
 __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,
+__isl_give isl_space *isl_space_reverse(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_range_reverse(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *space,
 	enum isl_dim_type type, unsigned first, unsigned num);
 ISL_DEPRECATED
 __isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
@@ -111,27 +115,40 @@ __isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
 ISL_DEPRECATED
 __isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
 		unsigned first, unsigned n);
+__isl_give isl_space *isl_space_drop_all_params(__isl_take isl_space *space);
+__isl_export
 __isl_give isl_space *isl_space_domain(__isl_take isl_space *space);
-__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *space);
+__isl_export
 __isl_give isl_space *isl_space_range(__isl_take isl_space *space);
-__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_from_range(__isl_take isl_space *space);
 __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_export
 __isl_give isl_space *isl_space_params(__isl_take isl_space *space);
+__isl_overload
+__isl_give isl_space *isl_space_add_unnamed_tuple_ui(
+	__isl_take isl_space *space, unsigned dim);
+__isl_overload
+__isl_give isl_space *isl_space_add_named_tuple_id_ui(
+	__isl_take isl_space *space, __isl_take isl_id *tuple_id, unsigned dim);
 __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);
 
-isl_bool isl_space_is_wrapping(__isl_keep isl_space *dim);
+__isl_export
+isl_bool isl_space_is_wrapping(__isl_keep isl_space *space);
 isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space);
 isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space);
 isl_bool isl_space_is_product(__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);
+__isl_export
+__isl_give isl_space *isl_space_wrap(__isl_take isl_space *space);
+__isl_export
+__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *space);
 
 isl_bool isl_space_can_zip(__isl_keep isl_space *space);
-__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_zip(__isl_take isl_space *space);
 
 isl_bool isl_space_can_curry(__isl_keep isl_space *space);
 __isl_give isl_space *isl_space_curry(__isl_take isl_space *space);
@@ -146,6 +163,7 @@ isl_bool isl_space_is_domain(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2);
 isl_bool isl_space_is_range(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2);
+__isl_export
 isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2);
 isl_bool isl_space_has_equal_params(__isl_keep isl_space *space1,
@@ -158,15 +176,17 @@ isl_bool isl_space_tuple_is_equal(__isl_keep isl_space *space1,
 ISL_DEPRECATED
 isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
 	__isl_keep isl_space *space2, enum isl_dim_type type2);
-unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type);
+isl_size isl_space_dim(__isl_keep isl_space *space, enum isl_dim_type type);
 
+__isl_export
 __isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *space);
+__isl_export
 __isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *space);
 
 __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);
+	__isl_keep isl_space *space);
+void isl_space_dump(__isl_keep isl_space *space);
 
 #if defined(__cplusplus)
 }

diff  --git a/polly/lib/External/isl/include/isl/space_type.h b/polly/lib/External/isl/include/isl/space_type.h
index 6a181555db84..60c31b0d21d8 100644
--- a/polly/lib/External/isl/include/isl/space_type.h
+++ b/polly/lib/External/isl/include/isl/space_type.h
@@ -1,11 +1,13 @@
 #ifndef ISL_SPACE_TYPE_H
 #define ISL_SPACE_TYPE_H
 
+#include <isl/ctx.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
-struct isl_space;
+struct __isl_export isl_space;
 typedef struct isl_space isl_space;
 
 enum isl_dim_type {

diff  --git a/polly/lib/External/isl/include/isl/stream.h b/polly/lib/External/isl/include/isl/stream.h
index 38888d3a90f3..b77797f327e0 100644
--- a/polly/lib/External/isl/include/isl/stream.h
+++ b/polly/lib/External/isl/include/isl/stream.h
@@ -38,6 +38,7 @@ enum isl_token_type { ISL_TOKEN_ERROR = -1,
 			ISL_TOKEN_MAP, ISL_TOKEN_AFF,
 			ISL_TOKEN_CEIL, ISL_TOKEN_FLOOR,
 			ISL_TOKEN_IMPLIES,
+			ISL_TOKEN_INT_DIV,
 			ISL_TOKEN_LAST };
 
 struct isl_token;

diff  --git a/polly/lib/External/isl/include/isl/union_map.h b/polly/lib/External/isl/include/isl/union_map.h
index 18db9af4e217..bb9518690702 100644
--- a/polly/lib/External/isl/include/isl/union_map.h
+++ b/polly/lib/External/isl/include/isl/union_map.h
@@ -13,7 +13,7 @@
 extern "C" {
 #endif
 
-unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+isl_size isl_union_map_dim(__isl_keep isl_union_map *umap,
 	enum isl_dim_type type);
 isl_bool isl_union_map_involves_dims(__isl_keep isl_union_map *umap,
 	enum isl_dim_type type, unsigned first, unsigned n);
@@ -25,11 +25,16 @@ __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_overload
+__isl_give isl_union_map *isl_union_map_empty_ctx(isl_ctx *ctx);
+__isl_give isl_union_map *isl_union_map_empty_space(
+	__isl_take isl_space *space);
 __isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *space);
 __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_export
 __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(
@@ -38,6 +43,7 @@ __isl_give isl_union_map *isl_union_map_reset_user(
 int isl_union_map_find_dim_by_name(__isl_keep isl_union_map *umap,
 	enum isl_dim_type type, const char *name);
 
+__isl_export
 __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);
@@ -148,6 +154,10 @@ __isl_give isl_union_map *isl_union_map_intersect_domain(
 __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_give isl_union_map *isl_union_map_intersect_domain_factor_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_map *factor);
+__isl_give isl_union_map *isl_union_map_intersect_range_factor_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_map *factor);
 __isl_give isl_union_map *isl_union_map_intersect_range_factor_range(
 	__isl_take isl_union_map *umap, __isl_take isl_union_map *factor);
 
@@ -164,25 +174,35 @@ __isl_give isl_union_map *isl_union_map_apply_domain(
 __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_overload
 __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_overload
 __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_overload
 __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_overload
 __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_overload
 __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_overload
 __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_overload
 __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_export
+__isl_give isl_union_map *isl_union_map_range_reverse(
+	__isl_take isl_union_map *umap);
+__isl_export
 __isl_give isl_union_map *isl_union_map_from_domain_and_range(
 	__isl_take isl_union_set *domain, __isl_take isl_union_set *range);
 
@@ -205,6 +225,10 @@ __isl_give isl_union_map *isl_union_map_project_out_all_params(
 __isl_give isl_union_map *isl_union_map_remove_divs(
 	__isl_take isl_union_map *bmap);
 
+__isl_export
+__isl_give isl_union_set *isl_union_map_bind_range(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_id *tuple);
+
 isl_bool isl_union_map_plain_is_empty(__isl_keep isl_union_map *umap);
 __isl_export
 isl_bool isl_union_map_is_empty(__isl_keep isl_union_map *umap);
@@ -223,6 +247,7 @@ isl_bool isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
 __isl_export
 isl_bool isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
 	__isl_keep isl_union_map *umap2);
+__isl_export
 isl_bool isl_union_map_is_disjoint(__isl_keep isl_union_map *umap1,
 	__isl_keep isl_union_map *umap2);
 __isl_export
@@ -231,12 +256,13 @@ isl_bool isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
 
 uint32_t isl_union_map_get_hash(__isl_keep isl_union_map *umap);
 
-int isl_union_map_n_map(__isl_keep isl_union_map *umap);
+isl_size isl_union_map_n_map(__isl_keep isl_union_map *umap);
 __isl_export
 isl_stat isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
 	isl_stat (*fn)(__isl_take isl_map *map, void *user), void *user);
 __isl_give isl_map_list *isl_union_map_get_map_list(
 	__isl_keep isl_union_map *umap);
+__isl_export
 isl_bool isl_union_map_every_map(__isl_keep isl_union_map *umap,
 	isl_bool (*test)(__isl_keep isl_map *map, void *user), void *user);
 __isl_give isl_union_map *isl_union_map_remove_map_if(
@@ -244,8 +270,11 @@ __isl_give isl_union_map *isl_union_map_remove_map_if(
 	isl_bool (*fn)(__isl_keep isl_map *map, void *user), void *user);
 isl_bool isl_union_map_contains(__isl_keep isl_union_map *umap,
 	__isl_keep isl_space *space);
+__isl_export
 __isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
-	__isl_take isl_space *dim);
+	__isl_take isl_space *space);
+__isl_export
+isl_bool isl_union_map_isa_map(__isl_keep isl_union_map *umap);
 __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);
@@ -254,9 +283,9 @@ __isl_overload
 __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_bool *exact);
 __isl_give isl_union_map *isl_union_map_transitive_closure(
-	__isl_take isl_union_map *umap, int *exact);
+	__isl_take isl_union_map *umap, isl_bool *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);
@@ -295,9 +324,11 @@ __isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset);
 
 __isl_export
 __isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap);
+__isl_export
 __isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap);
 __isl_give isl_union_map *isl_union_map_range_curry(
 	__isl_take isl_union_map *umap);
+__isl_export
 __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(

diff  --git a/polly/lib/External/isl/include/isl/union_map_type.h b/polly/lib/External/isl/include/isl/union_map_type.h
index 72fdffdf4f1d..7b6e69f573e6 100644
--- a/polly/lib/External/isl/include/isl/union_map_type.h
+++ b/polly/lib/External/isl/include/isl/union_map_type.h
@@ -14,7 +14,7 @@ ISL_DECLARE_LIST_TYPE(union_map)
 #ifndef isl_union_set
 struct __isl_export isl_union_set;
 typedef struct isl_union_set isl_union_set;
-ISL_DECLARE_LIST_TYPE(union_set)
+ISL_DECLARE_EXPORTED_LIST_TYPE(union_set)
 #endif
 
 #if defined(__cplusplus)

diff  --git a/polly/lib/External/isl/include/isl/union_set.h b/polly/lib/External/isl/include/isl/union_set.h
index 0e6fc9843f49..8531da869bcf 100644
--- a/polly/lib/External/isl/include/isl/union_set.h
+++ b/polly/lib/External/isl/include/isl/union_set.h
@@ -8,7 +8,7 @@
 extern "C" {
 #endif
 
-unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+isl_size isl_union_set_dim(__isl_keep isl_union_set *uset,
 	enum isl_dim_type type);
 
 __isl_constructor
@@ -16,16 +16,22 @@ __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_overload
+__isl_give isl_union_set *isl_union_set_empty_ctx(isl_ctx *ctx);
+__isl_give isl_union_set *isl_union_set_empty_space(
+	__isl_take isl_space *space);
 __isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *space);
 __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_export
 __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_export
 __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);
@@ -94,6 +100,8 @@ __isl_give isl_union_set *isl_union_set_preimage_union_pw_multi_aff(
 __isl_give isl_union_set *isl_union_set_project_out(
 	__isl_take isl_union_set *uset,
 	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_union_set *isl_union_set_project_out_all_params(
+	__isl_take isl_union_set *uset);
 __isl_give isl_union_set *isl_union_set_remove_divs(
 	__isl_take isl_union_set *bset);
 
@@ -107,6 +115,7 @@ isl_bool isl_union_set_is_subset(__isl_keep isl_union_set *uset1,
 __isl_export
 isl_bool isl_union_set_is_equal(__isl_keep isl_union_set *uset1,
 	__isl_keep isl_union_set *uset2);
+__isl_export
 isl_bool isl_union_set_is_disjoint(__isl_keep isl_union_set *uset1,
 	__isl_keep isl_union_set *uset2);
 __isl_export
@@ -115,18 +124,24 @@ isl_bool isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
 
 uint32_t isl_union_set_get_hash(__isl_keep isl_union_set *uset);
 
-int isl_union_set_n_set(__isl_keep isl_union_set *uset);
+isl_size isl_union_set_n_set(__isl_keep isl_union_set *uset);
 __isl_export
 isl_stat isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
 	isl_stat (*fn)(__isl_take isl_set *set, void *user), void *user);
+__isl_export
+isl_bool isl_union_set_every_set(__isl_keep isl_union_set *uset,
+	isl_bool (*test)(__isl_keep isl_set *set, void *user), void *user);
 __isl_give isl_basic_set_list *isl_union_set_get_basic_set_list(
 	__isl_keep isl_union_set *uset);
 __isl_give isl_set_list *isl_union_set_get_set_list(
 	__isl_keep isl_union_set *uset);
 isl_bool isl_union_set_contains(__isl_keep isl_union_set *uset,
 	__isl_keep isl_space *space);
+__isl_export
 __isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
-	__isl_take isl_space *dim);
+	__isl_take isl_space *space);
+__isl_export
+isl_bool isl_union_set_isa_set(__isl_keep isl_union_set *uset);
 __isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset);
 __isl_export
 isl_stat isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
@@ -166,7 +181,7 @@ __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);
 
-ISL_DECLARE_LIST_FN(union_set)
+ISL_DECLARE_EXPORTED_LIST_FN(union_set)
 
 __isl_give isl_union_set *isl_union_set_list_union(
 	__isl_take isl_union_set_list *list);

diff  --git a/polly/lib/External/isl/include/isl/val.h b/polly/lib/External/isl/include/isl/val.h
index faf3e158c494..8c11efc02571 100644
--- a/polly/lib/External/isl/include/isl/val.h
+++ b/polly/lib/External/isl/include/isl/val.h
@@ -13,8 +13,12 @@ extern "C" {
 #endif
 
 ISL_DECLARE_MULTI(val)
-ISL_DECLARE_MULTI_NEG(val)
+ISL_DECLARE_MULTI_ARITH(val)
+ISL_DECLARE_MULTI_ZERO(val)
+ISL_DECLARE_MULTI_NAN(val)
 ISL_DECLARE_MULTI_DIMS(val)
+ISL_DECLARE_MULTI_DIM_ID(val)
+ISL_DECLARE_MULTI_TUPLE_ID(val)
 ISL_DECLARE_MULTI_WITH_DOMAIN(val)
 
 __isl_export
@@ -40,12 +44,14 @@ __isl_null isl_val *isl_val_free(__isl_take isl_val *v);
 
 isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val);
 uint32_t isl_val_get_hash(__isl_keep isl_val *val);
+__isl_export
 long isl_val_get_num_si(__isl_keep isl_val *v);
+__isl_export
 long isl_val_get_den_si(__isl_keep isl_val *v);
 __isl_give isl_val *isl_val_get_den_val(__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,
+isl_size isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size);
+isl_stat 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);
@@ -145,11 +151,15 @@ __isl_give isl_printer *isl_printer_print_val(__isl_take isl_printer *p,
 void isl_val_dump(__isl_keep isl_val *v);
 __isl_give char *isl_val_to_str(__isl_keep isl_val *v);
 
+isl_bool isl_multi_val_is_zero(__isl_keep isl_multi_val *mv);
+
+__isl_overload
 __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_constructor
 __isl_give isl_multi_val *isl_multi_val_read_from_str(isl_ctx *ctx,
 	const char *str);
 __isl_give isl_printer *isl_printer_print_multi_val(__isl_take isl_printer *p,
@@ -157,7 +167,7 @@ __isl_give isl_printer *isl_printer_print_multi_val(__isl_take isl_printer *p,
 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);
 
-ISL_DECLARE_LIST_FN(val)
+ISL_DECLARE_EXPORTED_LIST_FN(val)
 
 #if defined(__cplusplus)
 }

diff  --git a/polly/lib/External/isl/include/isl/val_type.h b/polly/lib/External/isl/include/isl/val_type.h
index f50be69ec9ae..ede64013c6ba 100644
--- a/polly/lib/External/isl/include/isl/val_type.h
+++ b/polly/lib/External/isl/include/isl/val_type.h
@@ -10,7 +10,7 @@ extern "C" {
 struct __isl_export isl_val;
 typedef struct isl_val isl_val;
 
-ISL_DECLARE_LIST_TYPE(val)
+ISL_DECLARE_EXPORTED_LIST_TYPE(val)
 
 struct __isl_export isl_multi_val;
 typedef struct isl_multi_val isl_multi_val;

diff  --git a/polly/lib/External/isl/include/isl/vec.h b/polly/lib/External/isl/include/isl/vec.h
index 23c8f581bb4c..6baa87bd25c6 100644
--- a/polly/lib/External/isl/include/isl/vec.h
+++ b/polly/lib/External/isl/include/isl/vec.h
@@ -30,7 +30,7 @@ __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_size 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);

diff  --git a/polly/lib/External/isl/include/isl/vertices.h b/polly/lib/External/isl/include/isl/vertices.h
index 6a7ee6ac8752..9a7ac508c56c 100644
--- a/polly/lib/External/isl/include/isl/vertices.h
+++ b/polly/lib/External/isl/include/isl/vertices.h
@@ -18,15 +18,15 @@ 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_size 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_null isl_vertex *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);
+isl_size isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices);
 isl_stat isl_vertices_foreach_vertex(__isl_keep isl_vertices *vertices,
 	isl_stat (*fn)(__isl_take isl_vertex *vertex, void *user), void *user);
 __isl_null isl_vertices *isl_vertices_free(__isl_take isl_vertices *vertices);
@@ -35,7 +35,7 @@ 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);
 isl_stat isl_cell_foreach_vertex(__isl_keep isl_cell *cell,
 	isl_stat (*fn)(__isl_take isl_vertex *vertex, void *user), void *user);
-void isl_cell_free(__isl_take isl_cell *cell);
+__isl_null isl_cell *isl_cell_free(__isl_take isl_cell *cell);
 
 isl_stat isl_vertices_foreach_cell(__isl_keep isl_vertices *vertices,
 	isl_stat (*fn)(__isl_take isl_cell *cell, void *user), void *user);

diff  --git a/polly/lib/External/isl/interface/Makefile.am b/polly/lib/External/isl/interface/Makefile.am
index fa09ce46c304..b0cfb38c9c7d 100644
--- a/polly/lib/External/isl/interface/Makefile.am
+++ b/polly/lib/External/isl/interface/Makefile.am
@@ -18,7 +18,7 @@ extract_interface_SOURCES = \
 	cpp_conversion.cc \
 	extract_interface.h \
 	extract_interface.cc
-extract_interface_LDFLAGS = $(CLANG_LDFLAGS)
+extract_interface_LDFLAGS = $(CLANG_LDFLAGS) $(CLANG_RFLAG)
 extract_interface_LDADD = \
 	-lclangFrontend -lclangSerialization -lclangParse -lclangSema \
 	$(LIB_CLANG_EDIT) \

diff  --git a/polly/lib/External/isl/interface/Makefile.in b/polly/lib/External/isl/interface/Makefile.in
index f34c851c92f5..08dd517cac2f 100644
--- a/polly/lib/External/isl/interface/Makefile.in
+++ b/polly/lib/External/isl/interface/Makefile.in
@@ -99,6 +99,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
 	$(top_srcdir)/m4/ax_create_stdint_h.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
+	$(top_srcdir)/m4/ax_cxx_compile_stdcxx_11_no_override.m4 \
 	$(top_srcdir)/m4/ax_detect_clang.m4 \
 	$(top_srcdir)/m4/ax_detect_git_head.m4 \
 	$(top_srcdir)/m4/ax_detect_gmp.m4 \
@@ -230,13 +231,15 @@ CFLAGS = @CFLAGS@
 CLANG_CXXFLAGS = @CLANG_CXXFLAGS@
 CLANG_LDFLAGS = @CLANG_LDFLAGS@
 CLANG_LIBS = @CLANG_LIBS@
+CLANG_RFLAG = @CLANG_RFLAG@
+CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX = @CXX@
-CXX11FLAGS = @CXX11FLAGS@
 CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
+CYGPATH = @CYGPATH@
 CYGPATH_W = @CYGPATH_W@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
@@ -266,12 +269,14 @@ LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIB_CLANG_EDIT = @LIB_CLANG_EDIT@
 LIPO = @LIPO@
+LLVM_CONFIG = @LLVM_CONFIG@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
 LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
 MAKEINFO = @MAKEINFO@
 MANIFEST_TOOL = @MANIFEST_TOOL@
 MKDIR_P = @MKDIR_P@
+MP_CFLAGS = @MP_CFLAGS@
 MP_CPPFLAGS = @MP_CPPFLAGS@
 MP_LDFLAGS = @MP_LDFLAGS@
 MP_LIBS = @MP_LIBS@
@@ -279,6 +284,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OS_SRCDIR = @OS_SRCDIR@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -341,7 +347,6 @@ infodir = @infodir@
 install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
-llvm_config_found = @llvm_config_found@
 localedir = @localedir@
 localstatedir = @localstatedir@
 mandir = @mandir@
@@ -385,7 +390,7 @@ extract_interface_SOURCES = \
 	extract_interface.h \
 	extract_interface.cc
 
-extract_interface_LDFLAGS = $(CLANG_LDFLAGS)
+extract_interface_LDFLAGS = $(CLANG_LDFLAGS) $(CLANG_RFLAG)
 extract_interface_LDADD = \
 	-lclangFrontend -lclangSerialization -lclangParse -lclangSema \
 	$(LIB_CLANG_EDIT) \

diff  --git a/polly/lib/External/isl/interface/cpp.cc b/polly/lib/External/isl/interface/cpp.cc
index a52e6fec06b3..785e0782787d 100644
--- a/polly/lib/External/isl/interface/cpp.cc
+++ b/polly/lib/External/isl/interface/cpp.cc
@@ -47,23 +47,51 @@
  * This osprintf method allows us to use printf style formatting constructs when
  * writing to an ostream.
  */
-static void osprintf(ostream &os, const char *format, ...)
+static void osprintf(ostream &os, const char *format, va_list arguments)
 {
-	va_list arguments;
+	va_list copy;
 	char *string_pointer;
 	size_t size;
 
-	va_start(arguments, format);
-	size = vsnprintf(NULL, 0, format, arguments);
+	va_copy(copy, arguments);
+	size = vsnprintf(NULL, 0, format, copy);
 	string_pointer = new char[size + 1];
-	va_end(arguments);
-	va_start(arguments, format);
+	va_end(copy);
 	vsnprintf(string_pointer, size + 1, format, arguments);
-	va_end(arguments);
 	os << string_pointer;
 	delete[] string_pointer;
 }
 
+/* Print string formatted according to "fmt" to ostream "os".
+ *
+ * This osprintf method allows us to use printf style formatting constructs when
+ * writing to an ostream.
+ */
+static void osprintf(ostream &os, const char *format, ...)
+{
+	va_list arguments;
+
+	va_start(arguments, format);
+	osprintf(os, format, arguments);
+	va_end(arguments);
+}
+
+/* Print string formatted according to "fmt" to ostream "os"
+ * with the given indentation.
+ *
+ * This osprintf method allows us to use printf style formatting constructs when
+ * writing to an ostream.
+ */
+static void osprintf(ostream &os, int indent, const char *format, ...)
+{
+	va_list arguments;
+
+	osprintf(os, "%*s", indent, " ");
+	va_start(arguments, format);
+	osprintf(os, format, arguments);
+	va_end(arguments);
+}
+
 /* Convert "l" to a string.
  */
 static std::string to_string(long l)
@@ -149,7 +177,48 @@ void cpp_generator::print_implementations(ostream &os)
 	}
 }
 
+/* If "clazz" is a subclass that is based on a type function,
+ * then introduce a "type" field that holds the value of the type
+ * corresponding to the subclass and make the fields of the class
+ * accessible to the "isa" and "as" methods of the (immediate) superclass.
+ * In particular, "isa" needs access to the type field itself,
+ * while "as" needs access to the private constructor.
+ * In case of the "isa" method, all instances are made friends
+ * to avoid access right confusion.
+ */
+void cpp_generator::print_subclass_type(ostream &os, const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	std::string super;
+	const char *cppname = cppstring.c_str();
+	const char *supername;
+
+	if (!clazz.is_type_subclass())
+		return;
+
+	super = type2cpp(clazz.superclass_name);
+	supername = super.c_str();
+	osprintf(os, "  template <class T>\n");
+	osprintf(os, "  friend %s %s::isa() const;\n",
+		isl_bool2cpp().c_str(), supername);
+	osprintf(os, "  friend %s %s::as<%s>() const;\n",
+		cppname, supername, cppname);
+	osprintf(os, "  static const auto type = %s;\n",
+		clazz.subclass_name.c_str());
+}
+
 /* Print declarations for class "clazz" to "os".
+ *
+ * If "clazz" is a subclass based on a type function,
+ * then it is made to inherit from the (immediate) superclass and
+ * a "type" attribute is added for use in the "as" and "isa"
+ * methods of the superclass.
+ *
+ * Conversely, if "clazz" is a superclass with a type function,
+ * then declare those "as" and "isa" methods.
+ *
+ * The pointer to the isl object is only added for classes that
+ * are not subclasses, since subclasses refer to the same isl object.
  */
 void cpp_generator::print_class(ostream &os, const isl_class &clazz)
 {
@@ -161,12 +230,20 @@ void cpp_generator::print_class(ostream &os, const isl_class &clazz)
 
 	print_class_factory_decl(os, clazz);
 	osprintf(os, "\n");
-	osprintf(os, "class %s {\n", cppname);
+	osprintf(os, "class %s ", cppname);
+	if (clazz.is_type_subclass())
+		osprintf(os, ": public %s ",
+			type2cpp(clazz.superclass_name).c_str());
+	osprintf(os, "{\n");
+	print_subclass_type(os, clazz);
 	print_class_factory_decl(os, clazz, "  friend ");
 	osprintf(os, "\n");
-	osprintf(os, "  %s *ptr = nullptr;\n", name);
-	osprintf(os, "\n");
-	print_private_constructors_decl(os, clazz);
+	osprintf(os, "protected:\n");
+	if (!clazz.is_type_subclass()) {
+		osprintf(os, "  %s *ptr = nullptr;\n", name);
+		osprintf(os, "\n");
+	}
+	print_protected_constructors_decl(os, clazz);
 	osprintf(os, "\n");
 	osprintf(os, "public:\n");
 	print_public_constructors_decl(os, clazz);
@@ -174,9 +251,12 @@ void cpp_generator::print_class(ostream &os, const isl_class &clazz)
 	print_copy_assignment_decl(os, clazz);
 	print_destructor_decl(os, clazz);
 	print_ptr_decl(os, clazz);
-	print_get_ctx_decl(os);
+	print_downcast_decl(os, clazz);
+	print_ctx_decl(os);
 	osprintf(os, "\n");
+	print_persistent_callbacks_decl(os, clazz);
 	print_methods_decl(os, clazz);
+	print_set_enums_decl(os, clazz);
 
 	osprintf(os, "};\n");
 }
@@ -206,6 +286,10 @@ void cpp_generator::print_class_forward_decl(ostream &os,
  * manage_copy() can be called on any isl raw pointer and the corresponding
  * object is automatically created, without the user having to choose the right
  * isl object type.
+ *
+ * For a subclass based on a type function, no factory functions
+ * are introduced because they share the C object type with
+ * the superclass.
  */
 void cpp_generator::print_class_factory_decl(ostream &os,
 	const isl_class &clazz, const std::string &prefix)
@@ -214,6 +298,9 @@ void cpp_generator::print_class_factory_decl(ostream &os,
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
 
+	if (clazz.is_type_subclass())
+		return;
+
 	os << prefix;
 	osprintf(os, "inline %s manage(__isl_take %s *ptr);\n", cppname, name);
 	os << prefix;
@@ -221,9 +308,9 @@ void cpp_generator::print_class_factory_decl(ostream &os,
 		cppname, name);
 }
 
-/* Print declarations of private constructors for class "clazz" to "os".
+/* Print declarations of protected constructors for class "clazz" to "os".
  *
- * Each class has currently one private constructor:
+ * Each class has currently one protected constructor:
  *
  * 	1) Constructor from a plain isl_* C pointer
  *
@@ -231,10 +318,10 @@ void cpp_generator::print_class_factory_decl(ostream &os,
  *
  * 	set(__isl_take isl_set *ptr);
  *
- * The raw pointer constructor is kept private. Object creation is only
+ * The raw pointer constructor is kept protected. Object creation is only
  * possible through manage() or manage_copy().
  */
-void cpp_generator::print_private_constructors_decl(ostream &os,
+void cpp_generator::print_protected_constructors_decl(ostream &os,
 	const isl_class &clazz)
 {
 	const char *name = clazz.name.c_str();
@@ -268,6 +355,35 @@ void cpp_generator::print_public_constructors_decl(ostream &os,
 		 cppname, cppname);
 }
 
+/* Print declarations for "method" in class "clazz" to "os".
+ *
+ * "kind" specifies the kind of method that should be generated.
+ *
+ * "convert" specifies which of the method arguments should
+ * be automatically converted.
+ */
+template <>
+void cpp_generator::print_method<cpp_generator::decl>(ostream &os,
+	const isl_class &clazz, FunctionDecl *method, function_kind kind,
+	const std::vector<bool> &convert)
+{
+	string name = clazz.method_name(method);
+
+	print_named_method_decl(os, clazz, method, name, kind, convert);
+}
+
+/* Print declarations for "method" in class "clazz" to "os",
+ * without any argument conversions.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ */
+template <>
+void cpp_generator::print_method<cpp_generator::decl>(ostream &os,
+	const isl_class &clazz, FunctionDecl *method, function_kind kind)
+{
+	print_method<decl>(os, clazz,method, kind, {});
+}
+
 /* Print declarations for constructors for class "class" to "os".
  *
  * For each isl function that is marked as __isl_constructor,
@@ -283,13 +399,13 @@ void cpp_generator::print_public_constructors_decl(ostream &os,
 void cpp_generator::print_constructors_decl(ostream &os,
        const isl_class &clazz)
 {
-	set<FunctionDecl *>::const_iterator in;
-	const set<FunctionDecl *> &constructors = clazz.constructors;
+	function_set::const_iterator in;
+	const function_set &constructors = clazz.constructors;
 
 	for (in = constructors.begin(); in != constructors.end(); ++in) {
 		FunctionDecl *cons = *in;
 
-		print_method_decl(os, clazz, cons, function_kind_constructor);
+		print_method<decl>(os, clazz, cons, function_kind_constructor);
 	}
 }
 
@@ -311,16 +427,23 @@ void cpp_generator::print_copy_assignment_decl(ostream &os,
 }
 
 /* Print declaration of destructor for class "clazz" to "os".
+ *
+ * No explicit destructor is needed for type based subclasses.
  */
 void cpp_generator::print_destructor_decl(ostream &os, const isl_class &clazz)
 {
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
 
+	if (clazz.is_type_subclass())
+		return;
+
 	osprintf(os, "  inline ~%s();\n", cppname);
 }
 
 /* Print declaration of pointer functions for class "clazz" to "os".
+ * Since type based subclasses share the pointer with their superclass,
+ * they can also reuse these functions from the superclass.
  *
  * To obtain a raw pointer three functions are provided:
  *
@@ -356,6 +479,9 @@ void cpp_generator::print_ptr_decl(ostream &os, const isl_class &clazz)
 {
 	const char *name = clazz.name.c_str();
 
+	if (clazz.is_type_subclass())
+		return;
+
 	osprintf(os, "  inline __isl_give %s *copy() const &;\n", name);
 	osprintf(os, "  inline __isl_give %s *copy() && = delete;\n", name);
 	osprintf(os, "  inline __isl_keep %s *get() const;\n", name);
@@ -363,44 +489,334 @@ void cpp_generator::print_ptr_decl(ostream &os, const isl_class &clazz)
 	osprintf(os, "  inline bool is_null() const;\n");
 }
 
-/* Print the declaration of the get_ctx method.
+/* Print a template declaration with given indentation
+ * for the "isa_type" method that ensures it is only enabled
+ * when called with a template argument
+ * that represents a type that is equal to that
+ * of the return type of the type function of "super".
+ * In particular, "isa_type" gets called from "isa"
+ * with as template argument the type of the "type" field
+ * of the subclass.
+ * The check ensures that this subclass is in fact a direct subclass
+ * of "super".
+ */
+void cpp_generator::print_isa_type_template(ostream &os, int indent,
+	const isl_class &super)
+{
+	osprintf(os, indent,
+		"template <typename T,\n");
+	osprintf(os, indent,
+		"        typename = typename std::enable_if<std::is_same<\n");
+	osprintf(os, indent,
+		"                const decltype(%s(NULL)),\n",
+		super.fn_type->getNameAsString().c_str());
+	osprintf(os, indent,
+		"                const T>::value>::type>\n");
+}
+
+/* Print declarations for the "as" and "isa" methods, if "clazz"
+ * is a superclass with a type function.
+ *
+ * "isa" checks whether an object is of a given subclass type.
+ * "isa_type" does the same, but gets passed the value of the type field
+ * of the subclass as a function argument and the type of this field
+ * as a template argument.
+ * "as" tries to cast an object to a given subclass type, returning
+ * an invalid object if the object is not of the given type.
+ */
+void cpp_generator::print_downcast_decl(ostream &os, const isl_class &clazz)
+{
+	if (!clazz.fn_type)
+		return;
+
+	osprintf(os, "private:\n");
+	print_isa_type_template(os, 2, clazz);
+	osprintf(os, "  inline %s isa_type(T subtype) const;\n",
+		isl_bool2cpp().c_str());
+	osprintf(os, "public:\n");
+	osprintf(os, "  template <class T> inline %s isa() const;\n",
+		isl_bool2cpp().c_str());
+	osprintf(os, "  template <class T> inline T as() const;\n");
+}
+
+/* Print the declaration of the ctx method.
+ */
+void cpp_generator::print_ctx_decl(ostream &os)
+{
+	std::string ns = isl_namespace();
+
+	osprintf(os, "  inline %sctx ctx() const;\n", ns.c_str());
+}
+
+/* Add a space to the return type "type" if needed,
+ * i.e., if it is not the type of a pointer.
  */
-void cpp_generator::print_get_ctx_decl(ostream &os)
+static string add_space_to_return_type(const string &type)
 {
-	osprintf(os, "  inline ctx get_ctx() const;\n");
+	if (type[type.size() - 1] == '*')
+		return type;
+	return type + " ";
+}
+
+/* Print the prototype of the static inline method that is used
+ * as the C callback of "clazz" set by "method" to "os".
+ */
+void cpp_generator::print_persistent_callback_prototype(ostream &os,
+	const isl_class &clazz, FunctionDecl *method, bool is_declaration)
+{
+	string callback_name, rettype, c_args;
+	ParmVarDecl *param = persistent_callback_arg(method);
+	const FunctionProtoType *callback;
+	QualType ptype;
+	string classname;
+
+	ptype = param->getType();
+	callback = extract_prototype(ptype);
+
+	rettype = callback->getReturnType().getAsString();
+	rettype = add_space_to_return_type(rettype);
+	callback_name = clazz.persistent_callback_name(method);
+	c_args = generate_callback_args(ptype, false);
+
+	if (!is_declaration)
+		classname = type2cpp(clazz) + "::";
+
+	osprintf(os, "%s%s%s(%s)",
+		 rettype.c_str(), classname.c_str(),
+		 callback_name.c_str(), c_args.c_str());
+}
+
+/* Print the prototype of the method for setting the callback function
+ * of "clazz" set by "method" to "os".
+ */
+void cpp_generator::print_persistent_callback_setter_prototype(ostream &os,
+	const isl_class &clazz, FunctionDecl *method, bool is_declaration)
+{
+	string classname, callback_name, cpptype;
+	ParmVarDecl *param = persistent_callback_arg(method);
+
+	if (!is_declaration)
+		classname = type2cpp(clazz) + "::";
+
+	cpptype = type2cpp(param->getOriginalType());
+	callback_name = clazz.persistent_callback_name(method);
+	osprintf(os, "void %sset_%s_data(const %s &%s)",
+		classname.c_str(), callback_name.c_str(), cpptype.c_str(),
+		param->getName().str().c_str());
+}
+
+/* Given a function "method" for setting a "clazz" persistent callback,
+ * print the fields that are needed for marshalling the callback to "os".
+ *
+ * In particular, print
+ * - the declaration of a data structure for storing the C++ callback function
+ * - a shared pointer to such a data structure
+ * - the declaration of a static inline method
+ *   for use as the C callback function
+ * - the declaration of a private method for setting the callback function
+ */
+void cpp_generator::print_persistent_callback_data(ostream &os,
+	const isl_class &clazz, FunctionDecl *method)
+{
+	string callback_name;
+	ParmVarDecl *param = persistent_callback_arg(method);
+
+	callback_name = clazz.persistent_callback_name(method);
+	print_callback_data_decl(os, param, callback_name);
+	osprintf(os, ";\n");
+	osprintf(os, "  std::shared_ptr<%s_data> %s_data;\n",
+		callback_name.c_str(), callback_name.c_str());
+	osprintf(os, "  static inline ");
+	print_persistent_callback_prototype(os, clazz, method, true);
+	osprintf(os, ";\n");
+	osprintf(os, "  inline ");
+	print_persistent_callback_setter_prototype(os, clazz, method, true);
+	osprintf(os, ";\n");
+}
+
+/* Print declarations needed for the persistent callbacks of "clazz".
+ *
+ * In particular, if there are any persistent callbacks, then
+ * print a private method for copying callback data from
+ * one object to another,
+ * private data for keeping track of the persistent callbacks and
+ * public methods for setting the persistent callbacks.
+ */
+void cpp_generator::print_persistent_callbacks_decl(ostream &os,
+       const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+	set<FunctionDecl *>::const_iterator in;
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
+
+	if (!clazz.has_persistent_callbacks())
+		return;
+
+	osprintf(os, "private:\n");
+	osprintf(os, "  inline %s &copy_callbacks(const %s &obj);\n",
+		cppname, cppname);
+	for (in = callbacks.begin(); in != callbacks.end(); ++in)
+		print_persistent_callback_data(os, clazz, *in);
+
+	osprintf(os, "public:\n");
+	for (in = callbacks.begin(); in != callbacks.end(); ++in)
+		print_method<decl>(os, clazz, *in, function_kind_member_method);
 }
 
 /* Print declarations for methods in class "clazz" to "os".
  */
 void cpp_generator::print_methods_decl(ostream &os, const isl_class &clazz)
 {
-	map<string, set<FunctionDecl *> >::const_iterator it;
+	map<string, function_set >::const_iterator it;
 
 	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
 		print_method_group_decl(os, clazz, it->second);
 }
 
+/* Print a declaration for a method "name" in "clazz" derived
+ * from "fd", which sets an enum, to "os".
+ *
+ * The last argument is removed because it is replaced by
+ * a break-up into several methods.
+ */
+void cpp_generator::print_set_enum_decl(ostream &os, const isl_class &clazz,
+	FunctionDecl *fd, const string &name)
+{
+	int n = fd->getNumParams();
+
+	print_method_header(os, clazz, fd, name, n - 1, true,
+				function_kind_member_method);
+}
+
+/* Print declarations for the methods in "clazz" derived from "fd",
+ * which sets an enum, to "os".
+ *
+ * A method is generated for each value in the enum, setting
+ * the enum to that value.
+ */
+void cpp_generator::print_set_enums_decl(ostream &os, const isl_class &clazz,
+	FunctionDecl *fd)
+{
+	vector<set_enum>::const_iterator it;
+	const vector<set_enum> &set_enums = clazz.set_enums.at(fd);
+
+	for (it = set_enums.begin(); it != set_enums.end(); ++it)
+		print_set_enum_decl(os, clazz, fd, it->method_name);
+}
+
+/* Print declarations for methods in "clazz" derived from functions
+ * that set an enum, to "os".
+ */
+void cpp_generator::print_set_enums_decl(ostream &os, const isl_class &clazz)
+{
+	map<FunctionDecl *, vector<set_enum> >::const_iterator it;
+
+	for (it = clazz.set_enums.begin(); it != clazz.set_enums.end(); ++it)
+		print_set_enums_decl(os, clazz, it->first);
+}
+
+/* Print a declaration for the "get" method "fd" in class "clazz",
+ * using a name that includes the "get_" prefix, to "os".
+ */
+template<>
+void cpp_generator::print_get_method<cpp_generator::decl>(ostream &os,
+	const isl_class &clazz, FunctionDecl *fd)
+{
+	function_kind kind = function_kind_member_method;
+	string base = clazz.base_method_name(fd);
+
+	print_named_method_decl(os, clazz, fd, base, kind);
+}
+
+/* Update "convert" to reflect the next combination of automatic conversions
+ * for the arguments of "fd",
+ * returning false if there are no more combinations.
+ *
+ * In particular, find the last argument for which an automatic
+ * conversion function is available mapping to the type of this argument and
+ * that is not already marked for conversion.
+ * Mark this argument, if any, for conversion and clear the markings
+ * of all subsequent arguments.
+ * Repeated calls to this method therefore run through
+ * all possible combinations.
+ *
+ * Note that the first function argument is never considered
+ * for automatic conversion since this is the argument
+ * from which the isl_ctx used in the conversion is extracted.
+ */
+bool cpp_generator::next_variant(FunctionDecl *fd, std::vector<bool> &convert)
+{
+	size_t n = convert.size();
+
+	for (int i = n - 1; i >= 1; --i) {
+		ParmVarDecl *param = fd->getParamDecl(i);
+		const Type *type = param->getOriginalType().getTypePtr();
+
+		if (conversions.count(type) == 0)
+			continue;
+		if (convert[i])
+			continue;
+		convert[i] = true;
+		for (size_t j = i + 1; j < n; ++j)
+			convert[j] = false;
+		return true;
+	}
+
+	return false;
+}
+
+/* Print a declaration or definition for method "fd" in class "clazz"
+ * to "os".
+ *
+ * For methods that are identified as "get" methods, also
+ * print a declaration or definition for the method
+ * using a name that includes the "get_" prefix.
+ *
+ * If the generated method is an object method, then check
+ * whether any of its arguments can be automatically converted
+ * from something else, and, if so, generate a method
+ * for each combination of converted arguments.
+ */
+template <enum cpp_generator::method_part part>
+void cpp_generator::print_method_variants(ostream &os, const isl_class &clazz,
+	FunctionDecl *fd)
+{
+	function_kind kind = get_method_kind(clazz, fd);
+	std::vector<bool> convert(fd->getNumParams());
+
+	print_method<part>(os, clazz, fd, kind);
+	if (clazz.is_get_method(fd))
+		print_get_method<part>(os, clazz, fd);
+	if (kind == function_kind_member_method)
+		while (next_variant(fd, convert))
+			print_method<part>(os, clazz, fd, kind, convert);
+}
+
 /* Print declarations for methods "methods" in class "clazz" to "os".
  */
 void cpp_generator::print_method_group_decl(ostream &os, const isl_class &clazz,
-	const set<FunctionDecl *> &methods)
+	const function_set &methods)
 {
-	set<FunctionDecl *>::const_iterator it;
+	function_set::const_iterator it;
 
-	for (it = methods.begin(); it != methods.end(); ++it) {
-		function_kind kind = get_method_kind(clazz, *it);
-		print_method_decl(os, clazz, *it, kind);
-	}
+	for (it = methods.begin(); it != methods.end(); ++it)
+		print_method_variants<decl>(os, clazz, *it);
 }
 
-/* Print declarations for "method" in class "clazz" to "os".
+/* Print a declaration for a method called "name" in class "clazz"
+ * derived from "fd" to "os".
  *
  * "kind" specifies the kind of method that should be generated.
+ *
+ * "convert" specifies which of the method arguments should
+ * be automatically converted.
  */
-void cpp_generator::print_method_decl(ostream &os, const isl_class &clazz,
-	FunctionDecl *method, function_kind kind)
+void cpp_generator::print_named_method_decl(ostream &os, const isl_class &clazz,
+	FunctionDecl *fd, const string &name, function_kind kind,
+	const std::vector<bool> &convert)
 {
-	print_method_header(os, clazz, method, true, kind);
+	print_named_method_header(os, clazz, fd, name, true, kind, convert);
 }
 
 /* Print implementations for class "clazz" to "os".
@@ -410,42 +826,104 @@ void cpp_generator::print_class_impl(ostream &os, const isl_class &clazz)
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
 
-	osprintf(os, "// implementations for isl::%s\n", cppname);
+	osprintf(os, "// implementations for isl::%s", cppname);
 
 	print_class_factory_impl(os, clazz);
-	osprintf(os, "\n");
 	print_public_constructors_impl(os, clazz);
-	osprintf(os, "\n");
-	print_private_constructors_impl(os, clazz);
-	osprintf(os, "\n");
+	print_protected_constructors_impl(os, clazz);
 	print_constructors_impl(os, clazz);
-	osprintf(os, "\n");
 	print_copy_assignment_impl(os, clazz);
-	osprintf(os, "\n");
 	print_destructor_impl(os, clazz);
-	osprintf(os, "\n");
 	print_ptr_impl(os, clazz);
-	osprintf(os, "\n");
-	print_get_ctx_impl(os, clazz);
-	osprintf(os, "\n");
+	print_downcast_impl(os, clazz);
+	print_ctx_impl(os, clazz);
+	print_persistent_callbacks_impl(os, clazz);
 	print_methods_impl(os, clazz);
+	print_set_enums_impl(os, clazz);
+	print_stream_insertion(os, clazz);
 }
 
 /* Print code for throwing an exception corresponding to the last error
- * that occurred on "ctx".
- * This assumes that a valid isl::ctx is available in the "ctx" variable,
+ * that occurred on "saved_ctx".
+ * This assumes that a valid isl::ctx is available in the "saved_ctx" variable,
  * e.g., through a prior call to print_save_ctx.
  */
 static void print_throw_last_error(ostream &os)
 {
-	osprintf(os, "    exception::throw_last_error(ctx);\n");
+	osprintf(os, "    exception::throw_last_error(saved_ctx);\n");
+}
+
+/* Print code with the given indentation
+ * for throwing an exception_invalid with the given message.
+ */
+static void print_throw_invalid(ostream &os, int indent, const char *msg)
+{
+	osprintf(os, indent,
+		"exception::throw_invalid(\"%s\", __FILE__, __LINE__);\n", msg);
 }
 
 /* Print code for throwing an exception on NULL input.
  */
 static void print_throw_NULL_input(ostream &os)
 {
-	osprintf(os, "    exception::throw_NULL_input(__FILE__, __LINE__);\n");
+	print_throw_invalid(os, 4, "NULL input");
+}
+
+/* Print code with the given indentation
+ * for acting on an invalid error with message "msg".
+ * In particular, throw an exception_invalid.
+ * In the checked C++ bindings, isl_die is called instead with the code
+ * in "checked_code".
+ */
+void cpp_generator::print_invalid(ostream &os, int indent, const char *msg,
+	const char *checked_code)
+{
+	if (checked)
+		osprintf(os, indent,
+			"isl_die(ctx().get(), isl_error_invalid, "
+			"\"%s\", %s);\n", msg, checked_code);
+	else
+		print_throw_invalid(os, indent, msg);
+}
+
+/* Print an operator for inserting objects of "class"
+ * into an output stream.
+ *
+ * Unless checked C++ bindings are being generated,
+ * the operator requires its argument to be non-NULL.
+ * An exception is thrown if anything went wrong during the printing.
+ * During this printing, isl is made not to print any error message
+ * because the error message is included in the exception.
+ *
+ * If checked C++ bindings are being generated and anything went wrong,
+ * then record this failure in the output stream.
+ */
+void cpp_generator::print_stream_insertion(ostream &os, const isl_class &clazz)
+{
+	const char *name = clazz.name.c_str();
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	if (!clazz.fn_to_str)
+		return;
+
+	osprintf(os, "\n");
+	osprintf(os, "inline std::ostream &operator<<(std::ostream &os, ");
+	osprintf(os, "const %s &obj)\n", cppname);
+	osprintf(os, "{\n");
+	print_check_ptr_start(os, clazz, "obj.get()");
+	osprintf(os, "  char *str = %s_to_str(obj.get());\n", name);
+	print_check_ptr_end(os, "str");
+	if (checked) {
+		osprintf(os, "  if (!str) {\n");
+		osprintf(os, "    os.setstate(std::ios_base::badbit);\n");
+		osprintf(os, "    return os;\n");
+		osprintf(os, "  }\n");
+	}
+	osprintf(os, "  os << str;\n");
+	osprintf(os, "  free(str);\n");
+	osprintf(os, "  return os;\n");
+	osprintf(os, "}\n");
 }
 
 /* Print code that checks that "ptr" is not NULL at input.
@@ -473,7 +951,8 @@ void cpp_generator::print_check_ptr_start(ostream &os, const isl_class &clazz,
 		return;
 
 	print_check_ptr(os, ptr);
-	osprintf(os, "  auto ctx = %s_get_ctx(%s);\n", clazz.name.c_str(), ptr);
+	osprintf(os, "  auto saved_ctx = %s_get_ctx(%s);\n",
+		clazz.name.c_str(), ptr);
 	print_on_error_continue(os);
 }
 
@@ -505,6 +984,10 @@ void cpp_generator::print_check_ptr_end(ostream &os, const char *ptr)
  * in manage_copy.
  * During the copying, isl is made not to print any error message
  * because the error message is included in the exception.
+ *
+ * For a subclass based on a type function, no factory functions
+ * are introduced because they share the C object type with
+ * the superclass.
  */
 void cpp_generator::print_class_factory_impl(ostream &os,
 	const isl_class &clazz)
@@ -513,6 +996,10 @@ void cpp_generator::print_class_factory_impl(ostream &os,
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
 
+	if (clazz.is_type_subclass())
+		return;
+
+	osprintf(os, "\n");
 	osprintf(os, "%s manage(__isl_take %s *ptr) {\n", cppname, name);
 	print_check_ptr(os, "ptr");
 	osprintf(os, "  return %s(ptr);\n", cppname);
@@ -527,23 +1014,40 @@ void cpp_generator::print_class_factory_impl(ostream &os,
 	osprintf(os, "}\n");
 }
 
-/* Print implementations of private constructors for class "clazz" to "os".
+/* Print implementations of protected constructors for class "clazz" to "os".
+ *
+ * The pointer to the isl object is either initialized directly or
+ * through the (immediate) superclass.
  */
-void cpp_generator::print_private_constructors_impl(ostream &os,
+void cpp_generator::print_protected_constructors_impl(ostream &os,
 	const isl_class &clazz)
 {
 	const char *name = clazz.name.c_str();
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
+	bool subclass = clazz.is_type_subclass();
 
-	osprintf(os, "%s::%s(__isl_take %s *ptr)\n    : ptr(ptr) {}\n",
-		 cppname, cppname, name);
+	osprintf(os, "\n");
+	osprintf(os, "%s::%s(__isl_take %s *ptr)\n", cppname, cppname, name);
+	if (subclass)
+		osprintf(os, "    : %s(ptr) {}\n",
+			type2cpp(clazz.superclass_name).c_str());
+	else
+		osprintf(os, "    : ptr(ptr) {}\n");
 }
 
 /* Print implementations of public constructors for class "clazz" to "os".
+ *
+ * The pointer to the isl object is either initialized directly or
+ * through the (immediate) superclass.
+ *
+ * If the class has any persistent callbacks, then copy them
+ * from the original object in the copy constructor.
+ * If the class is a subclass, then the persistent callbacks
+ * are assumed to be copied by the copy constructor of the superclass.
  *
  * Throw an exception from the copy constructor if anything went wrong
- * during the copying or if the input is NULL.
+ * during the copying or if the input is NULL, if any copying is performed.
  * During the copying, isl is made not to print any error message
  * because the error message is included in the exception.
  * No exceptions are thrown if checked C++ bindings
@@ -553,15 +1057,166 @@ void cpp_generator::print_public_constructors_impl(ostream &os,
 	const isl_class &clazz)
 {
 	std::string cppstring = type2cpp(clazz);
+	std::string super;
 	const char *cppname = cppstring.c_str();
+	bool subclass = clazz.is_type_subclass();
 
-	osprintf(os, "%s::%s()\n    : ptr(nullptr) {}\n\n", cppname, cppname);
-	osprintf(os, "%s::%s(const %s &obj)\n    : ptr(nullptr)\n",
-		 cppname, cppname, cppname);
+	osprintf(os, "\n");
+	if (subclass)
+		super = type2cpp(clazz.superclass_name);
+	osprintf(os, "%s::%s()\n", cppname, cppname);
+	if (subclass)
+		osprintf(os, "    : %s() {}\n\n", super.c_str());
+	else
+		osprintf(os, "    : ptr(nullptr) {}\n\n");
+	osprintf(os, "%s::%s(const %s &obj)\n", cppname, cppname, cppname);
+	if (subclass)
+		osprintf(os, "    : %s(obj)\n", super.c_str());
+	else
+		osprintf(os, "    : ptr(nullptr)\n");
 	osprintf(os, "{\n");
-	print_check_ptr_start(os, clazz, "obj.ptr");
-	osprintf(os, "  ptr = obj.copy();\n");
-	print_check_ptr_end(os, "ptr");
+	if (!subclass) {
+		print_check_ptr_start(os, clazz, "obj.ptr");
+		osprintf(os, "  ptr = obj.copy();\n");
+		if (clazz.has_persistent_callbacks())
+			osprintf(os, "  copy_callbacks(obj);\n");
+		print_check_ptr_end(os, "ptr");
+	}
+	osprintf(os, "}\n");
+}
+
+/* Print definition for "method" in class "clazz" to "os",
+ * without any automatic type conversions.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ *
+ * This method distinguishes three kinds of methods: member methods, static
+ * methods, and constructors.
+ *
+ * Member methods call "method" by passing to the underlying isl function the
+ * isl object belonging to "this" as first argument and the remaining arguments
+ * as subsequent arguments.
+ *
+ * Static methods call "method" by passing all arguments to the underlying isl
+ * function, as no this-pointer is available. The result is a newly managed
+ * isl C++ object.
+ *
+ * Constructors create a new object from a given set of input parameters. They
+ * do not return a value, but instead update the pointer stored inside the
+ * newly created object.
+ *
+ * If the method has a callback argument, we reduce the number of parameters
+ * that are exposed by one to hide the user pointer from the interface. On
+ * the C++ side no user pointer is needed, as arguments can be forwarded
+ * as part of the std::function argument which specifies the callback function.
+ *
+ * Unless checked C++ bindings are being generated,
+ * the inputs of the method are first checked for being valid isl objects and
+ * a copy of the associated isl::ctx is saved (if needed).
+ * If any failure occurs, either during the check for the inputs or
+ * during the isl function call, an exception is thrown.
+ * During the function call, isl is made not to print any error message
+ * because the error message is included in the exception.
+ */
+template<>
+void cpp_generator::print_method<cpp_generator::impl>(ostream &os,
+	const isl_class &clazz, FunctionDecl *method, function_kind kind)
+{
+	string methodname = method->getName();
+	int num_params = method->getNumParams();
+
+	osprintf(os, "\n");
+	print_method_header(os, clazz, method, false, kind);
+	osprintf(os, "{\n");
+	print_argument_validity_check(os, method, kind);
+	print_save_ctx(os, method, kind);
+	print_on_error_continue(os);
+
+	for (int i = 0; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		if (is_callback(param->getType())) {
+			num_params -= 1;
+			print_callback_local(os, param);
+		}
+	}
+
+	osprintf(os, "  auto res = %s(", methodname.c_str());
+
+	for (int i = 0; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		bool load_from_this_ptr = false;
+
+		if (i == 0 && kind == function_kind_member_method)
+			load_from_this_ptr = true;
+
+		print_method_param_use(os, param, load_from_this_ptr);
+
+		if (i != num_params - 1)
+			osprintf(os, ", ");
+	}
+	osprintf(os, ");\n");
+
+	print_exceptional_execution_check(os, clazz, method, kind);
+	if (kind == function_kind_constructor) {
+		osprintf(os, "  ptr = res;\n");
+	} else {
+		print_method_return(os, clazz, method);
+	}
+
+	osprintf(os, "}\n");
+}
+
+/* Print a definition for "method" in class "clazz" to "os",
+ * where at least one of the argument types needs to be converted,
+ * as specified by "convert".
+ *
+ * "kind" specifies the kind of method that should be generated and
+ * is assumed to be set to function_kind_member_method.
+ *
+ * The generated method performs the required conversion(s) and
+ * calls the method generated without conversions.
+ *
+ * Each conversion is performed by calling the conversion function
+ * with as arguments the isl_ctx of the object and the argument
+ * to the generated method.
+ * In order to be able to use this isl_ctx, the current object needs
+ * to valid.  The validity of other arguments is checked
+ * by the called method.
+ */
+template<>
+void cpp_generator::print_method<cpp_generator::impl>(ostream &os,
+	const isl_class &clazz, FunctionDecl *method, function_kind kind,
+	const std::vector<bool> &convert)
+{
+	string name = clazz.method_name(method);
+	int num_params = method->getNumParams();
+
+	if (kind != function_kind_member_method)
+		die("Automatic conversion currently only supported "
+		    "for object methods");
+
+	osprintf(os, "\n");
+	print_named_method_header(os, clazz, method, name, false,
+				  kind, convert);
+	osprintf(os, "{\n");
+	print_check_ptr(os, "ptr");
+	osprintf(os, "  return this->%s(", name.c_str());
+	for (int i = 1; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		std::string name = param->getName().str();
+
+		if (i != 1)
+			osprintf(os, ", ");
+		if (convert[i]) {
+			QualType type = param->getOriginalType();
+			string cpptype = type2cpp(type);
+			osprintf(os, "%s(ctx(), %s)",
+				cpptype.c_str(), name.c_str());
+		} else {
+			osprintf(os, "%s", name.c_str());
+		}
+	}
+	osprintf(os, ");\n");
 	osprintf(os, "}\n");
 }
 
@@ -570,17 +1225,20 @@ void cpp_generator::print_public_constructors_impl(ostream &os,
 void cpp_generator::print_constructors_impl(ostream &os,
        const isl_class &clazz)
 {
-	set<FunctionDecl *>::const_iterator in;
-	const set<FunctionDecl *> constructors = clazz.constructors;
+	function_set::const_iterator in;
+	const function_set constructors = clazz.constructors;
 
 	for (in = constructors.begin(); in != constructors.end(); ++in) {
 		FunctionDecl *cons = *in;
 
-		print_method_impl(os, clazz, cons, function_kind_constructor);
+		print_method<impl>(os, clazz, cons, function_kind_constructor);
 	}
 }
 
 /* Print implementation of copy assignment operator for class "clazz" to "os".
+ *
+ * If the class has any persistent callbacks, then copy them
+ * from the original object.
  */
 void cpp_generator::print_copy_assignment_impl(ostream &os,
 	const isl_class &clazz)
@@ -589,14 +1247,19 @@ void cpp_generator::print_copy_assignment_impl(ostream &os,
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
 
+	osprintf(os, "\n");
 	osprintf(os, "%s &%s::operator=(%s obj) {\n", cppname,
 		 cppname, cppname);
 	osprintf(os, "  std::swap(this->ptr, obj.ptr);\n", name);
+	if (clazz.has_persistent_callbacks())
+		osprintf(os, "  copy_callbacks(obj);\n");
 	osprintf(os, "  return *this;\n");
 	osprintf(os, "}\n");
 }
 
 /* Print implementation of destructor for class "clazz" to "os".
+ *
+ * No explicit destructor is needed for type based subclasses.
  */
 void cpp_generator::print_destructor_impl(ostream &os,
 	const isl_class &clazz)
@@ -605,20 +1268,50 @@ void cpp_generator::print_destructor_impl(ostream &os,
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
 
+	if (clazz.is_type_subclass())
+		return;
+
+	osprintf(os, "\n");
 	osprintf(os, "%s::~%s() {\n", cppname, cppname);
 	osprintf(os, "  if (ptr)\n");
 	osprintf(os, "    %s_free(ptr);\n", name);
 	osprintf(os, "}\n");
 }
 
+/* Print a check that the persistent callback corresponding to "fd"
+ * is not set, throwing an exception (or printing an error message
+ * and returning nullptr) if it is set.
+ */
+void cpp_generator::print_check_no_persistent_callback(ostream &os,
+	const isl_class &clazz, FunctionDecl *fd)
+{
+	string callback_name = clazz.persistent_callback_name(fd);
+
+	osprintf(os, "  if (%s_data)\n", callback_name.c_str());
+	print_invalid(os, 4, "cannot release object with persistent callbacks",
+			    "return nullptr");
+}
+
 /* Print implementation of ptr() functions for class "clazz" to "os".
+ * Since type based subclasses share the pointer with their superclass,
+ * they can also reuse these functions from the superclass.
+ *
+ * If an object has persistent callbacks set, then the underlying
+ * C object pointer cannot be released because it references data
+ * in the C++ object.
  */
 void cpp_generator::print_ptr_impl(ostream &os, const isl_class &clazz)
 {
 	const char *name = clazz.name.c_str();
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
+	set<FunctionDecl *>::const_iterator in;
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
 
+	if (clazz.is_type_subclass())
+		return;
+
+	osprintf(os, "\n");
 	osprintf(os, "__isl_give %s *%s::copy() const & {\n", name, cppname);
 	osprintf(os, "  return %s_copy(ptr);\n", name);
 	osprintf(os, "}\n\n");
@@ -626,6 +1319,8 @@ void cpp_generator::print_ptr_impl(ostream &os, const isl_class &clazz)
 	osprintf(os, "  return ptr;\n");
 	osprintf(os, "}\n\n");
 	osprintf(os, "__isl_give %s *%s::release() {\n", name, cppname);
+	for (in = callbacks.begin(); in != callbacks.end(); ++in)
+		print_check_no_persistent_callback(os, clazz, *in);
 	osprintf(os, "  %s *tmp = ptr;\n", name);
 	osprintf(os, "  ptr = nullptr;\n");
 	osprintf(os, "  return tmp;\n");
@@ -635,54 +1330,234 @@ void cpp_generator::print_ptr_impl(ostream &os, const isl_class &clazz)
 	osprintf(os, "}\n");
 }
 
-/* Print the implementation of the get_ctx method.
+/* Print implementations for the "as" and "isa" methods, if "clazz"
+ * is a superclass with a type function.
+ *
+ * "isa" checks whether an object is of a given subclass type.
+ * "isa_type" does the same, but gets passed the value of the type field
+ * of the subclass as a function argument and the type of this field
+ * as a template argument.
+ * "as" casts an object to a given subclass type, erroring out
+ * if the object is not of the given type.
+ *
+ * If the input is an invalid object, then these methods raise
+ * an exception.
+ * If checked bindings are being generated,
+ * then an invalid boolean or object is returned instead.
+ */
+void cpp_generator::print_downcast_impl(ostream &os, const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+
+	if (!clazz.fn_type)
+		return;
+
+	osprintf(os, "\n");
+	osprintf(os, "template <typename T, typename>\n");
+	osprintf(os, "%s %s::isa_type(T subtype) const\n",
+		isl_bool2cpp().c_str(), cppname);
+	osprintf(os, "{\n");
+	osprintf(os, "  if (is_null())\n");
+	if (checked)
+		osprintf(os, "    return boolean();\n");
+	else
+		print_throw_NULL_input(os);
+	osprintf(os, "  return %s(get()) == subtype;\n",
+		clazz.fn_type->getNameAsString().c_str());
+	osprintf(os, "}\n");
+
+	osprintf(os, "template <class T>\n");
+	osprintf(os, "%s %s::isa() const\n", isl_bool2cpp().c_str(), cppname);
+	osprintf(os, "{\n");
+	osprintf(os, "  return isa_type<decltype(T::type)>(T::type);\n");
+	osprintf(os, "}\n");
+
+	osprintf(os, "template <class T>\n");
+	osprintf(os, "T %s::as() const\n", cppname);
+	osprintf(os, "{\n");
+	if (checked)
+		osprintf(os, " if (isa<T>().is_false())\n");
+	else
+		osprintf(os, " if (!isa<T>())\n");
+	print_invalid(os, 4, "not an object of the requested subtype",
+		    "return T()");
+	osprintf(os, "  return T(copy());\n");
+	osprintf(os, "}\n");
+}
+
+/* Print the implementation of the ctx method.
  */
-void cpp_generator::print_get_ctx_impl(ostream &os, const isl_class &clazz)
+void cpp_generator::print_ctx_impl(ostream &os, const isl_class &clazz)
 {
 	const char *name = clazz.name.c_str();
 	std::string cppstring = type2cpp(clazz);
 	const char *cppname = cppstring.c_str();
+	std::string ns = isl_namespace();
+
+	osprintf(os, "\n");
+	osprintf(os, "%sctx %s::ctx() const {\n", ns.c_str(), cppname);
+	osprintf(os, "  return %sctx(%s_get_ctx(ptr));\n", ns.c_str(), name);
+	osprintf(os, "}\n");
+}
+
+/* Print the implementations of the methods needed for the persistent callbacks
+ * of "clazz".
+ */
+void cpp_generator::print_persistent_callbacks_impl(ostream &os,
+       const isl_class &clazz)
+{
+	std::string cppstring = type2cpp(clazz);
+	const char *cppname = cppstring.c_str();
+	string classname = type2cpp(clazz);
+	set<FunctionDecl *>::const_iterator in;
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
+
+	if (!clazz.has_persistent_callbacks())
+		return;
+
+	osprintf(os, "\n");
+	osprintf(os, "%s &%s::copy_callbacks(const %s &obj)\n",
+		cppname, classname.c_str(), cppname);
+	osprintf(os, "{\n");
+	for (in = callbacks.begin(); in != callbacks.end(); ++in) {
+		string callback_name = clazz.persistent_callback_name(*in);
 
-	osprintf(os, "ctx %s::get_ctx() const {\n", cppname);
-	osprintf(os, "  return ctx(%s_get_ctx(ptr));\n", name);
+		osprintf(os, "  %s_data = obj.%s_data;\n",
+			callback_name.c_str(), callback_name.c_str());
+	}
+	osprintf(os, "  return *this;\n");
 	osprintf(os, "}\n");
+
+	for (in = callbacks.begin(); in != callbacks.end(); ++in) {
+		function_kind kind = function_kind_member_method;
+
+		print_set_persistent_callback(os, clazz, *in, kind);
+	}
 }
 
 /* Print definitions for methods of class "clazz" to "os".
  */
 void cpp_generator::print_methods_impl(ostream &os, const isl_class &clazz)
 {
-	map<string, set<FunctionDecl *> >::const_iterator it;
-	bool first = true;
+	map<string, function_set>::const_iterator it;
 
-	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it) {
-		if (first)
-			first = false;
-		else
-			osprintf(os, "\n");
+	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
 		print_method_group_impl(os, clazz, it->second);
+}
+
+/* Print the definition for a method "method_name" in "clazz" derived
+ * from "fd", which sets an enum, to "os".
+ * In particular, the method "method_name" sets the enum to "enum_name".
+ *
+ * The last argument of the C function does not appear in the method call,
+ * but is fixed to "enum_name" instead.
+ * Other than that, the method printed here is similar to one
+ * printed by cpp_generator::print_method_impl, except that
+ * some of the special cases do not occur.
+ */
+void cpp_generator::print_set_enum_impl(ostream &os, const isl_class &clazz,
+	FunctionDecl *fd, const string &enum_name, const string &method_name)
+{
+	string c_name = fd->getName();
+	int n = fd->getNumParams();
+	function_kind kind = function_kind_member_method;
+
+	osprintf(os, "\n");
+	print_method_header(os, clazz, fd, method_name, n - 1, false, kind);
+	osprintf(os, "{\n");
+
+	print_argument_validity_check(os, fd, kind);
+	print_save_ctx(os, fd, kind);
+	print_on_error_continue(os);
+
+	osprintf(os, "  auto res = %s(", c_name.c_str());
+
+	for (int i = 0; i < n - 1; ++i) {
+		ParmVarDecl *param = fd->getParamDecl(i);
+
+		if (i > 0)
+			osprintf(os, ", ");
+		print_method_param_use(os, param, i == 0);
+	}
+	osprintf(os, ", %s", enum_name.c_str());
+	osprintf(os, ");\n");
+
+	print_exceptional_execution_check(os, clazz, fd, kind);
+	print_method_return(os, clazz, fd);
+
+	osprintf(os, "}\n");
+}
+
+/* Print definitions for the methods in "clazz" derived from "fd",
+ * which sets an enum, to "os".
+ *
+ * A method is generated for each value in the enum, setting
+ * the enum to that value.
+ */
+void cpp_generator::print_set_enums_impl(ostream &os, const isl_class &clazz,
+	FunctionDecl *fd)
+{
+	vector<set_enum>::const_iterator it;
+	const vector<set_enum> &set_enums = clazz.set_enums.at(fd);
+
+	for (it = set_enums.begin(); it != set_enums.end(); ++it) {
+		osprintf(os, "\n");
+		print_set_enum_impl(os, clazz, fd, it->name, it->method_name);
 	}
 }
 
+/* Print definitions for methods in "clazz" derived from functions
+ * that set an enum, to "os".
+ */
+void cpp_generator::print_set_enums_impl(ostream &os, const isl_class &clazz)
+{
+	map<FunctionDecl *, vector<set_enum> >::const_iterator it;
+
+	for (it = clazz.set_enums.begin(); it != clazz.set_enums.end(); ++it)
+		print_set_enums_impl(os, clazz, it->first);
+}
+
+/* Print a definition for the "get" method "fd" in class "clazz",
+ * using a name that includes the "get_" prefix, to "os".
+ *
+ * This definition simply calls the variant without the "get_" prefix and
+ * returns its result.
+ * Note that static methods are not considered to be "get" methods.
+ */
+template<>
+void cpp_generator::print_get_method<cpp_generator::impl>(ostream &os,
+	const isl_class &clazz, FunctionDecl *fd)
+{
+	string get_name = clazz.base_method_name(fd);
+	string name = clazz.method_name(fd);
+	function_kind kind = function_kind_member_method;
+	int num_params = fd->getNumParams();
+
+	osprintf(os, "\n");
+	print_named_method_header(os, clazz, fd, get_name, false, kind);
+	osprintf(os, "{\n");
+	osprintf(os, "  return %s(", name.c_str());
+	for (int i = 1; i < num_params; ++i) {
+		ParmVarDecl *param = fd->getParamDecl(i);
+
+		if (i != 1)
+			osprintf(os, ", ");
+		osprintf(os, "%s", param->getName().str().c_str());
+	}
+	osprintf(os, ");\n");
+	osprintf(os, "}\n");
+}
+
 /* Print definitions for methods "methods" in class "clazz" to "os".
- *
- * "kind" specifies the kind of method that should be generated.
  */
 void cpp_generator::print_method_group_impl(ostream &os, const isl_class &clazz,
-	const set<FunctionDecl *> &methods)
+	const function_set &methods)
 {
-	set<FunctionDecl *>::const_iterator it;
-	bool first = true;
+	function_set::const_iterator it;
 
-	for (it = methods.begin(); it != methods.end(); ++it) {
-		function_kind kind;
-		if (first)
-			first = false;
-		else
-			osprintf(os, "\n");
-		kind = get_method_kind(clazz, *it);
-		print_method_impl(os, clazz, *it, kind);
-	}
+	for (it = methods.begin(); it != methods.end(); ++it)
+		print_method_variants<impl>(os, clazz, *it);
 }
 
 /* Print the use of "param" to "os".
@@ -726,7 +1601,7 @@ void cpp_generator::print_method_param_use(ostream &os, ParmVarDecl *param,
 		return;
 	}
 
-	if (!load_from_this_ptr && !is_callback(type))
+	if (!load_from_this_ptr)
 		osprintf(os, "%s.", name_str);
 
 	if (keeps(param)) {
@@ -786,15 +1661,15 @@ void cpp_generator::print_argument_validity_check(ostream &os,
 }
 
 /* Print code for saving a copy of the isl::ctx available at the start
- * of the method "method" in a "ctx" variable, for use in exception handling.
+ * of the method "method" in a "saved_ctx" variable,
+ * for use in exception handling.
  * "kind" specifies what kind of method "method" is.
  *
  * If checked bindings are being generated,
- * then the "ctx" variable is not needed.
+ * then the "saved_ctx" variable is not needed.
  * If "method" is a member function, then obtain the isl_ctx from
  * the "this" object.
- * If the first argument of the method is an isl::ctx, then use that one,
- * assuming it is not already called "ctx".
+ * If the first argument of the method is an isl::ctx, then use that one.
  * Otherwise, save a copy of the isl::ctx associated to the first argument
  * of isl object type.
  */
@@ -808,15 +1683,14 @@ void cpp_generator::print_save_ctx(ostream &os, FunctionDecl *method,
 	if (checked)
 		return;
 	if (kind == function_kind_member_method) {
-		osprintf(os, "  auto ctx = get_ctx();\n");
+		osprintf(os, "  auto saved_ctx = ctx();\n");
 		return;
 	}
 	if (is_isl_ctx(type)) {
 		const char *name;
 
 		name = param->getName().str().c_str();
-		if (strcmp(name, "ctx") != 0)
-			osprintf(os, "  auto ctx = %s;\n", name);
+		osprintf(os, "  auto saved_ctx = %s;\n", name);
 		return;
 	}
 	n = method->getNumParams();
@@ -826,7 +1700,7 @@ void cpp_generator::print_save_ctx(ostream &os, FunctionDecl *method,
 
 		if (!is_isl_type(type))
 			continue;
-		osprintf(os, "  auto ctx = %s.get_ctx();\n",
+		osprintf(os, "  auto saved_ctx = %s.ctx();\n",
 			param->getName().str().c_str());
 		return;
 	}
@@ -840,19 +1714,53 @@ void cpp_generator::print_save_ctx(ostream &os, FunctionDecl *method,
  *
  * If checked bindings are being generated,
  * then leave it to the user to decide what isl should do on error.
- * Otherwise, assume that a valid isl::ctx is available in the "ctx" variable,
+ * Otherwise, assume that a valid isl::ctx is available
+ * in the "saved_ctx" variable,
  * e.g., through a prior call to print_save_ctx.
  */
 void cpp_generator::print_on_error_continue(ostream &os)
 {
 	if (checked)
 		return;
-	osprintf(os, "  options_scoped_set_on_error saved_on_error(ctx, "
+	osprintf(os, "  options_scoped_set_on_error saved_on_error(saved_ctx, "
 		     "exception::on_error);\n");
 }
 
+/* Print code to "os" that checks whether any of the persistent callbacks
+ * of "clazz" is set and if it failed with an exception.  If so, the "eptr"
+ * in the corresponding data structure contains the exception
+ * that was caught and that needs to be rethrown.
+ * This field is cleared because the callback and its data may get reused.
+ *
+ * The check only needs to be generated for member methods since
+ * an object is needed for any of the persistent callbacks to be set.
+ */
+static void print_persistent_callback_exceptional_execution_check(ostream &os,
+	const isl_class &clazz, cpp_generator::function_kind kind)
+{
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
+	set<FunctionDecl *>::const_iterator in;
+
+	if (kind != cpp_generator::function_kind_member_method)
+		return;
+
+	for (in = callbacks.begin(); in != callbacks.end(); ++in) {
+		string callback_name = clazz.persistent_callback_name(*in);
+
+		osprintf(os, "  if (%s_data && %s_data->eptr) {\n",
+			callback_name.c_str(), callback_name.c_str());
+		osprintf(os, "    std::exception_ptr eptr = %s_data->eptr;\n",
+			callback_name.c_str());
+		osprintf(os, "    %s_data->eptr = nullptr;\n",
+			callback_name.c_str());
+		osprintf(os, "    std::rethrow_exception(eptr);\n");
+		osprintf(os, "  }\n");
+	}
+}
+
 /* Print code that checks whether the execution of the core of "method"
- * was successful.
+ * of class "clazz" was successful.
+ * "kind" specifies what kind of method "method" is.
  *
  * If checked bindings are being generated,
  * then no checks are performed.
@@ -862,14 +1770,14 @@ void cpp_generator::print_on_error_continue(ostream &os)
  * contains the exception that was caught and that needs to be rethrown.
  * Then check if the function call failed in any other way and throw
  * the appropriate exception.
- * In particular, if the return type is isl_stat or isl_bool,
+ * In particular, if the return type is isl_stat, isl_bool or isl_size,
  * then a negative value indicates a failure.  If the return type
  * is an isl type, then a NULL value indicates a failure.
  * Assume print_save_ctx has made sure that a valid isl::ctx
  * is available in the "ctx" variable.
  */
 void cpp_generator::print_exceptional_execution_check(ostream &os,
-	FunctionDecl *method)
+	const isl_class &clazz, FunctionDecl *method, function_kind kind)
 {
 	int n;
 	bool check_null, check_neg;
@@ -878,6 +1786,8 @@ void cpp_generator::print_exceptional_execution_check(ostream &os,
 	if (checked)
 		return;
 
+	print_persistent_callback_exceptional_execution_check(os, clazz, kind);
+
 	n = method->getNumParams();
 	for (int i = 0; i < n; ++i) {
 		ParmVarDecl *param = method->getParamDecl(i);
@@ -891,7 +1801,7 @@ void cpp_generator::print_exceptional_execution_check(ostream &os,
 			name);
 	}
 
-	check_neg = is_isl_stat(return_type) || is_isl_bool(return_type);
+	check_neg = is_isl_neg_error(return_type);
 	check_null = is_isl_type(return_type);
 	if (!check_null && !check_neg)
 		return;
@@ -903,6 +1813,77 @@ void cpp_generator::print_exceptional_execution_check(ostream &os,
 	print_throw_last_error(os);
 }
 
+/* Does "fd" modify an object of a subclass based on a type function?
+ */
+static bool is_subclass_mutator(const isl_class &clazz, FunctionDecl *fd)
+{
+	return clazz.is_type_subclass() && generator::is_mutator(clazz, fd);
+}
+
+/* Return the C++ return type of the method corresponding to "fd" in "clazz".
+ *
+ * If "fd" modifies an object of a subclass, then return
+ * the type of this subclass.
+ * Otherwise, return the C++ counterpart of the actual return type.
+ */
+std::string cpp_generator::get_return_type(const isl_class &clazz,
+	FunctionDecl *fd)
+{
+	if (is_subclass_mutator(clazz, fd))
+		return type2cpp(clazz);
+	else
+		return type2cpp(fd->getReturnType());
+}
+
+/* Given a function "method" for setting a "clazz" persistent callback,
+ * print the implementations of the methods needed for that callback.
+ *
+ * In particular, print
+ * - the implementation of a static inline method
+ *   for use as the C callback function
+ * - the definition of a private method for setting the callback function
+ * - the public method for constructing a new object with the callback set.
+ */
+void cpp_generator::print_set_persistent_callback(ostream &os,
+	const isl_class &clazz, FunctionDecl *method,
+	function_kind kind)
+{
+	string fullname = method->getName();
+	ParmVarDecl *param = persistent_callback_arg(method);
+	string classname = type2cpp(clazz);
+	string pname;
+	string callback_name = clazz.persistent_callback_name(method);
+
+	osprintf(os, "\n");
+	print_persistent_callback_prototype(os, clazz, method, false);
+	osprintf(os, "\n");
+	osprintf(os, "{\n");
+	print_callback_body(os, 2, param, callback_name);
+	osprintf(os, "}\n\n");
+
+	pname = param->getName().str();
+	print_persistent_callback_setter_prototype(os, clazz, method, false);
+	osprintf(os, "\n");
+	osprintf(os, "{\n");
+	print_check_ptr_start(os, clazz, "ptr");
+	osprintf(os, "  %s_data = std::make_shared<struct %s_data>();\n",
+		callback_name.c_str(), callback_name.c_str());
+	osprintf(os, "  %s_data->func = %s;\n",
+		callback_name.c_str(), pname.c_str());
+	osprintf(os, "  ptr = %s(ptr, &%s, %s_data.get());\n",
+		fullname.c_str(), callback_name.c_str(), callback_name.c_str());
+	print_check_ptr_end(os, "ptr");
+	osprintf(os, "}\n\n");
+
+	print_method_header(os, clazz, method, false, kind);
+	osprintf(os, "{\n");
+	osprintf(os, "  auto copy = *this;\n");
+	osprintf(os, "  copy.set_%s_data(%s);\n",
+		callback_name.c_str(), pname.c_str());
+	osprintf(os, "  return copy;\n");
+	osprintf(os, "}\n");
+}
+
 /* Print the return statement of the C++ method corresponding
  * to the C function "method" in class "clazz" to "os".
  *
@@ -916,16 +1897,29 @@ void cpp_generator::print_exceptional_execution_check(ostream &os,
  * then an isl_bool return type is transformed into a boolean and
  * an isl_stat into a stat since no exceptions can be generated
  * on negative results from the isl function.
+ * If the method returns a new instance of the same object type and
+ * if the class has any persistent callbacks, then the data
+ * for these callbacks are copied from the original to the new object.
+ * If "clazz" is a subclass that is based on a type function and
+ * if the return type corresponds to the superclass data type,
+ * then it is replaced by the subclass data type.
  */
 void cpp_generator::print_method_return(ostream &os, const isl_class &clazz,
 	FunctionDecl *method)
 {
 	QualType return_type = method->getReturnType();
+	string rettype_str = get_return_type(clazz, method);
+	bool returns_super = is_subclass_mutator(clazz, method);
 
 	if (is_isl_type(return_type) ||
-		    (checked &&
-		     (is_isl_bool(return_type) || is_isl_stat(return_type)))) {
-		osprintf(os, "  return manage(res);\n");
+		    (checked && is_isl_neg_error(return_type))) {
+		osprintf(os, "  return manage(res)");
+		if (is_mutator(clazz, method) &&
+		    clazz.has_persistent_callbacks())
+			osprintf(os, ".copy_callbacks(*this)");
+		if (returns_super)
+			osprintf(os, ".as<%s>()", rettype_str.c_str());
+		osprintf(os, ";\n");
 	} else if (is_isl_stat(return_type)) {
 		osprintf(os, "  return;\n");
 	} else if (is_string(return_type)) {
@@ -938,91 +1932,37 @@ void cpp_generator::print_method_return(ostream &os, const isl_class &clazz,
 	}
 }
 
-/* Print definition for "method" in class "clazz" to "os".
- *
- * "kind" specifies the kind of method that should be generated.
- *
- * This method distinguishes three kinds of methods: member methods, static
- * methods, and constructors.
- *
- * Member methods call "method" by passing to the underlying isl function the
- * isl object belonging to "this" as first argument and the remaining arguments
- * as subsequent arguments.
- *
- * Static methods call "method" by passing all arguments to the underlying isl
- * function, as no this-pointer is available. The result is a newly managed
- * isl C++ object.
- *
- * Constructors create a new object from a given set of input parameters. They
- * do not return a value, but instead update the pointer stored inside the
- * newly created object.
- *
- * If the method has a callback argument, we reduce the number of parameters
- * that are exposed by one to hide the user pointer from the interface. On
- * the C++ side no user pointer is needed, as arguments can be forwarded
- * as part of the std::function argument which specifies the callback function.
+/* Return the formal parameter at position "pos" of "fd".
+ * However, if this parameter should be converted, as indicated
+ * by "convert", then return the second formal parameter
+ * of the conversion function instead.
  *
- * Unless checked C++ bindings are being generated,
- * the inputs of the method are first checked for being valid isl objects and
- * a copy of the associated isl::ctx is saved (if needed).
- * If any failure occurs, either during the check for the inputs or
- * during the isl function call, an exception is thrown.
- * During the function call, isl is made not to print any error message
- * because the error message is included in the exception.
+ * If "convert" is empty, then it is assumed that
+ * none of the arguments should be converted.
  */
-void cpp_generator::print_method_impl(ostream &os, const isl_class &clazz,
-	FunctionDecl *method, function_kind kind)
+ParmVarDecl *cpp_generator::get_param(FunctionDecl *fd, int pos,
+	const std::vector<bool> &convert)
 {
-	string methodname = method->getName();
-	int num_params = method->getNumParams();
-
-	print_method_header(os, clazz, method, false, kind);
-	osprintf(os, "{\n");
-	print_argument_validity_check(os, method, kind);
-	print_save_ctx(os, method, kind);
-	print_on_error_continue(os);
-
-	for (int i = 0; i < num_params; ++i) {
-		ParmVarDecl *param = method->getParamDecl(i);
-		if (is_callback(param->getType())) {
-			num_params -= 1;
-			print_callback_local(os, param);
-		}
-	}
-
-	osprintf(os, "  auto res = %s(", methodname.c_str());
-
-	for (int i = 0; i < num_params; ++i) {
-		ParmVarDecl *param = method->getParamDecl(i);
-		bool load_from_this_ptr = false;
-
-		if (i == 0 && kind == function_kind_member_method)
-			load_from_this_ptr = true;
+	ParmVarDecl *param = fd->getParamDecl(pos);
 
-		print_method_param_use(os, param, load_from_this_ptr);
-
-		if (i != num_params - 1)
-			osprintf(os, ", ");
-	}
-	osprintf(os, ");\n");
-
-	print_exceptional_execution_check(os, method);
-	if (kind == function_kind_constructor) {
-		osprintf(os, "  ptr = res;\n");
-	} else {
-		print_method_return(os, clazz, method);
-	}
-
-	osprintf(os, "}\n");
+	if (convert.size() == 0)
+		return param;
+	if (!convert[pos])
+		return param;
+	return conversions[param->getOriginalType().getTypePtr()];
 }
 
-/* Print the header for "method" in class "clazz" to "os".
+/* Print the header for "method" in class "clazz", with name "cname" and
+ * "num_params" number of arguments, to "os".
  *
  * Print the header of a declaration if "is_declaration" is set, otherwise print
  * the header of a method definition.
  *
  * "kind" specifies the kind of method that should be generated.
  *
+ * "convert" specifies which of the method arguments should
+ * be automatically converted.
+ *
  * This function prints headers for member methods, static methods, and
  * constructors, either for their declaration or definition.
  *
@@ -1054,17 +1994,21 @@ void cpp_generator::print_method_impl(ostream &os, const isl_class &clazz,
  * aware of the potential danger that implicit construction is possible
  * for these constructors, whereas without a comment not every user would
  * know that implicit construction is allowed in absence of an explicit keyword.
+ *
+ * If any of the arguments needs to be converted, then the argument
+ * of the method is changed to that of the source of the conversion.
+ * The name of the argument is, however, derived from the original
+ * function argument.
  */
 void cpp_generator::print_method_header(ostream &os, const isl_class &clazz,
-	FunctionDecl *method, bool is_declaration, function_kind kind)
+	FunctionDecl *method, const string &cname, int num_params,
+	bool is_declaration, function_kind kind,
+	const std::vector<bool> &convert)
 {
-	string cname = clazz.method_name(method);
-	string rettype_str = type2cpp(method->getReturnType());
+	string rettype_str = get_return_type(clazz, method);
 	string classname = type2cpp(clazz);
-	int num_params = method->getNumParams();
 	int first_param = 0;
 
-	cname = rename_method(cname);
 	if (kind == function_kind_member_method)
 		first_param = 1;
 
@@ -1098,7 +2042,8 @@ void cpp_generator::print_method_header(ostream &os, const isl_class &clazz,
 	osprintf(os, "(");
 
 	for (int i = first_param; i < num_params; ++i) {
-		ParmVarDecl *param = method->getParamDecl(i);
+		std::string name = method->getParamDecl(i)->getName().str();
+		ParmVarDecl *param = get_param(method, i, convert);
 		QualType type = param->getOriginalType();
 		string cpptype = type2cpp(type);
 
@@ -1107,10 +2052,9 @@ void cpp_generator::print_method_header(ostream &os, const isl_class &clazz,
 
 		if (keeps(param) || is_string(type) || is_callback(type))
 			osprintf(os, "const %s &%s", cpptype.c_str(),
-				 param->getName().str().c_str());
+				 name.c_str());
 		else
-			osprintf(os, "%s %s", cpptype.c_str(),
-				 param->getName().str().c_str());
+			osprintf(os, "%s %s", cpptype.c_str(), name.c_str());
 
 		if (i != num_params - 1)
 			osprintf(os, ", ");
@@ -1126,6 +2070,46 @@ void cpp_generator::print_method_header(ostream &os, const isl_class &clazz,
 	osprintf(os, "\n");
 }
 
+/* Print the header for a method called "name" in class "clazz"
+ * derived from "method" to "os".
+ *
+ * Print the header of a declaration if "is_declaration" is set, otherwise print
+ * the header of a method definition.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ *
+ * "convert" specifies which of the method arguments should
+ * be automatically converted.
+ */
+void cpp_generator::print_named_method_header(ostream &os,
+	const isl_class &clazz, FunctionDecl *method, string name,
+	bool is_declaration, function_kind kind,
+	const std::vector<bool> &convert)
+{
+	int num_params = method->getNumParams();
+
+	name = rename_method(name);
+	print_method_header(os, clazz, method, name, num_params,
+			    is_declaration, kind, convert);
+}
+
+/* Print the header for "method" in class "clazz" to "os"
+ * using its default name.
+ *
+ * Print the header of a declaration if "is_declaration" is set, otherwise print
+ * the header of a method definition.
+ *
+ * "kind" specifies the kind of method that should be generated.
+ */
+void cpp_generator::print_method_header(ostream &os, const isl_class &clazz,
+	FunctionDecl *method, bool is_declaration, function_kind kind)
+{
+	string name = clazz.method_name(method);
+
+	print_named_method_header(os, clazz, method, name, is_declaration,
+				  kind);
+}
+
 /* Generate the list of argument types for a callback function of
  * type "type".  If "cpp" is set, then generate the C++ type list, otherwise
  * the C type list.
@@ -1193,23 +2177,25 @@ string cpp_generator::generate_callback_type(QualType type)
 	return type_str;
 }
 
-/* Print the call to the C++ callback function "call", wrapped
+/* Print the call to the C++ callback function "call",
+ * with the given indentation, wrapped
  * for use inside the lambda function that is used as the C callback function,
  * in the case where checked C++ bindings are being generated.
  *
  * In particular, print
  *
- *        stat ret = @call@;
+ *        auto ret = @call@;
  *        return ret.release();
  */
-void cpp_generator::print_wrapped_call_checked(ostream &os,
+void cpp_generator::print_wrapped_call_checked(ostream &os, int indent,
 	const string &call)
 {
-	osprintf(os, "    stat ret = %s;\n", call.c_str());
-	osprintf(os, "    return ret.release();\n");
+	osprintf(os, indent, "auto ret = %s;\n", call.c_str());
+	osprintf(os, indent, "return ret.release();\n");
 }
 
-/* Print the call to the C++ callback function "call", wrapped
+/* Print the call to the C++ callback function "call",
+ * with the given indentation and with return type "rtype", wrapped
  * for use inside the lambda function that is used as the C callback function.
  *
  * In particular, print
@@ -1221,6 +2207,24 @@ void cpp_generator::print_wrapped_call_checked(ostream &os,
  *          data->eptr = std::current_exception();
  *          return isl_stat_error;
  *        }
+ * or
+ *        ISL_CPP_TRY {
+ *          auto ret = @call@;
+ *          return ret ? isl_bool_true : isl_bool_false;
+ *        } ISL_CPP_CATCH_ALL {
+ *          data->eptr = std::current_exception();
+ *          return isl_bool_error;
+ *        }
+ * or
+ *        ISL_CPP_TRY {
+ *          auto ret = @call@;
+ *          return ret.release();
+ *        } ISL_CPP_CATCH_ALL {
+ *          data->eptr = std::current_exception();
+ *          return NULL;
+ *        }
+ *
+ * depending on the return type.
  *
  * where ISL_CPP_TRY is defined to "try" and ISL_CPP_CATCH_ALL to "catch (...)"
  * (if exceptions are available).
@@ -1228,18 +2232,131 @@ void cpp_generator::print_wrapped_call_checked(ostream &os,
  * If checked C++ bindings are being generated, then
  * the call is wrapped 
diff erently.
  */
-void cpp_generator::print_wrapped_call(ostream &os, const string &call)
+void cpp_generator::print_wrapped_call(ostream &os, int indent,
+	const string &call, QualType rtype)
 {
 	if (checked)
-		return print_wrapped_call_checked(os, call);
+		return print_wrapped_call_checked(os, indent, call);
+
+	osprintf(os, indent, "ISL_CPP_TRY {\n");
+	if (is_isl_stat(rtype))
+		osprintf(os, indent, "  %s;\n", call.c_str());
+	else
+		osprintf(os, indent, "  auto ret = %s;\n", call.c_str());
+	if (is_isl_stat(rtype))
+		osprintf(os, indent, "  return isl_stat_ok;\n");
+	else if (is_isl_bool(rtype))
+		osprintf(os, indent,
+			"  return ret ? isl_bool_true : isl_bool_false;\n");
+	else
+		osprintf(os, indent, "  return ret.release();\n");
+	osprintf(os, indent, "} ISL_CPP_CATCH_ALL {\n");
+	osprintf(os, indent, "  data->eptr = std::current_exception();\n");
+	if (is_isl_stat(rtype))
+		osprintf(os, indent, "  return isl_stat_error;\n");
+	else if (is_isl_bool(rtype))
+		osprintf(os, indent, "  return isl_bool_error;\n");
+	else
+		osprintf(os, indent, "  return NULL;\n");
+	osprintf(os, indent, "}\n");
+}
+
+/* Print the declaration for a "prefix"_data data structure
+ * that can be used for passing to a C callback function
+ * containing a copy of the C++ callback function "param",
+ * along with an std::exception_ptr that is used to store any
+ * exceptions thrown in the C++ callback.
+ *
+ * If the C callback is of the form
+ *
+ *      isl_stat (*fn)(__isl_take isl_map *map, void *user)
+ *
+ * then the following declaration is printed:
+ *
+ *      struct <prefix>_data {
+ *        std::function<stat(map)> func;
+ *        std::exception_ptr eptr;
+ *      }
+ *
+ * (without a newline or a semicolon).
+ *
+ * The std::exception_ptr object is not added to "prefix"_data
+ * if checked C++ bindings are being generated.
+ */
+void cpp_generator::print_callback_data_decl(ostream &os, ParmVarDecl *param,
+	const string &prefix)
+{
+	string cpp_args;
+
+	cpp_args = generate_callback_type(param->getType());
+
+	osprintf(os, "  struct %s_data {\n", prefix.c_str());
+	osprintf(os, "    %s func;\n", cpp_args.c_str());
+	if (!checked)
+		osprintf(os, "    std::exception_ptr eptr;\n");
+	osprintf(os, "  }");
+}
+
+/* Print the body of C function callback with the given indentation
+ * that can be use as an argument to "param" for marshalling
+ * the corresponding C++ callback.
+ * The data structure that contains the C++ callback is of type
+ * "prefix"_data.
+ *
+ * For a callback of the form
+ *
+ *      isl_stat (*fn)(__isl_take isl_map *map, void *user)
+ *
+ * the following code is generated:
+ *
+ *        auto *data = static_cast<struct <prefix>_data *>(arg_1);
+ *        ISL_CPP_TRY {
+ *          stat ret = (data->func)(manage(arg_0));
+ *          return isl_stat_ok;
+ *        } ISL_CPP_CATCH_ALL {
+ *          data->eptr = std::current_exception();
+ *          return isl_stat_error;
+ *        }
+ *
+ * If checked C++ bindings are being generated, then
+ * generate the following code:
+ *
+ *        auto *data = static_cast<struct <prefix>_data *>(arg_1);
+ *        stat ret = (data->func)(manage(arg_0));
+ *        return isl_stat(ret);
+ */
+void cpp_generator::print_callback_body(ostream &os, int indent,
+	ParmVarDecl *param, const string &prefix)
+{
+	QualType ptype, rtype;
+	string call, last_idx;
+	const FunctionProtoType *callback;
+	int num_params;
+
+	ptype = param->getType();
+
+	callback = extract_prototype(ptype);
+	rtype = callback->getReturnType();
+	num_params = callback->getNumArgs();
+
+	last_idx = ::to_string(num_params - 1);
+
+	call = "(data->func)(";
+	for (long i = 0; i < num_params - 1; i++) {
+		if (!callback_takes_argument(param, i))
+			call += "manage_copy";
+		else
+			call += "manage";
+		call += "(arg_" + ::to_string(i) + ")";
+		if (i != num_params - 2)
+			call += ", ";
+	}
+	call += ")";
 
-	osprintf(os, "    ISL_CPP_TRY {\n");
-	osprintf(os, "      %s;\n", call.c_str());
-	osprintf(os, "      return isl_stat_ok;\n");
-	osprintf(os, "    } ISL_CPP_CATCH_ALL {\n"
-		     "      data->eptr = std::current_exception();\n");
-	osprintf(os, "      return isl_stat_error;\n");
-	osprintf(os, "    }\n");
+	osprintf(os, indent,
+		 "auto *data = static_cast<struct %s_data *>(arg_%s);\n",
+		 prefix.c_str(), last_idx.c_str());
+	print_wrapped_call(os, indent, call, rtype);
 }
 
 /* Print the local variables that are needed for a callback argument,
@@ -1255,7 +2372,7 @@ void cpp_generator::print_wrapped_call(ostream &os, const string &call)
  *      auto fn_lambda = [](isl_map *arg_0, void *arg_1) -> isl_stat {
  *        auto *data = static_cast<struct fn_data *>(arg_1);
  *        try {
- *          stat ret = (*data->func)(manage(arg_0));
+ *          stat ret = (data->func)(manage(arg_0));
  *          return isl_stat_ok;
  *        } catch (...) {
  *          data->eptr = std::current_exception();
@@ -1263,15 +2380,15 @@ void cpp_generator::print_wrapped_call(ostream &os, const string &call)
  *        }
  *      };
  *
- * The pointer to the std::function C++ callback function is stored in
+ * A copy of the std::function C++ callback function is stored in
  * a fn_data data structure for passing to the C callback function,
  * along with an std::exception_ptr that is used to store any
  * exceptions thrown in the C++ callback.
  *
  *      struct fn_data {
- *        const std::function<stat(map)> *func;
+ *        std::function<stat(map)> func;
  *        std::exception_ptr eptr;
- *      } fn_data = { &fn };
+ *      } fn_data = { fn };
  *
  * This std::function object represents the actual user
  * callback function together with the locally captured state at the caller.
@@ -1286,7 +2403,7 @@ void cpp_generator::print_wrapped_call(ostream &os, const string &call)
  * if checked C++ bindings are being generated.
  * The body of the generated lambda function then is as follows:
  *
- *        stat ret = (*data->func)(manage(arg_0));
+ *        stat ret = (data->func)(manage(arg_0));
  *        return isl_stat(ret);
  *
  * If the C callback does not take its arguments, then
@@ -1295,46 +2412,24 @@ void cpp_generator::print_wrapped_call(ostream &os, const string &call)
 void cpp_generator::print_callback_local(ostream &os, ParmVarDecl *param)
 {
 	string pname;
-	QualType ptype;
-	string call, c_args, cpp_args, rettype, last_idx;
+	QualType ptype, rtype;
+	string c_args, cpp_args, rettype;
 	const FunctionProtoType *callback;
-	int num_params;
 
 	pname = param->getName().str();
 	ptype = param->getType();
 
 	c_args = generate_callback_args(ptype, false);
-	cpp_args = generate_callback_type(ptype);
 
 	callback = extract_prototype(ptype);
-	rettype = callback->getReturnType().getAsString();
-	num_params = callback->getNumArgs();
-
-	last_idx = ::to_string(num_params - 1);
-
-	call = "(*data->func)(";
-	for (long i = 0; i < num_params - 1; i++) {
-		if (!callback_takes_argument(param, i))
-			call += "manage_copy";
-		else
-			call += "manage";
-		call += "(arg_" + ::to_string(i) + ")";
-		if (i != num_params - 2)
-			call += ", ";
-	}
-	call += ")";
+	rtype = callback->getReturnType();
+	rettype = rtype.getAsString();
 
-	osprintf(os, "  struct %s_data {\n", pname.c_str());
-	osprintf(os, "    const %s *func;\n", cpp_args.c_str());
-	if (!checked)
-		osprintf(os, "    std::exception_ptr eptr;\n");
-	osprintf(os, "  } %s_data = { &%s };\n", pname.c_str(), pname.c_str());
+	print_callback_data_decl(os, param, pname);
+	osprintf(os, " %s_data = { %s };\n", pname.c_str(), pname.c_str());
 	osprintf(os, "  auto %s_lambda = [](%s) -> %s {\n",
 		 pname.c_str(), c_args.c_str(), rettype.c_str());
-	osprintf(os,
-		 "    auto *data = static_cast<struct %s_data *>(arg_%s);\n",
-		 pname.c_str(), last_idx.c_str());
-	print_wrapped_call(os, call);
+	print_callback_body(os, 4, param, pname);
 	osprintf(os, "  };\n");
 }
 
@@ -1360,10 +2455,11 @@ std::string cpp_generator::rename_method(std::string name)
 }
 
 /* Translate isl class "clazz" to its corresponding C++ type.
+ * Use the name of the type based subclass, if any.
  */
 string cpp_generator::type2cpp(const isl_class &clazz)
 {
-	return type2cpp(clazz.name);
+	return type2cpp(clazz.subclass_name);
 }
 
 /* Translate type string "type_str" to its C++ name counterpart.
@@ -1373,25 +2469,46 @@ string cpp_generator::type2cpp(string type_str)
 	return type_str.substr(4);
 }
 
+/* Return the C++ counterpart to the isl_bool type.
+ * If checked C++ bindings are being generated,
+ * then this is "boolean".  Otherwise, it is simply "bool".
+ */
+string cpp_generator::isl_bool2cpp()
+{
+	return checked ? "boolean" : "bool";
+}
+
+/* Return the namespace of the generated C++ bindings.
+ */
+string cpp_generator::isl_namespace()
+{
+	return checked ? "isl::checked::" : "isl::";
+}
+
 /* Translate QualType "type" to its C++ name counterpart.
  *
  * An isl_bool return type is translated into "bool",
- * while an isl_stat is translated into "void".
+ * while an isl_stat is translated into "void" and
+ * an isl_size is translated to "unsigned".
  * The exceptional cases are handled through exceptions.
  * If checked C++ bindings are being generated, then
- * C++ counterparts of isl_bool and isl_stat need to be used instead.
+ * C++ counterparts of isl_bool, isl_stat and isl_size need to be used instead.
  */
 string cpp_generator::type2cpp(QualType type)
 {
 	if (is_isl_type(type))
-		return type2cpp(type->getPointeeType().getAsString());
+		return isl_namespace() +
+				type2cpp(type->getPointeeType().getAsString());
 
 	if (is_isl_bool(type))
-		return checked ? "boolean" : "bool";
+		return isl_bool2cpp();
 
 	if (is_isl_stat(type))
 		return checked ? "stat" : "void";
 
+	if (is_isl_size(type))
+		return checked ? "class size" : "unsigned";
+
 	if (type->isIntegerType())
 		return type.getAsString();
 

diff  --git a/polly/lib/External/isl/interface/cpp.h b/polly/lib/External/isl/interface/cpp.h
index 0e97c71533ae..c207af1dd99f 100644
--- a/polly/lib/External/isl/interface/cpp.h
+++ b/polly/lib/External/isl/interface/cpp.h
@@ -24,17 +24,21 @@ class cpp_generator : public generator {
 		function_kind_member_method,
 		function_kind_constructor,
 	};
+	enum method_part {
+		decl,
+		impl,
+	};
 
 	virtual void generate();
 private:
-	void print_file(ostream &os, std::string filename);
 	void print_forward_declarations(ostream &os);
 	void print_declarations(ostream &os);
 	void print_class(ostream &os, const isl_class &clazz);
+	void print_subclass_type(ostream &os, const isl_class &clazz);
 	void print_class_forward_decl(ostream &os, const isl_class &clazz);
 	void print_class_factory_decl(ostream &os, const isl_class &clazz,
 		const std::string &prefix = std::string());
-	void print_private_constructors_decl(ostream &os,
+	void print_protected_constructors_decl(ostream &os,
 		const isl_class &clazz);
 	void print_copy_assignment_decl(ostream &os, const isl_class &clazz);
 	void print_public_constructors_decl(ostream &os,
@@ -42,12 +46,42 @@ class cpp_generator : public generator {
 	void print_constructors_decl(ostream &os, const isl_class &clazz);
 	void print_destructor_decl(ostream &os, const isl_class &clazz);
 	void print_ptr_decl(ostream &os, const isl_class &clazz);
-	void print_get_ctx_decl(ostream &os);
+	void print_isa_type_template(ostream &os, int indent,
+		const isl_class &super);
+	void print_downcast_decl(ostream &os, const isl_class &clazz);
+	void print_ctx_decl(ostream &os);
+	void print_persistent_callback_prototype(ostream &os,
+		const isl_class &clazz, FunctionDecl *method,
+		bool is_declaration);
+	void print_persistent_callback_setter_prototype(ostream &os,
+		const isl_class &clazz, FunctionDecl *method,
+		bool is_declaration);
+	void print_persistent_callback_data(ostream &os, const isl_class &clazz,
+		FunctionDecl *method);
+	void print_persistent_callbacks_decl(ostream &os,
+		const isl_class &clazz);
 	void print_methods_decl(ostream &os, const isl_class &clazz);
+	bool next_variant(FunctionDecl *fd, std::vector<bool> &convert);
+	template <enum method_part>
+	void print_method_variants(ostream &os, const isl_class &clazz,
+		FunctionDecl *fd);
 	void print_method_group_decl(ostream &os, const isl_class &clazz,
-		const set<FunctionDecl *> &methods);
-	void print_method_decl(ostream &os, const isl_class &clazz,
+		const function_set &methods);
+	void print_named_method_decl(ostream &os, const isl_class &clazz,
+		FunctionDecl *fd, const string &name, function_kind kind,
+		const std::vector<bool> &convert = {});
+	template <enum method_part>
+	void print_method(ostream &os, const isl_class &clazz,
 		FunctionDecl *method, function_kind kind);
+	template <enum method_part>
+	void print_method(ostream &os, const isl_class &clazz,
+		FunctionDecl *method, function_kind kind,
+		const std::vector<bool> &convert);
+	void print_set_enum_decl(ostream &os, const isl_class &clazz,
+		FunctionDecl *fd, const string &name);
+	void print_set_enums_decl(ostream &os, const isl_class &clazz,
+		FunctionDecl *fd);
+	void print_set_enums_decl(ostream &os, const isl_class &clazz);
 	void print_implementations(ostream &os);
 	void print_class_impl(ostream &os, const isl_class &clazz);
 	void print_check_ptr(ostream &os, const char *ptr);
@@ -55,46 +89,81 @@ class cpp_generator : public generator {
 		const char *ptr);
 	void print_check_ptr_end(ostream &os, const char *ptr);
 	void print_class_factory_impl(ostream &os, const isl_class &clazz);
-	void print_private_constructors_impl(ostream &os,
+	void print_protected_constructors_impl(ostream &os,
 		const isl_class &clazz);
 	void print_public_constructors_impl(ostream &os,
 		const isl_class &clazz);
 	void print_constructors_impl(ostream &os, const isl_class &clazz);
 	void print_copy_assignment_impl(ostream &os, const isl_class &clazz);
 	void print_destructor_impl(ostream &os, const isl_class &clazz);
+	void print_check_no_persistent_callback(ostream &os,
+		const isl_class &clazz, FunctionDecl *fd);
 	void print_ptr_impl(ostream &os, const isl_class &clazz);
-	void print_get_ctx_impl(ostream &os, const isl_class &clazz);
+	void print_downcast_impl(ostream &os, const isl_class &clazz);
+	void print_ctx_impl(ostream &os, const isl_class &clazz);
+	void print_persistent_callbacks_impl(ostream &os,
+		const isl_class &clazz);
 	void print_methods_impl(ostream &os, const isl_class &clazz);
 	void print_method_group_impl(ostream &os, const isl_class &clazz,
-		const set<FunctionDecl *> &methods);
+		const function_set &methods);
 	void print_argument_validity_check(ostream &os, FunctionDecl *method,
 		function_kind kind);
 	void print_save_ctx(ostream &os, FunctionDecl *method,
 		function_kind kind);
 	void print_on_error_continue(ostream &os);
 	void print_exceptional_execution_check(ostream &os,
-		FunctionDecl *method);
+		const isl_class &clazz, FunctionDecl *method,
+		function_kind kind);
+	void print_set_persistent_callback(ostream &os, const isl_class &clazz,
+		FunctionDecl *method, function_kind kind);
 	void print_method_return(ostream &os, const isl_class &clazz,
 		FunctionDecl *method);
-	void print_method_impl(ostream &os, const isl_class &clazz,
-		FunctionDecl *method, function_kind kind);
+	void print_set_enum_impl(ostream &os, const isl_class &clazz,
+		FunctionDecl *fd, const string &enum_name,
+		const string &method_name);
+	void print_set_enums_impl(ostream &os, const isl_class &clazz,
+		FunctionDecl *fd);
+	void print_set_enums_impl(ostream &os, const isl_class &clazz);
+	template <enum method_part>
+	void print_get_method(ostream &os, const isl_class &clazz,
+		FunctionDecl *fd);
+	void print_invalid(ostream &os, int indent, const char *msg,
+		const char *checked_code);
+	void print_stream_insertion(ostream &os, const isl_class &clazz);
 	void print_method_param_use(ostream &os, ParmVarDecl *param,
 		bool load_from_this_ptr);
+	std::string get_return_type(const isl_class &clazz, FunctionDecl *fd);
+	ParmVarDecl *get_param(FunctionDecl *fd, int pos,
+		const std::vector<bool> &convert);
+	void print_method_header(ostream &os, const isl_class &clazz,
+		FunctionDecl *method, const string &cname, int num_params,
+		bool is_declaration, function_kind kind,
+		const std::vector<bool> &convert = {});
+	void print_named_method_header(ostream &os, const isl_class &clazz,
+		FunctionDecl *method, string name, bool is_declaration,
+		function_kind kind, const std::vector<bool> &convert = {});
 	void print_method_header(ostream &os, const isl_class &clazz,
 		FunctionDecl *method, bool is_declaration, function_kind kind);
 	string generate_callback_args(QualType type, bool cpp);
 	string generate_callback_type(QualType type);
-	void print_wrapped_call_checked(std::ostream &os,
+	void print_wrapped_call_checked(std::ostream &os, int indent,
 		const std::string &call);
-	void print_wrapped_call(std::ostream &os, const std::string &call);
+	void print_wrapped_call(std::ostream &os, int indent,
+		const std::string &call, QualType rtype);
+	void print_callback_data_decl(ostream &os, ParmVarDecl *param,
+		const string &name);
+	void print_callback_body(ostream &os, int indent, ParmVarDecl *param,
+		const string &name);
 	void print_callback_local(ostream &os, ParmVarDecl *param);
 	std::string rename_method(std::string name);
-	string type2cpp(const isl_class &clazz);
+	string isl_bool2cpp();
+	string isl_namespace();
 	string type2cpp(QualType type);
 	bool is_implicit_conversion(const isl_class &clazz, FunctionDecl *cons);
 	bool is_subclass(QualType subclass_type, const isl_class &class_type);
 	function_kind get_method_kind(const isl_class &clazz,
 		FunctionDecl *method);
 public:
+	static string type2cpp(const isl_class &clazz);
 	static string type2cpp(string type_string);
 };

diff  --git a/polly/lib/External/isl/interface/cpp_conversion.cc b/polly/lib/External/isl/interface/cpp_conversion.cc
index abdfcaff7f27..58294d54800b 100644
--- a/polly/lib/External/isl/interface/cpp_conversion.cc
+++ b/polly/lib/External/isl/interface/cpp_conversion.cc
@@ -6,17 +6,46 @@
  * Written by Sven Verdoolaege.
  */
 
+#include <stdio.h>
+#include <map>
+#include <string>
+
 #include "cpp.h"
 #include "cpp_conversion.h"
 
+/* If "clazz" describes a subclass of a C type, then print code
+ * for converting an object of the class derived from the C type
+ * to the subclass.  Do this by first converting this class
+ * to the immediate superclass of the subclass and then converting
+ * from this superclass to the subclass.
+ */
+void cpp_conversion_generator::cast(const isl_class &clazz, const char *to)
+{
+	string name = cpp_generator::type2cpp(clazz);
+
+	if (!clazz.is_type_subclass())
+		return;
+
+	cast(classes[clazz.superclass_name], to);
+	printf(".as<%s%s>()", to, name.c_str());
+}
+
 /* Print a function called "function" for converting objects of
- * type "name" from the "from" bindings to the "to" bindings.
+ * "clazz" from the "from" bindings to the "to" bindings.
+ * If "clazz" describes a subclass of a C type, then the result
+ * of the conversion between bindings is derived from the C type and
+ * needs to be converted back to the subclass.
  */
-static void convert(const char *name, const char *from, const char *to,
-	const char *function)
+void cpp_conversion_generator::convert(const isl_class &clazz,
+	const char *from, const char *to, const char *function)
 {
-	printf("%s%s %s(%s%s obj) {\n", to, name, function, from, name);
-	printf("\t""return %s""manage(obj.copy());\n", to);
+	string name = cpp_generator::type2cpp(clazz);
+
+	printf("%s%s %s(%s%s obj) {\n",
+		to, name.c_str(), function, from, name.c_str());
+	printf("\t""return %s""manage(obj.copy())", to);
+	cast(clazz, to);
+	printf(";\n");
 	printf("}\n");
 	printf("\n");
 }
@@ -36,12 +65,10 @@ static void convert(const char *name, const char *from, const char *to,
  *		return manage(obj.copy());
  *	}
  */
-static void print(const isl_class &clazz)
+void cpp_conversion_generator::print(const isl_class &clazz)
 {
-	string name = cpp_generator::type2cpp(clazz.name);
-
-	convert(name.c_str(), "", "checked::", "check");
-	convert(name.c_str(), "checked::", "", "uncheck");
+	convert(clazz, "", "checked::", "check");
+	convert(clazz, "checked::", "", "uncheck");
 }
 
 /* Generate conversion functions for converting objects between

diff  --git a/polly/lib/External/isl/interface/cpp_conversion.h b/polly/lib/External/isl/interface/cpp_conversion.h
index 6fd09c5b876f..57856b2c6a5d 100644
--- a/polly/lib/External/isl/interface/cpp_conversion.h
+++ b/polly/lib/External/isl/interface/cpp_conversion.h
@@ -1,6 +1,10 @@
 #include "generator.h"
 
 class cpp_conversion_generator : public generator {
+	void cast(const isl_class &clazz, const char *to);
+	void convert(const isl_class &clazz, const char *from, const char *to,
+		const char *function);
+	void print(const isl_class &clazz);
 public:
 	cpp_conversion_generator(SourceManager &SM,
 		set<RecordDecl *> &exported_types,

diff  --git a/polly/lib/External/isl/interface/extract_interface.cc b/polly/lib/External/isl/interface/extract_interface.cc
index 1267c370f7a3..34a7f40493ab 100644
--- a/polly/lib/External/isl/interface/extract_interface.cc
+++ b/polly/lib/External/isl/interface/extract_interface.cc
@@ -32,6 +32,7 @@
  */ 
 
 #include "isl_config.h"
+#undef PACKAGE
 
 #include <assert.h>
 #include <iostream>
@@ -41,12 +42,16 @@
 #else
 #include <memory>
 #endif
+#ifdef HAVE_LLVM_OPTION_ARG_H
+#include <llvm/Option/Arg.h>
+#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/Builtins.h>
 #include <clang/Basic/FileSystemOptions.h>
 #include <clang/Basic/FileManager.h>
 #include <clang/Basic/TargetOptions.h>
@@ -83,6 +88,9 @@
 using namespace std;
 using namespace clang;
 using namespace clang::driver;
+#ifdef HAVE_LLVM_OPTION_ARG_H
+using namespace llvm::opt;
+#endif
 
 #ifdef HAVE_ADT_OWNINGPTR_H
 #define unique_ptr	llvm::OwningPtr
@@ -94,7 +102,7 @@ static llvm::cl::list<string> Includes("I",
 			llvm::cl::desc("Header search path"),
 			llvm::cl::value_desc("path"), llvm::cl::Prefix);
 
-static llvm::cl::opt<string> Language(llvm::cl::Required,
+static llvm::cl::opt<string> OutputLanguage(llvm::cl::Required,
 	llvm::cl::ValueRequired, "language",
 	llvm::cl::desc("Bindings to generate"),
 	llvm::cl::value_desc("name"));
@@ -203,6 +211,32 @@ struct ClangAPI {
 	static Command *command(Command &C) { return &C; }
 };
 
+#ifdef CREATE_FROM_ARGS_TAKES_ARRAYREF
+
+/* Call CompilerInvocation::CreateFromArgs with the right arguments.
+ * In this case, an ArrayRef<const char *>.
+ */
+static void create_from_args(CompilerInvocation &invocation,
+	const ArgStringList *args, DiagnosticsEngine &Diags)
+{
+	CompilerInvocation::CreateFromArgs(invocation, *args, Diags);
+}
+
+#else
+
+/* Call CompilerInvocation::CreateFromArgs with the right arguments.
+ * In this case, two "const char *" pointers.
+ */
+static void create_from_args(CompilerInvocation &invocation,
+	const ArgStringList *args, DiagnosticsEngine &Diags)
+{
+	CompilerInvocation::CreateFromArgs(invocation, args->data() + 1,
+						args->data() + args->size(),
+						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
@@ -227,9 +261,7 @@ static CompilerInvocation *construct_invocation(const char *filename,
 	const ArgStringList *args = &cmd->getArguments();
 
 	CompilerInvocation *invocation = new CompilerInvocation;
-	CompilerInvocation::CreateFromArgs(*invocation, args->data() + 1,
-						args->data() + args->size(),
-						Diags);
+	create_from_args(*invocation, args, Diags);
 	return invocation;
 }
 
@@ -396,6 +428,44 @@ static void set_invocation(CompilerInstance *Clang,
 
 #endif
 
+/* Helper function for ignore_error that only gets enabled if T
+ * (which is either const FileEntry * or llvm::ErrorOr<const FileEntry *>)
+ * has getError method, i.e., if it is llvm::ErrorOr<const FileEntry *>.
+ */
+template <class T>
+static const FileEntry *ignore_error_helper(const T obj, int,
+	int[1][sizeof(obj.getError())])
+{
+	return *obj;
+}
+
+/* Helper function for ignore_error that is always enabled,
+ * but that only gets selected if the variant above is not enabled,
+ * i.e., if T is const FileEntry *.
+ */
+template <class T>
+static const FileEntry *ignore_error_helper(const T obj, long, void *)
+{
+	return obj;
+}
+
+/* Given either a const FileEntry * or a llvm::ErrorOr<const FileEntry *>,
+ * extract out the const FileEntry *.
+ */
+template <class T>
+static const FileEntry *ignore_error(const T obj)
+{
+	return ignore_error_helper(obj, 0, NULL);
+}
+
+/* Return the FileEntry corresponding to the given file name
+ * in the given compiler instances, ignoring any error.
+ */
+static const FileEntry *getFile(CompilerInstance *Clang, std::string Filename)
+{
+	return ignore_error(Clang->getFileManager().getFile(Filename));
+}
+
 /* Create an interface generator for the selected language and
  * then use it to generate the interface.
  */
@@ -403,20 +473,21 @@ static void generate(MyASTConsumer &consumer, SourceManager &SM)
 {
 	generator *gen;
 
-	if (Language.compare("python") == 0) {
+	if (OutputLanguage.compare("python") == 0) {
 		gen = new python_generator(SM, consumer.exported_types,
 			consumer.exported_functions, consumer.functions);
-	} else if (Language.compare("cpp") == 0) {
+	} else if (OutputLanguage.compare("cpp") == 0) {
 		gen = new cpp_generator(SM, consumer.exported_types,
 			consumer.exported_functions, consumer.functions);
-	} else if (Language.compare("cpp-checked") == 0) {
+	} else if (OutputLanguage.compare("cpp-checked") == 0) {
 		gen = new cpp_generator(SM, consumer.exported_types,
 			consumer.exported_functions, consumer.functions, true);
-	} else if (Language.compare("cpp-checked-conversion") == 0) {
+	} else if (OutputLanguage.compare("cpp-checked-conversion") == 0) {
 		gen = new cpp_conversion_generator(SM, consumer.exported_types,
 			consumer.exported_functions, consumer.functions);
 	} else {
-		cerr << "Language '" << Language << "' not recognized." << endl
+		cerr << "Language '" << OutputLanguage
+		     << "' not recognized." << endl
 		     << "Not generating bindings." << endl;
 		exit(EXIT_FAILURE);
 	}
@@ -432,15 +503,15 @@ int main(int argc, char *argv[])
 	create_diagnostics(Clang);
 	DiagnosticsEngine &Diags = Clang->getDiagnostics();
 	Diags.setSuppressSystemWarnings(true);
+	TargetInfo *target = create_target_info(Clang, Diags);
+	Clang->setTarget(target);
+	set_lang_defaults(Clang);
 	CompilerInvocation *invocation =
 		construct_invocation(InputFilename.c_str(), Diags);
 	if (invocation)
 		set_invocation(Clang, invocation);
 	Clang->createFileManager();
 	Clang->createSourceManager(Clang->getFileManager());
-	TargetInfo *target = create_target_info(Clang, Diags);
-	Clang->setTarget(target);
-	set_lang_defaults(Clang);
 	HeaderSearchOptions &HSO = Clang->getHeaderSearchOpts();
 	LangOptions &LO = Clang->getLangOpts();
 	PreprocessorOptions &PO = Clang->getPreprocessorOpts();
@@ -464,7 +535,7 @@ int main(int argc, char *argv[])
 
 	PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), LO);
 
-	const FileEntry *file = Clang->getFileManager().getFile(InputFilename);
+	const FileEntry *file = getFile(Clang, InputFilename);
 	assert(file);
 	create_main_file_id(Clang->getSourceManager(), file);
 
@@ -482,5 +553,7 @@ int main(int argc, char *argv[])
 	delete Clang;
 	llvm::llvm_shutdown();
 
+	if (Diags.hasErrorOccurred())
+		return EXIT_FAILURE;
 	return EXIT_SUCCESS;
 }

diff  --git a/polly/lib/External/isl/interface/generator.cc b/polly/lib/External/isl/interface/generator.cc
index fee2347b6c5c..075a3d6294ac 100644
--- a/polly/lib/External/isl/interface/generator.cc
+++ b/polly/lib/External/isl/interface/generator.cc
@@ -33,6 +33,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <algorithm>
 #include <iostream>
 
 #include <clang/AST/Attr.h>
@@ -42,11 +43,26 @@
 #include "extract_interface.h"
 #include "generator.h"
 
-/* Compare the prefix of "s" to "prefix" up to the length of "prefix".
+const char *isl_class::get_prefix = "get_";
+const char *isl_class::set_callback_prefix = "set_";
+
+/* Should "method" be considered to be a static method?
+ * That is, is the first argument something other than
+ * an instance of the class?
  */
-static int prefixcmp(const char *s, const char *prefix)
+bool isl_class::is_static(FunctionDecl *method) const
 {
-	return strncmp(s, prefix, strlen(prefix));
+	ParmVarDecl *param;
+	QualType type;
+
+	if (method->getNumParams() < 1)
+		return true;
+
+	param = method->getParamDecl(0);
+	type = param->getOriginalType();
+	if (!generator::is_isl_type(type))
+		return true;
+	return generator::extract_type(type) != name;
 }
 
 /* Should "method" be considered to be a static method?
@@ -55,12 +71,31 @@ static int prefixcmp(const char *s, const char *prefix)
  */
 bool generator::is_static(const isl_class &clazz, FunctionDecl *method)
 {
-	ParmVarDecl *param = method->getParamDecl(0);
-	QualType type = param->getOriginalType();
+	return clazz.is_static(method);
+}
 
-	if (!is_isl_type(type))
-		return true;
-	return extract_type(type) != clazz.name;
+/* Does "fd" modify an object of "clazz"?
+ * That is, is it an object method that takes the object and
+ * returns (gives) an object of the same type?
+ */
+bool generator::is_mutator(const isl_class &clazz, FunctionDecl *fd)
+{
+	ParmVarDecl *param;
+	QualType type, return_type;
+
+	if (fd->getNumParams() < 1)
+		return false;
+	if (is_static(clazz, fd))
+		return false;
+
+	if (!gives(fd))
+		return false;
+	param = fd->getParamDecl(0);
+	if (!takes(param))
+		return false;
+	type = param->getOriginalType();
+	return_type = fd->getReturnType();
+	return return_type == type;
 }
 
 /* Find the FunctionDecl with name "name",
@@ -79,49 +114,291 @@ FunctionDecl *generator::find_by_name(const string &name, bool required)
 	return NULL;
 }
 
+/* List of conversion functions that are used to automatically convert
+ * the second argument of the conversion function to its function result.
+ */
+const std::set<std::string> generator::automatic_conversion_functions = {
+	"isl_id_read_from_str",
+	"isl_val_int_from_si",
+};
+
+/* Extract information about the automatic conversion function "fd",
+ * storing the results in this->conversions.
+ *
+ * A function used for automatic conversion has exactly two arguments,
+ * an isl_ctx and a non-isl object, and it returns an isl object.
+ * Store a mapping from the isl object return type
+ * to the non-isl object source type.
+ */
+void generator::extract_automatic_conversion(FunctionDecl *fd)
+{
+	QualType return_type = fd->getReturnType();
+	const Type *type = return_type.getTypePtr();
+
+	if (fd->getNumParams() != 2)
+		die("Expecting two arguments");
+	if (!is_isl_ctx(fd->getParamDecl(0)->getOriginalType()))
+		die("Expecting isl_ctx first argument");
+	if (!is_isl_type(return_type))
+		die("Expecting isl object return type");
+	conversions[type] = fd->getParamDecl(1);
+}
+
+/* Extract information about all automatic conversion functions
+ * for the given class, storing the results in this->conversions.
+ *
+ * In particular, look through all exported constructors for the class and
+ * check if any of them is explicitly marked as a conversion function.
+ */
+void generator::extract_class_automatic_conversions(const isl_class &clazz)
+{
+	const function_set &constructors = clazz.constructors;
+	function_set::iterator fi;
+
+	for (fi = constructors.begin(); fi != constructors.end(); ++fi) {
+		FunctionDecl *fd = *fi;
+		string name = fd->getName();
+		if (automatic_conversion_functions.count(name) != 0)
+			extract_automatic_conversion(fd);
+	}
+}
+
+/* Extract information about all automatic conversion functions,
+ * storing the results in this->conversions.
+ */
+void generator::extract_automatic_conversions()
+{
+	map<string, isl_class>::iterator ci;
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci)
+		extract_class_automatic_conversions(ci->second);
+}
+
+/* Add a subclass derived from "decl" called "sub_name" to the set of classes,
+ * keeping track of the _to_str, _copy and _free functions, if any, separately.
+ * "sub_name" is either the name of the class itself or
+ * the name of a type based subclass.
+ * If the class is a proper subclass, then "super_name" is the name
+ * of its immediate superclass.
+ */
+void generator::add_subclass(RecordDecl *decl, const string &super_name,
+	const string &sub_name)
+{
+	string name = decl->getName();
+
+	classes[sub_name].name = name;
+	classes[sub_name].superclass_name = super_name;
+	classes[sub_name].subclass_name = sub_name;
+	classes[sub_name].type = decl;
+	classes[sub_name].fn_to_str = find_by_name(name + "_to_str", false);
+	classes[sub_name].fn_copy = find_by_name(name + "_copy", true);
+	classes[sub_name].fn_free = find_by_name(name + "_free", true);
+}
+
+/* Add a class derived from "decl" to the set of classes,
+ * keeping track of the _to_str, _copy and _free functions, if any, separately.
+ */
+void generator::add_class(RecordDecl *decl)
+{
+	return add_subclass(decl, "", decl->getName());
+}
+
+/* Given a function "fn_type" that returns the subclass type
+ * of a C object, create subclasses for each of the (non-negative)
+ * return values.
+ *
+ * The function "fn_type" is also stored in the superclass,
+ * along with all pairs of type values and subclass names.
+ */
+void generator::add_type_subclasses(FunctionDecl *fn_type)
+{
+	QualType return_type = fn_type->getReturnType();
+	const EnumType *enum_type = return_type->getAs<EnumType>();
+	EnumDecl *decl = enum_type->getDecl();
+	isl_class *c = method2class(fn_type);
+	DeclContext::decl_iterator i;
+
+	c->fn_type = fn_type;
+	for (i = decl->decls_begin(); i != decl->decls_end(); ++i) {
+		EnumConstantDecl *ecd = dyn_cast<EnumConstantDecl>(*i);
+		int val = (int) ecd->getInitVal().getSExtValue();
+		string name = ecd->getNameAsString();
+
+		if (val < 0)
+			continue;
+		c->type_subclasses[val] = name;
+		add_subclass(c->type, c->subclass_name, name);
+	}
+}
+
+/* Add information about the enum values in "decl", set by "fd",
+ * to c->set_enums. "prefix" is the prefix of the generated method names.
+ * In particular, it has the name of the enum type removed.
+ *
+ * In particular, for each non-negative enum value, keep track of
+ * the value, the name and the corresponding method name.
+ */
+static void add_set_enum(isl_class *c, const string &prefix, EnumDecl *decl,
+	FunctionDecl *fd)
+{
+	DeclContext::decl_iterator i;
+
+	for (i = decl->decls_begin(); i != decl->decls_end(); ++i) {
+		EnumConstantDecl *ecd = dyn_cast<EnumConstantDecl>(*i);
+		int val = (int) ecd->getInitVal().getSExtValue();
+		string name = ecd->getNameAsString();
+		string method_name;
+
+		if (val < 0)
+			continue;
+		method_name = prefix + name.substr(4);
+		c->set_enums[fd].push_back(set_enum(val, name, method_name));
+	}
+}
+
+/* Check if "fd" sets an enum value and, if so, add information
+ * about the enum values to c->set_enums.
+ *
+ * A function is considered to set an enum value if:
+ * - the function returns an object of the same type
+ * - the last argument is of type enum
+ * - the name of the function ends with the name of the enum
+ */
+static bool handled_sets_enum(isl_class *c, FunctionDecl *fd)
+{
+	unsigned n;
+	ParmVarDecl *param;
+	const EnumType *enum_type;
+	EnumDecl *decl;
+	string enum_name;
+	string fd_name;
+	string prefix;
+	size_t pos;
+
+	if (!generator::is_mutator(*c, fd))
+		return false;
+	n = fd->getNumParams();
+	if (n < 2)
+		return false;
+	param = fd->getParamDecl(n - 1);
+	enum_type = param->getType()->getAs<EnumType>();
+	if (!enum_type)
+		return false;
+	decl = enum_type->getDecl();
+	enum_name = decl->getName();
+	enum_name = enum_name.substr(4);
+	fd_name = c->method_name(fd);
+	pos = fd_name.find(enum_name);
+	if (pos == std::string::npos)
+		return false;
+	prefix = fd_name.substr(0, pos);
+
+	add_set_enum(c, prefix, decl, fd);
+
+	return true;
+}
+
+/* Return the callback argument of a function setting
+ * a persistent callback.
+ * This callback is in the second argument (position 1).
+ */
+ParmVarDecl *generator::persistent_callback_arg(FunctionDecl *fd)
+{
+	return fd->getParamDecl(1);
+}
+
+/* Does the given function set a persistent callback?
+ * The following heuristics are used to determine this property:
+ * - the function returns an object of the same type
+ * - its name starts with "set_"
+ * - it has exactly three arguments
+ * - the second (position 1) of which is a callback
+ */
+static bool sets_persistent_callback(isl_class *c, FunctionDecl *fd)
+{
+	ParmVarDecl *param;
+
+	if (!generator::is_mutator(*c, fd))
+		return false;
+	if (fd->getNumParams() != 3)
+		return false;
+	param = generator::persistent_callback_arg(fd);
+	if (!generator::is_callback(param->getType()))
+		return false;
+	return prefixcmp(c->method_name(fd).c_str(),
+			 c->set_callback_prefix) == 0;
+}
+
+/* Sorting function that places declaration of functions
+ * with a shorter name first.
+ */
+static bool less_name(const FunctionDecl *a, const FunctionDecl *b)
+{
+	return a->getName().size() < b->getName().size();
+}
+
 /* Collect all functions that belong to a certain type, separating
- * constructors from regular methods and keeping track of the _to_str,
+ * constructors from methods that set persistent callback and
+ * from regular methods, while keeping track of the _to_str,
  * _copy and _free functions, if any, separately.  If there are any overloaded
  * functions, then they are grouped based on their name after removing the
  * argument type suffix.
+ * Check for functions that describe subclasses before considering
+ * any other functions in order to be able to detect those other
+ * functions as belonging to the subclasses.
+ * Sort the names of the functions based on their lengths
+ * to ensure that nested subclasses are handled later.
  */
 generator::generator(SourceManager &SM, set<RecordDecl *> &exported_types,
 	set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions) :
 	SM(SM)
 {
-	map<string, isl_class>::iterator ci;
-
 	set<FunctionDecl *>::iterator in;
+	set<RecordDecl *>::iterator it;
+	vector<FunctionDecl *> type_subclasses;
+	vector<FunctionDecl *>::iterator iv;
+
 	for (in = functions.begin(); in != functions.end(); ++in) {
 		FunctionDecl *decl = *in;
 		functions_by_name[decl->getName()] = decl;
 	}
 
-	set<RecordDecl *>::iterator it;
-	for (it = exported_types.begin(); it != exported_types.end(); ++it) {
-		RecordDecl *decl = *it;
-		string name = decl->getName();
-		classes[name].name = name;
-		classes[name].type = decl;
-		classes[name].fn_to_str = find_by_name(name + "_to_str", false);
-		classes[name].fn_copy = find_by_name(name + "_copy", true);
-		classes[name].fn_free = find_by_name(name + "_free", true);
+	for (it = exported_types.begin(); it != exported_types.end(); ++it)
+		add_class(*it);
+
+	for (in = exported_functions.begin(); in != exported_functions.end();
+	     ++in) {
+		if (is_subclass(*in))
+			type_subclasses.push_back(*in);
+	}
+	std::sort(type_subclasses.begin(), type_subclasses.end(), &less_name);
+	for (iv = type_subclasses.begin(); iv != type_subclasses.end(); ++iv) {
+		add_type_subclasses(*iv);
 	}
 
 	for (in = exported_functions.begin(); in != exported_functions.end();
 	     ++in) {
 		FunctionDecl *method = *in;
-		isl_class *c = method2class(method);
+		isl_class *c;
 
+		if (is_subclass(method))
+			continue;
+
+		c = method2class(method);
 		if (!c)
 			continue;
 		if (is_constructor(method)) {
 			c->constructors.insert(method);
+		} else if (handled_sets_enum(c, method)) {
+		} else if (sets_persistent_callback(c, method)) {
+			c->persistent_callbacks.insert(method);
 		} else {
-			string fullname = c->name_without_type_suffix(method);
+			string fullname = c->name_without_type_suffixes(method);
 			c->methods[fullname].insert(method);
 		}
 	}
+
+	extract_automatic_conversions();
 }
 
 /* Print error message "msg" and abort.
@@ -145,10 +422,20 @@ void generator::die(string msg)
  * appear in the source.  In particular, the first annotation
  * is the one that is closest to the annotated type and the corresponding
  * type is then also the first that will appear in the sequence of types.
+ * This is also the order in which the annotations appear
+ * in the AttrVec returned by Decl::getAttrs() in older versions of clang.
+ * In newer versions of clang, the order is that in which
+ * the attribute appears in the source.
+ * Use the position of the "isl_export" attribute to determine
+ * whether this is an old (with reversed order) or a new version.
+ * The "isl_export" attribute is automatically added
+ * after each "isl_subclass" attribute.  If it appears in the list before
+ * any "isl_subclass" is encountered, then this must be a reversed list.
  */
-std::vector<string> generator::find_superclasses(RecordDecl *decl)
+std::vector<string> generator::find_superclasses(Decl *decl)
 {
 	vector<string> super;
+	bool reversed = false;
 
 	if (!decl->hasAttrs())
 		return super;
@@ -161,15 +448,27 @@ std::vector<string> generator::find_superclasses(RecordDecl *decl)
 		if (!ann)
 			continue;
 		string s = ann->getAnnotation().str();
+		if (s == "isl_export" && super.size() == 0)
+			reversed = true;
 		if (s.substr(0, len) == sub) {
 			s = s.substr(len + 1, s.length() - len  - 2);
-			super.push_back(s);
+			if (reversed)
+				super.push_back(s);
+			else
+				super.insert(super.begin(), s);
 		}
 	}
 
 	return super;
 }
 
+/* Is "decl" marked as describing subclasses?
+ */
+bool generator::is_subclass(FunctionDecl *decl)
+{
+	return find_superclasses(decl).size() > 0;
+}
+
 /* Is decl marked as being part of an overloaded method?
  */
 bool generator::is_overload(Decl *decl)
@@ -205,7 +504,7 @@ bool generator::gives(Decl *decl)
 	return has_annotation(decl, "isl_give");
 }
 
-/* Return the class that has a name that matches the initial part
+/* Return the class that has a name that best matches the initial part
  * of the name of function "fd" or NULL if no such class could be found.
  */
 isl_class *generator::method2class(FunctionDecl *fd)
@@ -215,7 +514,9 @@ isl_class *generator::method2class(FunctionDecl *fd)
 	string name = fd->getNameAsString();
 
 	for (ci = classes.begin(); ci != classes.end(); ++ci) {
-		if (name.substr(0, ci->first.length()) == ci->first)
+		size_t len = ci->first.length();
+		if (len > best.length() && name.substr(0, len) == ci->first &&
+		    name[len] == '_')
 			best = ci->first;
 	}
 
@@ -232,7 +533,7 @@ isl_class *generator::method2class(FunctionDecl *fd)
 bool generator::is_isl_ctx(QualType type)
 {
 	if (!type->isPointerType())
-		return 0;
+		return false;
 	type = type->getPointeeType();
 	if (type.getAsString() != "isl_ctx")
 		return false;
@@ -346,9 +647,17 @@ bool generator::is_isl_type(QualType type)
 	return false;
 }
 
-/* Is "type" the type isl_bool?
+/* Is "type" one of the integral types with a negative value
+ * indicating an error condition?
  */
-bool generator::is_isl_bool(QualType type)
+bool generator::is_isl_neg_error(QualType type)
+{
+	return is_isl_bool(type) || is_isl_stat(type) || is_isl_size(type);
+}
+
+/* Is "type" the primitive type with the given name?
+ */
+static bool is_isl_primitive(QualType type, const char *name)
 {
 	string s;
 
@@ -356,22 +665,29 @@ bool generator::is_isl_bool(QualType type)
 		return false;
 
 	s = type.getAsString();
-	return s == "isl_bool";
+	return s == name;
+}
+
+/* Is "type" the type isl_bool?
+ */
+bool generator::is_isl_bool(QualType type)
+{
+	return is_isl_primitive(type, "isl_bool");
 }
 
 /* Is "type" the type isl_stat?
  */
 bool generator::is_isl_stat(QualType type)
 {
-	string s;
-
-	if (type->isPointerType())
-		return false;
-
-	s = type.getAsString();
-	return s == "isl_stat";
+	return is_isl_primitive(type, "isl_stat");
 }
 
+/* Is "type" the type isl_size?
+ */
+bool generator::is_isl_size(QualType type)
+{
+	return is_isl_primitive(type, "isl_size");
+}
 
 /* Is "type" that of a pointer to a function?
  */
@@ -403,6 +719,14 @@ bool generator::is_long(QualType type)
 	return builtin && builtin->getKind() == BuiltinType::Long;
 }
 
+/* Is "type" that of "unsigned int"?
+ */
+static bool is_unsigned_int(QualType type)
+{
+	const BuiltinType *builtin = type->getAs<BuiltinType>();
+	return builtin && builtin->getKind() == BuiltinType::UInt;
+}
+
 /* Return the name of the type that "type" points to.
  * The input "type" is assumed to be a pointer type.
  */
@@ -421,30 +745,90 @@ const FunctionProtoType *generator::extract_prototype(QualType type)
 	return type->getPointeeType()->getAs<FunctionProtoType>();
 }
 
-/* If "method" is overloaded, then return its name with the suffix
- * corresponding to the type of the final argument removed.
+/* Return the function name suffix for the type of "param".
+ *
+ * If the type of "param" is an isl object type,
+ * then the suffix is the name of the type with the "isl" prefix removed,
+ * but keeping the "_".
+ * If the type is an unsigned integer, then the type suffix is "_ui".
+ */
+static std::string type_suffix(ParmVarDecl *param)
+{
+	QualType type;
+
+	type = param->getOriginalType();
+	if (generator::is_isl_type(type))
+		return generator::extract_type(type).substr(3);
+	else if (is_unsigned_int(type))
+		return "_ui";
+	generator::die("Unsupported type suffix");
+}
+
+/* If "suffix" is a suffix of "s", then return "s" with the suffix removed.
+ * Otherwise, simply return "s".
+ */
+static std::string drop_suffix(const std::string &s, const std::string &suffix)
+{
+	size_t len, suffix_len;
+
+	len = s.length();
+	suffix_len = suffix.length();
+
+	if (len >= suffix_len && s.substr(len - suffix_len) == suffix)
+		return s.substr(0, len - suffix_len);
+	else
+		return s;
+}
+
+/* If "method" is overloaded, then return its name with the suffixes
+ * corresponding to the types of the final arguments removed.
  * Otherwise, simply return the name of the function.
+ * Start from the final argument and keep removing suffixes
+ * matching arguments, independently of whether previously considered
+ * arguments matched.
  */
-string isl_class::name_without_type_suffix(FunctionDecl *method)
+string isl_class::name_without_type_suffixes(FunctionDecl *method)
 {
 	int num_params;
-	ParmVarDecl *param;
-	string name, type;
-	size_t name_len, type_len;
+	string name;
 
 	name = method->getName();
 	if (!generator::is_overload(method))
 		return name;
 
 	num_params = method->getNumParams();
-	param = method->getParamDecl(num_params - 1);
-	type = generator::extract_type(param->getOriginalType());
-	type = type.substr(4);
-	name_len = name.length();
-	type_len = type.length();
+	for (int i = num_params - 1; i >= 0; --i) {
+		ParmVarDecl *param;
+		string type;
 
-	if (name_len > type_len && name.substr(name_len - type_len) == type)
-		name = name.substr(0, name_len - type_len - 1);
+		param = method->getParamDecl(i);
+		type = type_suffix(param);
+
+		name = drop_suffix(name, type);
+	}
 
 	return name;
 }
+
+/* Is function "fd" with the given name a "get" method?
+ *
+ * A "get" method is an instance method
+ * with a name that starts with the get method prefix.
+ */
+bool isl_class::is_get_method_name(FunctionDecl *fd, const string &name) const
+{
+	return !is_static(fd) && prefixcmp(name.c_str(), get_prefix) == 0;
+}
+
+/* Extract the method name corresponding to "fd".
+ *
+ * If "fd" is a "get" method, then drop the "get" method prefix.
+ */
+string isl_class::method_name(FunctionDecl *fd) const
+{
+      string base = base_method_name(fd);
+
+      if (is_get_method_name(fd, base))
+	      return base.substr(strlen(get_prefix));
+      return base;
+}

diff  --git a/polly/lib/External/isl/interface/generator.h b/polly/lib/External/isl/interface/generator.h
index 2f8d88dbef84..e829f26e56e4 100644
--- a/polly/lib/External/isl/interface/generator.h
+++ b/polly/lib/External/isl/interface/generator.h
@@ -4,39 +4,124 @@
 #include <map>
 #include <set>
 #include <string>
+#include <vector>
 
 #include <clang/AST/Decl.h>
 
 using namespace std;
 using namespace clang;
 
+/* Compare the prefix of "s" to "prefix" up to the length of "prefix".
+ */
+inline int prefixcmp(const char *s, const char *prefix)
+{
+	return strncmp(s, prefix, strlen(prefix));
+}
+
+/* Information about a single enum value of an enum set by a function.
+ * "value" is the enum value.
+ * "name" is the corresponding name.
+ * "method_name" is the the name of the method that sets this value.
+ */
+struct set_enum {
+	int	value;
+	string	name;
+	string	method_name;
+	set_enum(int value, string name, string method_name) :
+		value(value), name(name), method_name(method_name) {}
+};
+
+/* Helper structure for sorting FunctionDecl pointers
+ * on the corresponding function names.
+ */
+struct function_name_less {
+	bool operator()(FunctionDecl *x, FunctionDecl *y) {
+		return x->getName() < y->getName();
+	}
+};
+
+/* Set of FunctionDecl pointers sorted on function name.
+ */
+typedef std::set<FunctionDecl *, function_name_less> function_set;
+
 /* isl_class collects all constructors and methods for an isl "class".
  * "name" is the name of the class.
+ * If this object describes a subclass of a C type, then
+ * "subclass_name" is the name of that subclass and "superclass_name"
+ * is the name of the immediate superclass of that subclass.  Otherwise,
+ * "subclass_name" is equal to "name" and "superclass_name" is undefined.
  * "type" is the declaration that introduces the type.
+ * "persistent_callbacks" contains the set of functions that
+ * set a persistent callback.
+ * "set_enums" maps the set of functions that set an enum value
+ * to information associated to each value.
+ * A function is considered to set an enum value if it returns
+ * an object of the same type and if its last argument is of an enum type.
  * "methods" contains the set of methods, grouped by method name.
  * "fn_to_str" is a reference to the *_to_str method of this class, if any.
  * "fn_copy" is a reference to the *_copy method of this class, if any.
  * "fn_free" is a reference to the *_free method of this class, if any.
+ * "fn_type" is a reference to a function that described subclasses, if any.
+ * If "fn_type" is set, then "type_subclasses" maps the values returned
+ * by that function to the names of the corresponding subclasses.
  */
 struct isl_class {
 	string name;
+	string superclass_name;
+	string subclass_name;
 	RecordDecl *type;
-	set<FunctionDecl *> constructors;
-	map<string, set<FunctionDecl *> > methods;
+	function_set constructors;
+	set<FunctionDecl *> persistent_callbacks;
+	map<FunctionDecl *, vector<set_enum> > set_enums;
+	map<string, function_set> methods;
+	map<int, string> type_subclasses;
+	FunctionDecl *fn_type;
 	FunctionDecl *fn_to_str;
 	FunctionDecl *fn_copy;
 	FunctionDecl *fn_free;
 
-	/* Return name of "fd" without type suffix, if any. */
-	static string name_without_type_suffix(FunctionDecl *fd);
+	/* Does "method" correspond to a static method? */
+	bool is_static(FunctionDecl *method) const;
+	/* Is this class a subclass based on a type function? */
+	bool is_type_subclass() const { return name != subclass_name; }
+	/* Return name of "fd" without type suffixes, if any. */
+	static string name_without_type_suffixes(FunctionDecl *fd);
+	/* Extract the method name corresponding to "fd"
+	 * (including "get" method prefix if any).
+	 */
+	string base_method_name(FunctionDecl *fd) const {
+		string m_name = name_without_type_suffixes(fd);
+		return m_name.substr(subclass_name.length() + 1);
+	}
+	/* The prefix of a "get" method. */
+	static const char *get_prefix;
+	/* Is function "fd" with the given name a "get" method? */
+	bool is_get_method_name(FunctionDecl *fd, const string &name) const;
+	/* Is function "fd" a "get" method? */
+	bool is_get_method(FunctionDecl *fd) const {
+		return is_get_method_name(fd, base_method_name(fd));
+	}
 	/* Extract the method name corresponding to "fd". */
-	string method_name(FunctionDecl *fd) const {
-		string m_name = name_without_type_suffix(fd);
-		return m_name.substr(name.length() + 1);
+	string method_name(FunctionDecl *fd) const;
+	/* The prefix of any method that may set a (persistent) callback. */
+	static const char *set_callback_prefix;
+	/* Given a function that sets a persistent callback,
+	 * return the name of the callback.
+	 */
+	string persistent_callback_name(FunctionDecl *fd) const {
+		return method_name(fd).substr(strlen(set_callback_prefix));
+	}
+	/* Does this class have any functions that set a persistent callback?
+	 */
+	bool has_persistent_callbacks() const {
+		return persistent_callbacks.size() != 0;
 	}
 };
 
 /* Base class for interface generators.
+ *
+ * "conversions" maps the target type of automatic conversion
+ * to the second input argument of the conversion function.
  */
 class generator {
 protected:
@@ -53,13 +138,24 @@ class generator {
 	virtual ~generator() {};
 
 protected:
+	void add_subclass(RecordDecl *decl, const string &name,
+		const string &sub_name);
+	void add_class(RecordDecl *decl);
+	void add_type_subclasses(FunctionDecl *method);
 	isl_class *method2class(FunctionDecl *fd);
 	bool callback_takes_argument(ParmVarDecl *param, int pos);
 	FunctionDecl *find_by_name(const string &name, bool required);
+	std::map<const Type *, ParmVarDecl *> conversions;
+private:
+	static const std::set<std::string> automatic_conversion_functions;
+	void extract_automatic_conversion(FunctionDecl *fd);
+	void extract_class_automatic_conversions(const isl_class &clazz);
+	void extract_automatic_conversions();
 public:
 	static void die(const char *msg) __attribute__((noreturn));
 	static void die(string msg) __attribute__((noreturn));
-	static vector<string> find_superclasses(RecordDecl *decl);
+	static vector<string> find_superclasses(Decl *decl);
+	static bool is_subclass(FunctionDecl *decl);
 	static bool is_overload(Decl *decl);
 	static bool is_constructor(Decl *decl);
 	static bool takes(Decl *decl);
@@ -68,14 +164,18 @@ class generator {
 	static bool is_isl_ctx(QualType type);
 	static bool first_arg_is_isl_ctx(FunctionDecl *fd);
 	static bool is_isl_type(QualType type);
+	static bool is_isl_neg_error(QualType type);
 	static bool is_isl_bool(QualType type);
 	static bool is_isl_stat(QualType type);
+	static bool is_isl_size(QualType type);
 	static bool is_long(QualType type);
 	static bool is_callback(QualType type);
 	static bool is_string(QualType type);
 	static bool is_static(const isl_class &clazz, FunctionDecl *method);
+	static bool is_mutator(const isl_class &clazz, FunctionDecl *fd);
 	static string extract_type(QualType type);
 	static const FunctionProtoType *extract_prototype(QualType type);
+	static ParmVarDecl *persistent_callback_arg(FunctionDecl *fd);
 };
 
 #endif /* ISL_INTERFACE_GENERATOR_H */

diff  --git a/polly/lib/External/isl/interface/isl.py b/polly/lib/External/isl/interface/isl.py
index 11c18b5c523b..f920f7abb088 100644
--- a/polly/lib/External/isl/interface/isl.py
+++ b/polly/lib/External/isl/interface/isl.py
@@ -1,7 +1,16 @@
+isl_dlname='libisl.so.22'
+import os
 from ctypes import *
+from ctypes.util import find_library
 
-isl = cdll.LoadLibrary("libisl.so")
-libc = cdll.LoadLibrary("libc.so.6")
+isl_dyld_library_path = os.environ.get('ISL_DYLD_LIBRARY_PATH')
+if isl_dyld_library_path != None:
+    os.environ['DYLD_LIBRARY_PATH'] =  isl_dyld_library_path
+try:
+    isl = cdll.LoadLibrary(isl_dlname)
+except:
+    isl = cdll.LoadLibrary(find_library("isl"))
+libc = cdll.LoadLibrary(find_library("c"))
 
 class Error(Exception):
     pass
@@ -38,14 +47,14 @@ def __init__(self, *args, **keywords):
             self.ctx = Context.getDefaultInstance()
             self.ptr = isl.isl_union_pw_multi_aff_from_pw_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr))
             return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_pw_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
         if len(args) == 1 and args[0].__class__ is union_pw_aff:
             self.ctx = Context.getDefaultInstance()
             self.ptr = isl.isl_union_pw_multi_aff_from_union_pw_aff(isl.isl_union_pw_aff_copy(args[0].ptr))
             return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_pw_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
@@ -79,7 +88,61 @@ def add(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_union_pw_multi_aff_add(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-        return union_pw_multi_aff(ctx=ctx, ptr=res)
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def as_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_as_pw_multi_aff(isl.isl_union_pw_multi_aff_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_coalesce(isl.isl_union_pw_multi_aff_copy(arg0.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_domain(isl.isl_union_pw_multi_aff_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def empty(*args):
+        if len(args) == 0:
+            ctx = Context.getDefaultInstance()
+            res = isl.isl_union_pw_multi_aff_empty_ctx(ctx)
+            obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def extract_pw_multi_aff(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is space:
+                arg1 = space(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_extract_pw_multi_aff(arg0.ptr, isl.isl_space_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
     def flat_range_product(arg0, arg1):
         try:
             if not arg0.__class__ is union_pw_multi_aff:
@@ -93,11 +156,163 @@ def flat_range_product(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_union_pw_multi_aff_flat_range_product(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-        return union_pw_multi_aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is union_pw_multi_aff:
-            res = isl.isl_union_pw_multi_aff_pullback_union_pw_multi_aff(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-            return union_pw_multi_aff(ctx=arg0.ctx, ptr=res)
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def space(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_gist(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_intersect_domain(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain_wrapped_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_intersect_domain_wrapped_domain(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain_wrapped_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_intersect_domain_wrapped_range(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_intersect_params(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def isa_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_isa_pw_multi_aff(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_pw_multi_aff_pullback_union_pw_multi_aff(isl.isl_union_pw_multi_aff_copy(args[0].ptr), isl.isl_union_pw_multi_aff_copy(args[1].ptr))
+            obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def range_factor_domain(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_range_factor_domain(isl.isl_union_pw_multi_aff_copy(arg0.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def range_factor_range(arg0):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_range_factor_range(isl.isl_union_pw_multi_aff_copy(arg0.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def sub(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_pw_multi_aff:
+                arg1 = union_pw_multi_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_sub(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def subtract_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_multi_aff:
+                arg0 = union_pw_multi_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_multi_aff_subtract_domain(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
     def union_add(arg0, arg1):
         try:
             if not arg0.__class__ is union_pw_multi_aff:
@@ -111,20 +326,52 @@ def union_add(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_union_pw_multi_aff_union_add(isl.isl_union_pw_multi_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-        return union_pw_multi_aff(ctx=ctx, ptr=res)
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
 
 isl.isl_union_pw_multi_aff_from_pw_multi_aff.restype = c_void_p
 isl.isl_union_pw_multi_aff_from_pw_multi_aff.argtypes = [c_void_p]
-isl.isl_union_pw_multi_aff_read_from_str.restype = c_void_p
-isl.isl_union_pw_multi_aff_read_from_str.argtypes = [Context, c_char_p]
 isl.isl_union_pw_multi_aff_from_union_pw_aff.restype = c_void_p
 isl.isl_union_pw_multi_aff_from_union_pw_aff.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_read_from_str.restype = c_void_p
+isl.isl_union_pw_multi_aff_read_from_str.argtypes = [Context, c_char_p]
 isl.isl_union_pw_multi_aff_add.restype = c_void_p
 isl.isl_union_pw_multi_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_as_pw_multi_aff.restype = c_void_p
+isl.isl_union_pw_multi_aff_as_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_coalesce.restype = c_void_p
+isl.isl_union_pw_multi_aff_coalesce.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_domain.restype = c_void_p
+isl.isl_union_pw_multi_aff_domain.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_empty_ctx.restype = c_void_p
+isl.isl_union_pw_multi_aff_empty_ctx.argtypes = [Context]
+isl.isl_union_pw_multi_aff_extract_pw_multi_aff.restype = c_void_p
+isl.isl_union_pw_multi_aff_extract_pw_multi_aff.argtypes = [c_void_p, c_void_p]
 isl.isl_union_pw_multi_aff_flat_range_product.restype = c_void_p
 isl.isl_union_pw_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_get_space.restype = c_void_p
+isl.isl_union_pw_multi_aff_get_space.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_gist.restype = c_void_p
+isl.isl_union_pw_multi_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_intersect_domain.restype = c_void_p
+isl.isl_union_pw_multi_aff_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_intersect_domain_wrapped_domain.restype = c_void_p
+isl.isl_union_pw_multi_aff_intersect_domain_wrapped_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_intersect_domain_wrapped_range.restype = c_void_p
+isl.isl_union_pw_multi_aff_intersect_domain_wrapped_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_intersect_params.restype = c_void_p
+isl.isl_union_pw_multi_aff_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_isa_pw_multi_aff.argtypes = [c_void_p]
 isl.isl_union_pw_multi_aff_pullback_union_pw_multi_aff.restype = c_void_p
 isl.isl_union_pw_multi_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_range_factor_domain.restype = c_void_p
+isl.isl_union_pw_multi_aff_range_factor_domain.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_range_factor_range.restype = c_void_p
+isl.isl_union_pw_multi_aff_range_factor_range.argtypes = [c_void_p]
+isl.isl_union_pw_multi_aff_sub.restype = c_void_p
+isl.isl_union_pw_multi_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_multi_aff_subtract_domain.restype = c_void_p
+isl.isl_union_pw_multi_aff_subtract_domain.argtypes = [c_void_p, c_void_p]
 isl.isl_union_pw_multi_aff_union_add.restype = c_void_p
 isl.isl_union_pw_multi_aff_union_add.argtypes = [c_void_p, c_void_p]
 isl.isl_union_pw_multi_aff_copy.restype = c_void_p
@@ -140,13 +387,17 @@ def __init__(self, *args, **keywords):
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
+        if len(args) == 1 and args[0].__class__ is multi_pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_union_pw_aff_from_multi_pw_aff(isl.isl_multi_pw_aff_copy(args[0].ptr))
+            return
         if len(args) == 1 and args[0].__class__ is union_pw_aff:
             self.ctx = Context.getDefaultInstance()
             self.ptr = isl.isl_multi_union_pw_aff_from_union_pw_aff(isl.isl_union_pw_aff_copy(args[0].ptr))
             return
-        if len(args) == 1 and args[0].__class__ is multi_pw_aff:
+        if len(args) == 2 and args[0].__class__ is space and args[1].__class__ is union_pw_aff_list:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_multi_union_pw_aff_from_multi_pw_aff(isl.isl_multi_pw_aff_copy(args[0].ptr))
+            self.ptr = isl.isl_multi_union_pw_aff_from_union_pw_aff_list(isl.isl_space_copy(args[0].ptr), isl.isl_union_pw_aff_list_copy(args[1].ptr))
             return
         if len(args) == 1 and type(args[0]) == str:
             self.ctx = Context.getDefaultInstance()
@@ -185,40 +436,44 @@ def add(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_multi_union_pw_aff_add(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
-        return multi_union_pw_aff(ctx=ctx, ptr=res)
-    def flat_range_product(arg0, arg1):
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def bind(arg0, arg1):
         try:
             if not arg0.__class__ is multi_union_pw_aff:
                 arg0 = multi_union_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is multi_union_pw_aff:
-                arg1 = multi_union_pw_aff(arg1)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_multi_union_pw_aff_flat_range_product(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
-        return multi_union_pw_aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is union_pw_multi_aff:
-            res = isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-            return multi_union_pw_aff(ctx=arg0.ctx, ptr=res)
-    def range_product(arg0, arg1):
+        res = isl.isl_multi_union_pw_aff_bind(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
         try:
             if not arg0.__class__ is multi_union_pw_aff:
                 arg0 = multi_union_pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_coalesce(isl.isl_multi_union_pw_aff_copy(arg0.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
         try:
-            if not arg1.__class__ is multi_union_pw_aff:
-                arg1 = multi_union_pw_aff(arg1)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_multi_union_pw_aff_range_product(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
-        return multi_union_pw_aff(ctx=ctx, ptr=res)
-    def union_add(arg0, arg1):
+        res = isl.isl_multi_union_pw_aff_domain(isl.isl_multi_union_pw_aff_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def flat_range_product(arg0, arg1):
         try:
             if not arg0.__class__ is multi_union_pw_aff:
                 arg0 = multi_union_pw_aff(arg0)
@@ -230,2098 +485,2618 @@ def union_add(arg0, arg1):
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_multi_union_pw_aff_union_add(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
-        return multi_union_pw_aff(ctx=ctx, ptr=res)
-
-isl.isl_multi_union_pw_aff_from_union_pw_aff.restype = c_void_p
-isl.isl_multi_union_pw_aff_from_union_pw_aff.argtypes = [c_void_p]
-isl.isl_multi_union_pw_aff_from_multi_pw_aff.restype = c_void_p
-isl.isl_multi_union_pw_aff_from_multi_pw_aff.argtypes = [c_void_p]
-isl.isl_multi_union_pw_aff_read_from_str.restype = c_void_p
-isl.isl_multi_union_pw_aff_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_multi_union_pw_aff_add.restype = c_void_p
-isl.isl_multi_union_pw_aff_add.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_union_pw_aff_flat_range_product.restype = c_void_p
-isl.isl_multi_union_pw_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff.restype = c_void_p
-isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_union_pw_aff_range_product.restype = c_void_p
-isl.isl_multi_union_pw_aff_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_union_pw_aff_union_add.restype = c_void_p
-isl.isl_multi_union_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_union_pw_aff_copy.restype = c_void_p
-isl.isl_multi_union_pw_aff_copy.argtypes = [c_void_p]
-isl.isl_multi_union_pw_aff_free.restype = c_void_p
-isl.isl_multi_union_pw_aff_free.argtypes = [c_void_p]
-isl.isl_multi_union_pw_aff_to_str.restype = POINTER(c_char)
-isl.isl_multi_union_pw_aff_to_str.argtypes = [c_void_p]
-
-class union_pw_aff(union_pw_multi_aff, multi_union_pw_aff):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        if len(args) == 1 and args[0].__class__ is pw_aff:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_pw_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
-            return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_union_pw_aff_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_multi_union_pw_aff_flat_range_product(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is union_pw_aff:
-                arg0 = union_pw_aff(arg0)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
             raise
-        ptr = isl.isl_union_pw_aff_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.union_pw_aff("""%s""")' % s
-        else:
-            return 'isl.union_pw_aff("%s")' % s
-    def add(arg0, arg1):
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_get_at(arg0.ptr, arg1)
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def space(arg0):
         try:
-            if not arg0.__class__ is union_pw_aff:
-                arg0 = union_pw_aff(arg0)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is union_pw_aff:
-                arg1 = union_pw_aff(arg1)
-        except:
-            return union_pw_multi_aff(arg0).add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_pw_aff_add(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
-        return union_pw_aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is union_pw_multi_aff:
-            res = isl.isl_union_pw_aff_pullback_union_pw_multi_aff(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-            return union_pw_aff(ctx=arg0.ctx, ptr=res)
-    def union_add(arg0, arg1):
+        res = isl.isl_multi_union_pw_aff_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
         try:
-            if not arg0.__class__ is union_pw_aff:
-                arg0 = union_pw_aff(arg0)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_pw_aff:
-                arg1 = union_pw_aff(arg1)
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
-            return union_pw_multi_aff(arg0).union_add(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_union_pw_aff_union_add(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
-        return union_pw_aff(ctx=ctx, ptr=res)
-
-isl.isl_union_pw_aff_from_pw_aff.restype = c_void_p
-isl.isl_union_pw_aff_from_pw_aff.argtypes = [c_void_p]
-isl.isl_union_pw_aff_read_from_str.restype = c_void_p
-isl.isl_union_pw_aff_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_union_pw_aff_add.restype = c_void_p
-isl.isl_union_pw_aff_add.argtypes = [c_void_p, c_void_p]
-isl.isl_union_pw_aff_pullback_union_pw_multi_aff.restype = c_void_p
-isl.isl_union_pw_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_union_pw_aff_union_add.restype = c_void_p
-isl.isl_union_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
-isl.isl_union_pw_aff_copy.restype = c_void_p
-isl.isl_union_pw_aff_copy.argtypes = [c_void_p]
-isl.isl_union_pw_aff_free.restype = c_void_p
-isl.isl_union_pw_aff_free.argtypes = [c_void_p]
-isl.isl_union_pw_aff_to_str.restype = POINTER(c_char)
-isl.isl_union_pw_aff_to_str.argtypes = [c_void_p]
-
-class multi_pw_aff(multi_union_pw_aff):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        if len(args) == 1 and args[0].__class__ is multi_aff:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_multi_pw_aff_from_multi_aff(isl.isl_multi_aff_copy(args[0].ptr))
-            return
-        if len(args) == 1 and args[0].__class__ is pw_aff:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_multi_pw_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
-            return
-        if len(args) == 1 and args[0].__class__ is pw_multi_aff:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_multi_pw_aff_from_pw_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr))
-            return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_multi_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_multi_pw_aff_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_multi_union_pw_aff_gist(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_pw_aff:
-                arg0 = multi_pw_aff(arg0)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
             raise
-        ptr = isl.isl_multi_pw_aff_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.multi_pw_aff("""%s""")' % s
-        else:
-            return 'isl.multi_pw_aff("%s")' % s
-    def add(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_pw_aff:
-                arg0 = multi_pw_aff(arg0)
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_intersect_domain(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
         try:
-            if not arg1.__class__ is multi_pw_aff:
-                arg1 = multi_pw_aff(arg1)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
-            return multi_union_pw_aff(arg0).add(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_multi_pw_aff_add(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
-        return multi_pw_aff(ctx=ctx, ptr=res)
-    def flat_range_product(arg0, arg1):
+            raise
         try:
-            if not arg0.__class__ is multi_pw_aff:
-                arg0 = multi_pw_aff(arg0)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_intersect_params(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def neg(arg0):
         try:
-            if not arg1.__class__ is multi_pw_aff:
-                arg1 = multi_pw_aff(arg1)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
-            return multi_union_pw_aff(arg0).flat_range_product(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_multi_pw_aff_flat_range_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
-        return multi_pw_aff(ctx=ctx, ptr=res)
-    def product(arg0, arg1):
+        res = isl.isl_multi_union_pw_aff_neg(isl.isl_multi_union_pw_aff_copy(arg0.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def plain_is_equal(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_pw_aff:
-                arg0 = multi_pw_aff(arg0)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is multi_pw_aff:
-                arg1 = multi_pw_aff(arg1)
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
         except:
-            return multi_union_pw_aff(arg0).product(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_multi_pw_aff_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
-        return multi_pw_aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is multi_aff:
-            res = isl.isl_multi_pw_aff_pullback_multi_aff(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-            return multi_pw_aff(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is pw_multi_aff:
-            res = isl.isl_multi_pw_aff_pullback_pw_multi_aff(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-            return multi_pw_aff(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is multi_pw_aff:
-            res = isl.isl_multi_pw_aff_pullback_multi_pw_aff(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
-            return multi_pw_aff(ctx=arg0.ctx, ptr=res)
+        res = isl.isl_multi_union_pw_aff_plain_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff(isl.isl_multi_union_pw_aff_copy(args[0].ptr), isl.isl_union_pw_multi_aff_copy(args[1].ptr))
+            obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
     def range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_pw_aff:
-                arg0 = multi_pw_aff(arg0)
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is multi_pw_aff:
-                arg1 = multi_pw_aff(arg1)
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
         except:
-            return multi_union_pw_aff(arg0).range_product(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_multi_pw_aff_range_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
-        return multi_pw_aff(ctx=ctx, ptr=res)
+        res = isl.isl_multi_union_pw_aff_range_product(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def scale(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_union_pw_aff_scale_multi_val(isl.isl_multi_union_pw_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_union_pw_aff_scale_val(isl.isl_multi_union_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale_down(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_union_pw_aff_scale_down_multi_val(isl.isl_multi_union_pw_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_union_pw_aff_scale_down_val(isl.isl_multi_union_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def set_at(arg0, arg1, arg2):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg2.__class__ is union_pw_aff:
+                arg2 = union_pw_aff(arg2)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_set_at(isl.isl_multi_union_pw_aff_copy(arg0.ptr), arg1, isl.isl_union_pw_aff_copy(arg2.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def size(arg0):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def sub(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_sub(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def union_add(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_union_pw_aff:
+                arg0 = multi_union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_union_add(isl.isl_multi_union_pw_aff_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def zero(arg0):
+        try:
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_union_pw_aff_zero(isl.isl_space_copy(arg0.ptr))
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
 
-isl.isl_multi_pw_aff_from_multi_aff.restype = c_void_p
-isl.isl_multi_pw_aff_from_multi_aff.argtypes = [c_void_p]
-isl.isl_multi_pw_aff_from_pw_aff.restype = c_void_p
-isl.isl_multi_pw_aff_from_pw_aff.argtypes = [c_void_p]
-isl.isl_multi_pw_aff_from_pw_multi_aff.restype = c_void_p
-isl.isl_multi_pw_aff_from_pw_multi_aff.argtypes = [c_void_p]
-isl.isl_multi_pw_aff_read_from_str.restype = c_void_p
-isl.isl_multi_pw_aff_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_multi_pw_aff_add.restype = c_void_p
-isl.isl_multi_pw_aff_add.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_pw_aff_flat_range_product.restype = c_void_p
-isl.isl_multi_pw_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_pw_aff_product.restype = c_void_p
-isl.isl_multi_pw_aff_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_pw_aff_pullback_multi_aff.restype = c_void_p
-isl.isl_multi_pw_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_pw_aff_pullback_pw_multi_aff.restype = c_void_p
-isl.isl_multi_pw_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_pw_aff_pullback_multi_pw_aff.restype = c_void_p
-isl.isl_multi_pw_aff_pullback_multi_pw_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_pw_aff_range_product.restype = c_void_p
-isl.isl_multi_pw_aff_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_pw_aff_copy.restype = c_void_p
-isl.isl_multi_pw_aff_copy.argtypes = [c_void_p]
-isl.isl_multi_pw_aff_free.restype = c_void_p
-isl.isl_multi_pw_aff_free.argtypes = [c_void_p]
-isl.isl_multi_pw_aff_to_str.restype = POINTER(c_char)
-isl.isl_multi_pw_aff_to_str.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_from_multi_pw_aff.restype = c_void_p
+isl.isl_multi_union_pw_aff_from_multi_pw_aff.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_from_union_pw_aff.restype = c_void_p
+isl.isl_multi_union_pw_aff_from_union_pw_aff.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_from_union_pw_aff_list.restype = c_void_p
+isl.isl_multi_union_pw_aff_from_union_pw_aff_list.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_read_from_str.restype = c_void_p
+isl.isl_multi_union_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_union_pw_aff_add.restype = c_void_p
+isl.isl_multi_union_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_bind.restype = c_void_p
+isl.isl_multi_union_pw_aff_bind.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_coalesce.restype = c_void_p
+isl.isl_multi_union_pw_aff_coalesce.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_domain.restype = c_void_p
+isl.isl_multi_union_pw_aff_domain.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_flat_range_product.restype = c_void_p
+isl.isl_multi_union_pw_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_get_at.restype = c_void_p
+isl.isl_multi_union_pw_aff_get_at.argtypes = [c_void_p, c_int]
+isl.isl_multi_union_pw_aff_get_space.restype = c_void_p
+isl.isl_multi_union_pw_aff_get_space.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_gist.restype = c_void_p
+isl.isl_multi_union_pw_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_intersect_domain.restype = c_void_p
+isl.isl_multi_union_pw_aff_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_intersect_params.restype = c_void_p
+isl.isl_multi_union_pw_aff_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_neg.restype = c_void_p
+isl.isl_multi_union_pw_aff_neg.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_plain_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff.restype = c_void_p
+isl.isl_multi_union_pw_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_range_product.restype = c_void_p
+isl.isl_multi_union_pw_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_scale_multi_val.restype = c_void_p
+isl.isl_multi_union_pw_aff_scale_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_scale_val.restype = c_void_p
+isl.isl_multi_union_pw_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_scale_down_multi_val.restype = c_void_p
+isl.isl_multi_union_pw_aff_scale_down_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_scale_down_val.restype = c_void_p
+isl.isl_multi_union_pw_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_set_at.restype = c_void_p
+isl.isl_multi_union_pw_aff_set_at.argtypes = [c_void_p, c_int, c_void_p]
+isl.isl_multi_union_pw_aff_size.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_sub.restype = c_void_p
+isl.isl_multi_union_pw_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_union_add.restype = c_void_p
+isl.isl_multi_union_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_union_pw_aff_zero.restype = c_void_p
+isl.isl_multi_union_pw_aff_zero.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_copy.restype = c_void_p
+isl.isl_multi_union_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_free.restype = c_void_p
+isl.isl_multi_union_pw_aff_free.argtypes = [c_void_p]
+isl.isl_multi_union_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_multi_union_pw_aff_to_str.argtypes = [c_void_p]
 
-class pw_multi_aff(union_pw_multi_aff, multi_pw_aff):
+class union_pw_aff(union_pw_multi_aff, multi_union_pw_aff):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and args[0].__class__ is multi_aff:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_pw_multi_aff_from_multi_aff(isl.isl_multi_aff_copy(args[0].ptr))
-            return
         if len(args) == 1 and args[0].__class__ is pw_aff:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_pw_multi_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
+            self.ptr = isl.isl_union_pw_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
             return
         if len(args) == 1 and type(args[0]) == str:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_pw_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            self.ptr = isl.isl_union_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
             return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_pw_multi_aff_free(self.ptr)
+            isl.isl_union_pw_aff_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is pw_multi_aff:
-                arg0 = pw_multi_aff(arg0)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
             raise
-        ptr = isl.isl_pw_multi_aff_to_str(arg0.ptr)
+        ptr = isl.isl_union_pw_aff_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.pw_multi_aff("""%s""")' % s
+            return 'isl.union_pw_aff("""%s""")' % s
         else:
-            return 'isl.pw_multi_aff("%s")' % s
+            return 'isl.union_pw_aff("%s")' % s
     def add(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_multi_aff:
-                arg0 = pw_multi_aff(arg0)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_multi_aff:
-                arg1 = pw_multi_aff(arg1)
+            if not arg1.__class__ is union_pw_aff:
+                arg1 = union_pw_aff(arg1)
         except:
             return union_pw_multi_aff(arg0).add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_multi_aff_add(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-        return pw_multi_aff(ctx=ctx, ptr=res)
-    def flat_range_product(arg0, arg1):
+        res = isl.isl_union_pw_aff_add(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def bind(*args):
+        if len(args) == 2 and (args[1].__class__ is id or type(args[1]) == str):
+            args = list(args)
+            try:
+                if not args[1].__class__ is id:
+                    args[1] = id(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_union_pw_aff_bind_id(isl.isl_union_pw_aff_copy(args[0].ptr), isl.isl_id_copy(args[1].ptr))
+            obj = union_set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def coalesce(arg0):
         try:
-            if not arg0.__class__ is pw_multi_aff:
-                arg0 = pw_multi_aff(arg0)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_coalesce(isl.isl_union_pw_aff_copy(arg0.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
         try:
-            if not arg1.__class__ is pw_multi_aff:
-                arg1 = pw_multi_aff(arg1)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
-            return union_pw_multi_aff(arg0).flat_range_product(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_pw_multi_aff_flat_range_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-        return pw_multi_aff(ctx=ctx, ptr=res)
-    def product(arg0, arg1):
+        res = isl.isl_union_pw_aff_domain(isl.isl_union_pw_aff_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def space(arg0):
         try:
-            if not arg0.__class__ is pw_multi_aff:
-                arg0 = pw_multi_aff(arg0)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
         try:
-            if not arg1.__class__ is pw_multi_aff:
-                arg1 = pw_multi_aff(arg1)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
-            return union_pw_multi_aff(arg0).product(arg1)
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            return union_pw_multi_aff(arg0).gist(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_multi_aff_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-        return pw_multi_aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is multi_aff:
-            res = isl.isl_pw_multi_aff_pullback_multi_aff(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-            return pw_multi_aff(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is pw_multi_aff:
-            res = isl.isl_pw_multi_aff_pullback_pw_multi_aff(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-            return pw_multi_aff(ctx=arg0.ctx, ptr=res)
-    def range_product(arg0, arg1):
+        res = isl.isl_union_pw_aff_gist(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_multi_aff:
-                arg0 = pw_multi_aff(arg0)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_multi_aff:
-                arg1 = pw_multi_aff(arg1)
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
-            return union_pw_multi_aff(arg0).range_product(arg1)
+            return union_pw_multi_aff(arg0).intersect_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_multi_aff_range_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-        return pw_multi_aff(ctx=ctx, ptr=res)
+        res = isl.isl_union_pw_aff_intersect_domain(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain_wrapped_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            return union_pw_multi_aff(arg0).intersect_domain_wrapped_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_intersect_domain_wrapped_domain(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain_wrapped_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            return union_pw_multi_aff(arg0).intersect_domain_wrapped_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_intersect_domain_wrapped_range(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_pw_multi_aff(arg0).intersect_params(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_intersect_params(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_pw_aff_pullback_union_pw_multi_aff(isl.isl_union_pw_aff_copy(args[0].ptr), isl.isl_union_pw_multi_aff_copy(args[1].ptr))
+            obj = union_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def sub(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_pw_aff:
+                arg1 = union_pw_aff(arg1)
+        except:
+            return union_pw_multi_aff(arg0).sub(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_sub(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def subtract_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            return union_pw_multi_aff(arg0).subtract_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_subtract_domain(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
     def union_add(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_multi_aff:
-                arg0 = pw_multi_aff(arg0)
+            if not arg0.__class__ is union_pw_aff:
+                arg0 = union_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_multi_aff:
-                arg1 = pw_multi_aff(arg1)
+            if not arg1.__class__ is union_pw_aff:
+                arg1 = union_pw_aff(arg1)
         except:
             return union_pw_multi_aff(arg0).union_add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_multi_aff_union_add(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-        return pw_multi_aff(ctx=ctx, ptr=res)
+        res = isl.isl_union_pw_aff_union_add(isl.isl_union_pw_aff_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
 
-isl.isl_pw_multi_aff_from_multi_aff.restype = c_void_p
-isl.isl_pw_multi_aff_from_multi_aff.argtypes = [c_void_p]
-isl.isl_pw_multi_aff_from_pw_aff.restype = c_void_p
-isl.isl_pw_multi_aff_from_pw_aff.argtypes = [c_void_p]
-isl.isl_pw_multi_aff_read_from_str.restype = c_void_p
-isl.isl_pw_multi_aff_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_pw_multi_aff_add.restype = c_void_p
-isl.isl_pw_multi_aff_add.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_multi_aff_flat_range_product.restype = c_void_p
-isl.isl_pw_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_multi_aff_product.restype = c_void_p
-isl.isl_pw_multi_aff_product.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_multi_aff_pullback_multi_aff.restype = c_void_p
-isl.isl_pw_multi_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_multi_aff_pullback_pw_multi_aff.restype = c_void_p
-isl.isl_pw_multi_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_multi_aff_range_product.restype = c_void_p
-isl.isl_pw_multi_aff_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_multi_aff_union_add.restype = c_void_p
-isl.isl_pw_multi_aff_union_add.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_multi_aff_copy.restype = c_void_p
-isl.isl_pw_multi_aff_copy.argtypes = [c_void_p]
-isl.isl_pw_multi_aff_free.restype = c_void_p
-isl.isl_pw_multi_aff_free.argtypes = [c_void_p]
-isl.isl_pw_multi_aff_to_str.restype = POINTER(c_char)
-isl.isl_pw_multi_aff_to_str.argtypes = [c_void_p]
+isl.isl_union_pw_aff_from_pw_aff.restype = c_void_p
+isl.isl_union_pw_aff_from_pw_aff.argtypes = [c_void_p]
+isl.isl_union_pw_aff_read_from_str.restype = c_void_p
+isl.isl_union_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_union_pw_aff_add.restype = c_void_p
+isl.isl_union_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_bind_id.restype = c_void_p
+isl.isl_union_pw_aff_bind_id.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_coalesce.restype = c_void_p
+isl.isl_union_pw_aff_coalesce.argtypes = [c_void_p]
+isl.isl_union_pw_aff_domain.restype = c_void_p
+isl.isl_union_pw_aff_domain.argtypes = [c_void_p]
+isl.isl_union_pw_aff_get_space.restype = c_void_p
+isl.isl_union_pw_aff_get_space.argtypes = [c_void_p]
+isl.isl_union_pw_aff_gist.restype = c_void_p
+isl.isl_union_pw_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_intersect_domain.restype = c_void_p
+isl.isl_union_pw_aff_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_intersect_domain_wrapped_domain.restype = c_void_p
+isl.isl_union_pw_aff_intersect_domain_wrapped_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_intersect_domain_wrapped_range.restype = c_void_p
+isl.isl_union_pw_aff_intersect_domain_wrapped_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_intersect_params.restype = c_void_p
+isl.isl_union_pw_aff_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_pullback_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_pw_aff_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_sub.restype = c_void_p
+isl.isl_union_pw_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_subtract_domain.restype = c_void_p
+isl.isl_union_pw_aff_subtract_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_union_add.restype = c_void_p
+isl.isl_union_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_copy.restype = c_void_p
+isl.isl_union_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_union_pw_aff_free.restype = c_void_p
+isl.isl_union_pw_aff_free.argtypes = [c_void_p]
+isl.isl_union_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_union_pw_aff_to_str.argtypes = [c_void_p]
 
-class pw_aff(union_pw_aff, pw_multi_aff, multi_pw_aff):
+class multi_pw_aff(multi_union_pw_aff):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and args[0].__class__ is aff:
+        if len(args) == 1 and args[0].__class__ is multi_aff:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_pw_aff_from_aff(isl.isl_aff_copy(args[0].ptr))
+            self.ptr = isl.isl_multi_pw_aff_from_multi_aff(isl.isl_multi_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_pw_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
+            return
+        if len(args) == 2 and args[0].__class__ is space and args[1].__class__ is pw_aff_list:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_pw_aff_from_pw_aff_list(isl.isl_space_copy(args[0].ptr), isl.isl_pw_aff_list_copy(args[1].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is pw_multi_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_pw_aff_from_pw_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr))
             return
         if len(args) == 1 and type(args[0]) == str:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            self.ptr = isl.isl_multi_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
             return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_pw_aff_free(self.ptr)
+            isl.isl_multi_pw_aff_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
-        ptr = isl.isl_pw_aff_to_str(arg0.ptr)
+        ptr = isl.isl_multi_pw_aff_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.pw_aff("""%s""")' % s
+            return 'isl.multi_pw_aff("""%s""")' % s
         else:
-            return 'isl.pw_aff("%s")' % s
+            return 'isl.multi_pw_aff("%s")' % s
     def add(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
         except:
-            return union_pw_aff(arg0).add(arg1)
+            return multi_union_pw_aff(arg0).add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_add(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def ceil(arg0):
+        res = isl.isl_multi_pw_aff_add(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def add_constant(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_add_constant_multi_val(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_add_constant_val(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def bind(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_pw_aff_ceil(isl.isl_pw_aff_copy(arg0.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def cond(arg0, arg1, arg2):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
-            raise
+            return multi_union_pw_aff(arg0).bind(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_bind(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain(arg0, arg1):
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
-            return union_pw_aff(arg0).cond(arg1, arg2)
+            raise
         try:
-            if not arg2.__class__ is pw_aff:
-                arg2 = pw_aff(arg2)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
-            return union_pw_aff(arg0).cond(arg1, arg2)
+            return multi_union_pw_aff(arg0).bind_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_cond(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr), isl.isl_pw_aff_copy(arg2.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def div(arg0, arg1):
+        res = isl.isl_multi_pw_aff_bind_domain(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain_wrapped_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
-            return union_pw_aff(arg0).div(arg1)
+            return multi_union_pw_aff(arg0).bind_domain_wrapped_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_div(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def eq_set(arg0, arg1):
+        res = isl.isl_multi_pw_aff_bind_domain_wrapped_domain(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
-        except:
-            return union_pw_aff(arg0).eq_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_eq_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def floor(arg0):
+        res = isl.isl_multi_pw_aff_coalesce(isl.isl_multi_pw_aff_copy(arg0.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_floor(isl.isl_pw_aff_copy(arg0.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def ge_set(arg0, arg1):
+        res = isl.isl_multi_pw_aff_domain(isl.isl_multi_pw_aff_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def flat_range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
         except:
-            return union_pw_aff(arg0).ge_set(arg1)
+            return multi_union_pw_aff(arg0).flat_range_product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_ge_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def gt_set(arg0, arg1):
+        res = isl.isl_multi_pw_aff_flat_range_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_get_at(arg0.ptr, arg1)
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def space(arg0):
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
-            return union_pw_aff(arg0).gt_set(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_gt_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def le_set(arg0, arg1):
+        res = isl.isl_multi_pw_aff_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            return union_pw_aff(arg0).le_set(arg1)
+            return multi_union_pw_aff(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_gist(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def identity(*args):
+        if len(args) == 1:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_identity_multi_pw_aff(isl.isl_multi_pw_aff_copy(args[0].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    @staticmethod
+    def identity_on_domain(*args):
+        if len(args) == 1 and args[0].__class__ is space:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_identity_on_domain_space(isl.isl_space_copy(args[0].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return multi_union_pw_aff(arg0).intersect_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_le_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def lt_set(arg0, arg1):
+        res = isl.isl_multi_pw_aff_intersect_domain(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            return union_pw_aff(arg0).lt_set(arg1)
+            return multi_union_pw_aff(arg0).intersect_params(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_lt_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def max(arg0, arg1):
+        res = isl.isl_multi_pw_aff_intersect_params(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def involves_param(*args):
+        if len(args) == 2 and (args[1].__class__ is id or type(args[1]) == str):
+            args = list(args)
+            try:
+                if not args[1].__class__ is id:
+                    args[1] = id(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_involves_param_id(args[0].ptr, args[1].ptr)
+            if res < 0:
+                raise
+            return bool(res)
+        if len(args) == 2 and args[1].__class__ is id_list:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_involves_param_id_list(args[0].ptr, args[1].ptr)
+            if res < 0:
+                raise
+            return bool(res)
+        raise Error
+    def neg(arg0):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_neg(isl.isl_multi_pw_aff_copy(arg0.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def plain_is_equal(arg0, arg1):
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
-            return union_pw_aff(arg0).max(arg1)
+            raise
+        try:
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
+        except:
+            return multi_union_pw_aff(arg0).plain_is_equal(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_max(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def min(arg0, arg1):
+        res = isl.isl_multi_pw_aff_plain_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def product(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
         except:
-            return union_pw_aff(arg0).min(arg1)
+            return multi_union_pw_aff(arg0).product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_min(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def mod(arg0, arg1):
-        if arg1.__class__ is val:
-            res = isl.isl_pw_aff_mod_val(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-            return pw_aff(ctx=arg0.ctx, ptr=res)
-    def mul(arg0, arg1):
+        res = isl.isl_multi_pw_aff_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_pullback_multi_aff(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_pullback_multi_pw_aff(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_pullback_pw_multi_aff(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
         except:
-            return union_pw_aff(arg0).mul(arg1)
+            return multi_union_pw_aff(arg0).range_product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_mul(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def ne_set(arg0, arg1):
+        res = isl.isl_multi_pw_aff_range_product(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def scale(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_scale_multi_val(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_scale_val(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale_down(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_scale_down_multi_val(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_pw_aff_scale_down_val(isl.isl_multi_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def set_at(arg0, arg1, arg2):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg2.__class__ is pw_aff:
+                arg2 = pw_aff(arg2)
         except:
-            return union_pw_aff(arg0).ne_set(arg1)
+            return multi_union_pw_aff(arg0).set_at(arg1, arg2)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_ne_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def neg(arg0):
+        res = isl.isl_multi_pw_aff_set_at(isl.isl_multi_pw_aff_copy(arg0.ptr), arg1, isl.isl_pw_aff_copy(arg2.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def size(arg0):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_neg(isl.isl_pw_aff_copy(arg0.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is multi_aff:
-            res = isl.isl_pw_aff_pullback_multi_aff(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-            return pw_aff(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is pw_multi_aff:
-            res = isl.isl_pw_aff_pullback_pw_multi_aff(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-            return pw_aff(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is multi_pw_aff:
-            res = isl.isl_pw_aff_pullback_multi_pw_aff(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
-            return pw_aff(ctx=arg0.ctx, ptr=res)
-    def scale(arg0, arg1):
-        if arg1.__class__ is val:
-            res = isl.isl_pw_aff_scale_val(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-            return pw_aff(ctx=arg0.ctx, ptr=res)
-    def scale_down(arg0, arg1):
-        if arg1.__class__ is val:
-            res = isl.isl_pw_aff_scale_down_val(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-            return pw_aff(ctx=arg0.ctx, ptr=res)
+        res = isl.isl_multi_pw_aff_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
     def sub(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is multi_pw_aff:
+                arg0 = multi_pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is multi_pw_aff:
+                arg1 = multi_pw_aff(arg1)
         except:
-            return union_pw_aff(arg0).sub(arg1)
+            return multi_union_pw_aff(arg0).sub(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_sub(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def tdiv_q(arg0, arg1):
+        res = isl.isl_multi_pw_aff_sub(isl.isl_multi_pw_aff_copy(arg0.ptr), isl.isl_multi_pw_aff_copy(arg1.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def zero(arg0):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_pw_aff_zero(isl.isl_space_copy(arg0.ptr))
+        obj = multi_pw_aff(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_multi_pw_aff_from_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_from_multi_aff.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_from_pw_aff.restype = c_void_p
+isl.isl_multi_pw_aff_from_pw_aff.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_from_pw_aff_list.restype = c_void_p
+isl.isl_multi_pw_aff_from_pw_aff_list.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_from_pw_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_from_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_read_from_str.restype = c_void_p
+isl.isl_multi_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_pw_aff_add.restype = c_void_p
+isl.isl_multi_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_add_constant_multi_val.restype = c_void_p
+isl.isl_multi_pw_aff_add_constant_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_add_constant_val.restype = c_void_p
+isl.isl_multi_pw_aff_add_constant_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_bind.restype = c_void_p
+isl.isl_multi_pw_aff_bind.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_bind_domain.restype = c_void_p
+isl.isl_multi_pw_aff_bind_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_bind_domain_wrapped_domain.restype = c_void_p
+isl.isl_multi_pw_aff_bind_domain_wrapped_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_coalesce.restype = c_void_p
+isl.isl_multi_pw_aff_coalesce.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_domain.restype = c_void_p
+isl.isl_multi_pw_aff_domain.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_flat_range_product.restype = c_void_p
+isl.isl_multi_pw_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_get_at.restype = c_void_p
+isl.isl_multi_pw_aff_get_at.argtypes = [c_void_p, c_int]
+isl.isl_multi_pw_aff_get_space.restype = c_void_p
+isl.isl_multi_pw_aff_get_space.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_gist.restype = c_void_p
+isl.isl_multi_pw_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_identity_multi_pw_aff.restype = c_void_p
+isl.isl_multi_pw_aff_identity_multi_pw_aff.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_identity_on_domain_space.restype = c_void_p
+isl.isl_multi_pw_aff_identity_on_domain_space.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_intersect_domain.restype = c_void_p
+isl.isl_multi_pw_aff_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_intersect_params.restype = c_void_p
+isl.isl_multi_pw_aff_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_involves_param_id.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_involves_param_id_list.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_neg.restype = c_void_p
+isl.isl_multi_pw_aff_neg.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_plain_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_product.restype = c_void_p
+isl.isl_multi_pw_aff_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_pullback_multi_pw_aff.restype = c_void_p
+isl.isl_multi_pw_aff_pullback_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_pullback_pw_multi_aff.restype = c_void_p
+isl.isl_multi_pw_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_range_product.restype = c_void_p
+isl.isl_multi_pw_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_scale_multi_val.restype = c_void_p
+isl.isl_multi_pw_aff_scale_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_scale_val.restype = c_void_p
+isl.isl_multi_pw_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_scale_down_multi_val.restype = c_void_p
+isl.isl_multi_pw_aff_scale_down_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_scale_down_val.restype = c_void_p
+isl.isl_multi_pw_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_set_at.restype = c_void_p
+isl.isl_multi_pw_aff_set_at.argtypes = [c_void_p, c_int, c_void_p]
+isl.isl_multi_pw_aff_size.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_sub.restype = c_void_p
+isl.isl_multi_pw_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_pw_aff_zero.restype = c_void_p
+isl.isl_multi_pw_aff_zero.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_copy.restype = c_void_p
+isl.isl_multi_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_free.restype = c_void_p
+isl.isl_multi_pw_aff_free.argtypes = [c_void_p]
+isl.isl_multi_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_multi_pw_aff_to_str.argtypes = [c_void_p]
+
+class pw_multi_aff(union_pw_multi_aff, multi_pw_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is multi_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_from_multi_aff(isl.isl_multi_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_pw_multi_aff_free(self.ptr)
+    def __str__(arg0):
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
-            return union_pw_aff(arg0).tdiv_q(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_pw_aff_tdiv_q(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def tdiv_r(arg0, arg1):
+            raise
+        ptr = isl.isl_pw_multi_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.pw_multi_aff("""%s""")' % s
+        else:
+            return 'isl.pw_multi_aff("%s")' % s
+    def add(arg0, arg1):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
         except:
-            return union_pw_aff(arg0).tdiv_r(arg1)
+            return union_pw_multi_aff(arg0).add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_tdiv_r(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-    def union_add(arg0, arg1):
+        res = isl.isl_pw_multi_aff_add(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def add_constant(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_pw_multi_aff_add_constant_multi_val(isl.isl_pw_multi_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_multi_aff_add_constant_val(isl.isl_pw_multi_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def as_multi_aff(arg0):
         try:
-            if not arg0.__class__ is pw_aff:
-                arg0 = pw_aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_as_multi_aff(isl.isl_pw_multi_aff_copy(arg0.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain(arg0, arg1):
         try:
-            if not arg1.__class__ is pw_aff:
-                arg1 = pw_aff(arg1)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
-            return union_pw_aff(arg0).union_add(arg1)
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_pw_multi_aff(arg0).bind_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_pw_aff_union_add(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
-        return pw_aff(ctx=ctx, ptr=res)
-
-isl.isl_pw_aff_from_aff.restype = c_void_p
-isl.isl_pw_aff_from_aff.argtypes = [c_void_p]
-isl.isl_pw_aff_read_from_str.restype = c_void_p
-isl.isl_pw_aff_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_pw_aff_add.restype = c_void_p
-isl.isl_pw_aff_add.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_ceil.restype = c_void_p
-isl.isl_pw_aff_ceil.argtypes = [c_void_p]
-isl.isl_pw_aff_cond.restype = c_void_p
-isl.isl_pw_aff_cond.argtypes = [c_void_p, c_void_p, c_void_p]
-isl.isl_pw_aff_div.restype = c_void_p
-isl.isl_pw_aff_div.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_eq_set.restype = c_void_p
-isl.isl_pw_aff_eq_set.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_floor.restype = c_void_p
-isl.isl_pw_aff_floor.argtypes = [c_void_p]
-isl.isl_pw_aff_ge_set.restype = c_void_p
-isl.isl_pw_aff_ge_set.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_gt_set.restype = c_void_p
-isl.isl_pw_aff_gt_set.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_le_set.restype = c_void_p
-isl.isl_pw_aff_le_set.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_lt_set.restype = c_void_p
-isl.isl_pw_aff_lt_set.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_max.restype = c_void_p
-isl.isl_pw_aff_max.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_min.restype = c_void_p
-isl.isl_pw_aff_min.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_mod_val.restype = c_void_p
-isl.isl_pw_aff_mod_val.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_mul.restype = c_void_p
-isl.isl_pw_aff_mul.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_ne_set.restype = c_void_p
-isl.isl_pw_aff_ne_set.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_neg.restype = c_void_p
-isl.isl_pw_aff_neg.argtypes = [c_void_p]
-isl.isl_pw_aff_pullback_multi_aff.restype = c_void_p
-isl.isl_pw_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_pullback_pw_multi_aff.restype = c_void_p
-isl.isl_pw_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_pullback_multi_pw_aff.restype = c_void_p
-isl.isl_pw_aff_pullback_multi_pw_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_scale_val.restype = c_void_p
-isl.isl_pw_aff_scale_val.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_scale_down_val.restype = c_void_p
-isl.isl_pw_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_sub.restype = c_void_p
-isl.isl_pw_aff_sub.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_tdiv_q.restype = c_void_p
-isl.isl_pw_aff_tdiv_q.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_tdiv_r.restype = c_void_p
-isl.isl_pw_aff_tdiv_r.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_union_add.restype = c_void_p
-isl.isl_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
-isl.isl_pw_aff_copy.restype = c_void_p
-isl.isl_pw_aff_copy.argtypes = [c_void_p]
-isl.isl_pw_aff_free.restype = c_void_p
-isl.isl_pw_aff_free.argtypes = [c_void_p]
-isl.isl_pw_aff_to_str.restype = POINTER(c_char)
-isl.isl_pw_aff_to_str.argtypes = [c_void_p]
-
-class multi_aff(pw_multi_aff, multi_pw_aff):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        if len(args) == 1 and args[0].__class__ is aff:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_multi_aff_from_aff(isl.isl_aff_copy(args[0].ptr))
-            return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_multi_aff_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_pw_multi_aff_bind_domain(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain_wrapped_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_aff:
-                arg0 = multi_aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
-        ptr = isl.isl_multi_aff_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.multi_aff("""%s""")' % s
-        else:
-            return 'isl.multi_aff("%s")' % s
-    def add(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_aff:
-                arg0 = multi_aff(arg0)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_pw_multi_aff(arg0).bind_domain_wrapped_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_bind_domain_wrapped_domain(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_coalesce(isl.isl_pw_multi_aff_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
         try:
-            if not arg1.__class__ is multi_aff:
-                arg1 = multi_aff(arg1)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
-            return pw_multi_aff(arg0).add(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_multi_aff_add(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-        return multi_aff(ctx=ctx, ptr=res)
+        res = isl.isl_pw_multi_aff_domain(isl.isl_pw_multi_aff_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
     def flat_range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_aff:
-                arg0 = multi_aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is multi_aff:
-                arg1 = multi_aff(arg1)
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
         except:
-            return pw_multi_aff(arg0).flat_range_product(arg1)
+            return union_pw_multi_aff(arg0).flat_range_product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_multi_aff_flat_range_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-        return multi_aff(ctx=ctx, ptr=res)
-    def product(arg0, arg1):
+        res = isl.isl_pw_multi_aff_flat_range_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def foreach_piece(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_aff:
-                arg0 = multi_aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1, cb_arg2):
+            cb_arg0 = set(ctx=arg0.ctx, ptr=(cb_arg0))
+            cb_arg1 = multi_aff(ctx=arg0.ctx, ptr=(cb_arg1))
+            try:
+                arg1(cb_arg0, cb_arg1)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_foreach_piece(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def space(arg0):
         try:
-            if not arg1.__class__ is multi_aff:
-                arg1 = multi_aff(arg1)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
-            return pw_multi_aff(arg0).product(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_multi_aff_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-        return multi_aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is multi_aff:
-            res = isl.isl_multi_aff_pullback_multi_aff(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-            return multi_aff(ctx=arg0.ctx, ptr=res)
-    def range_product(arg0, arg1):
+        res = isl.isl_pw_multi_aff_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
         try:
-            if not arg0.__class__ is multi_aff:
-                arg0 = multi_aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is multi_aff:
-                arg1 = multi_aff(arg1)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            return pw_multi_aff(arg0).range_product(arg1)
+            return union_pw_multi_aff(arg0).gist(arg1)
         ctx = arg0.ctx
-        res = isl.isl_multi_aff_range_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-        return multi_aff(ctx=ctx, ptr=res)
-
-isl.isl_multi_aff_from_aff.restype = c_void_p
-isl.isl_multi_aff_from_aff.argtypes = [c_void_p]
-isl.isl_multi_aff_read_from_str.restype = c_void_p
-isl.isl_multi_aff_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_multi_aff_add.restype = c_void_p
-isl.isl_multi_aff_add.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_aff_flat_range_product.restype = c_void_p
-isl.isl_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_aff_product.restype = c_void_p
-isl.isl_multi_aff_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_aff_pullback_multi_aff.restype = c_void_p
-isl.isl_multi_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_aff_range_product.restype = c_void_p
-isl.isl_multi_aff_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_aff_copy.restype = c_void_p
-isl.isl_multi_aff_copy.argtypes = [c_void_p]
-isl.isl_multi_aff_free.restype = c_void_p
-isl.isl_multi_aff_free.argtypes = [c_void_p]
-isl.isl_multi_aff_to_str.restype = POINTER(c_char)
-isl.isl_multi_aff_to_str.argtypes = [c_void_p]
-
-class aff(pw_aff, multi_aff):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_aff_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_aff_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_pw_multi_aff_gist(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
-        ptr = isl.isl_aff_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.aff("""%s""")' % s
-        else:
-            return 'isl.aff("%s")' % s
-    def add(arg0, arg1):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_pw_multi_aff(arg0).intersect_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_intersect_domain(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            return pw_aff(arg0).add(arg1)
+            return union_pw_multi_aff(arg0).intersect_params(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_add(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return aff(ctx=ctx, ptr=res)
-    def ceil(arg0):
+        res = isl.isl_pw_multi_aff_intersect_params(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def isa_multi_aff(arg0):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_aff_ceil(isl.isl_aff_copy(arg0.ptr))
-        return aff(ctx=ctx, ptr=res)
-    def div(arg0, arg1):
-        try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
-        except:
+        res = isl.isl_pw_multi_aff_isa_multi_aff(arg0.ptr)
+        if res < 0:
             raise
+        return bool(res)
+    def n_piece(arg0):
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
-            return pw_aff(arg0).div(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_aff_div(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return aff(ctx=ctx, ptr=res)
-    def eq_set(arg0, arg1):
+        res = isl.isl_pw_multi_aff_n_piece(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def product(arg0, arg1):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
-        except:
-            return pw_aff(arg0).eq_set(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_aff_eq_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def floor(arg0):
-        try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
         except:
-            raise
+            return union_pw_multi_aff(arg0).product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_floor(isl.isl_aff_copy(arg0.ptr))
-        return aff(ctx=ctx, ptr=res)
-    def ge_set(arg0, arg1):
+        res = isl.isl_pw_multi_aff_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_pw_multi_aff_pullback_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_pw_multi_aff_pullback_pw_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def range_factor_domain(arg0):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
-        except:
-            return pw_aff(arg0).ge_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_ge_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def gt_set(arg0, arg1):
+        res = isl.isl_pw_multi_aff_range_factor_domain(isl.isl_pw_multi_aff_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def range_factor_range(arg0):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
-        except:
-            return pw_aff(arg0).gt_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_gt_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def le_set(arg0, arg1):
+        res = isl.isl_pw_multi_aff_range_factor_range(isl.isl_pw_multi_aff_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
         except:
-            return pw_aff(arg0).le_set(arg1)
+            return union_pw_multi_aff(arg0).range_product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_le_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def lt_set(arg0, arg1):
+        res = isl.isl_pw_multi_aff_range_product(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def scale(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_multi_aff_scale_val(isl.isl_pw_multi_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale_down(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_multi_aff_scale_down_val(isl.isl_pw_multi_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = pw_multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def sub(arg0, arg1):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
         except:
-            return pw_aff(arg0).lt_set(arg1)
+            return union_pw_multi_aff(arg0).sub(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_lt_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def mod(arg0, arg1):
-        if arg1.__class__ is val:
-            res = isl.isl_aff_mod_val(isl.isl_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-            return aff(ctx=arg0.ctx, ptr=res)
-    def mul(arg0, arg1):
+        res = isl.isl_pw_multi_aff_sub(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def subtract_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            return pw_aff(arg0).mul(arg1)
+            return union_pw_multi_aff(arg0).subtract_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_mul(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return aff(ctx=ctx, ptr=res)
-    def ne_set(arg0, arg1):
+        res = isl.isl_pw_multi_aff_subtract_domain(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def union_add(arg0, arg1):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is pw_multi_aff:
+                arg0 = pw_multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
-        except:
-            return pw_aff(arg0).ne_set(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_aff_ne_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def neg(arg0):
-        try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
         except:
-            raise
+            return union_pw_multi_aff(arg0).union_add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_neg(isl.isl_aff_copy(arg0.ptr))
-        return aff(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is multi_aff:
-            res = isl.isl_aff_pullback_multi_aff(isl.isl_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-            return aff(ctx=arg0.ctx, ptr=res)
-    def scale(arg0, arg1):
-        if arg1.__class__ is val:
-            res = isl.isl_aff_scale_val(isl.isl_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-            return aff(ctx=arg0.ctx, ptr=res)
-    def scale_down(arg0, arg1):
-        if arg1.__class__ is val:
-            res = isl.isl_aff_scale_down_val(isl.isl_aff_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-            return aff(ctx=arg0.ctx, ptr=res)
-    def sub(arg0, arg1):
+        res = isl.isl_pw_multi_aff_union_add(isl.isl_pw_multi_aff_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def zero(arg0):
         try:
-            if not arg0.__class__ is aff:
-                arg0 = aff(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
-        except:
-            return pw_aff(arg0).sub(arg1)
         ctx = arg0.ctx
-        res = isl.isl_aff_sub(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
-        return aff(ctx=ctx, ptr=res)
+        res = isl.isl_pw_multi_aff_zero(isl.isl_space_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
 
-isl.isl_aff_read_from_str.restype = c_void_p
-isl.isl_aff_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_aff_add.restype = c_void_p
-isl.isl_aff_add.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_ceil.restype = c_void_p
-isl.isl_aff_ceil.argtypes = [c_void_p]
-isl.isl_aff_div.restype = c_void_p
-isl.isl_aff_div.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_eq_set.restype = c_void_p
-isl.isl_aff_eq_set.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_floor.restype = c_void_p
-isl.isl_aff_floor.argtypes = [c_void_p]
-isl.isl_aff_ge_set.restype = c_void_p
-isl.isl_aff_ge_set.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_gt_set.restype = c_void_p
-isl.isl_aff_gt_set.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_le_set.restype = c_void_p
-isl.isl_aff_le_set.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_lt_set.restype = c_void_p
-isl.isl_aff_lt_set.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_mod_val.restype = c_void_p
-isl.isl_aff_mod_val.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_mul.restype = c_void_p
-isl.isl_aff_mul.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_ne_set.restype = c_void_p
-isl.isl_aff_ne_set.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_neg.restype = c_void_p
-isl.isl_aff_neg.argtypes = [c_void_p]
-isl.isl_aff_pullback_multi_aff.restype = c_void_p
-isl.isl_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_scale_val.restype = c_void_p
-isl.isl_aff_scale_val.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_scale_down_val.restype = c_void_p
-isl.isl_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_sub.restype = c_void_p
-isl.isl_aff_sub.argtypes = [c_void_p, c_void_p]
-isl.isl_aff_copy.restype = c_void_p
-isl.isl_aff_copy.argtypes = [c_void_p]
-isl.isl_aff_free.restype = c_void_p
-isl.isl_aff_free.argtypes = [c_void_p]
-isl.isl_aff_to_str.restype = POINTER(c_char)
-isl.isl_aff_to_str.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_from_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_from_multi_aff.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_from_pw_aff.restype = c_void_p
+isl.isl_pw_multi_aff_from_pw_aff.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_read_from_str.restype = c_void_p
+isl.isl_pw_multi_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_pw_multi_aff_add.restype = c_void_p
+isl.isl_pw_multi_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_add_constant_multi_val.restype = c_void_p
+isl.isl_pw_multi_aff_add_constant_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_add_constant_val.restype = c_void_p
+isl.isl_pw_multi_aff_add_constant_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_as_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_as_multi_aff.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_bind_domain.restype = c_void_p
+isl.isl_pw_multi_aff_bind_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_bind_domain_wrapped_domain.restype = c_void_p
+isl.isl_pw_multi_aff_bind_domain_wrapped_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_coalesce.restype = c_void_p
+isl.isl_pw_multi_aff_coalesce.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_domain.restype = c_void_p
+isl.isl_pw_multi_aff_domain.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_flat_range_product.restype = c_void_p
+isl.isl_pw_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_foreach_piece.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_pw_multi_aff_get_space.restype = c_void_p
+isl.isl_pw_multi_aff_get_space.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_gist.restype = c_void_p
+isl.isl_pw_multi_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_intersect_domain.restype = c_void_p
+isl.isl_pw_multi_aff_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_intersect_params.restype = c_void_p
+isl.isl_pw_multi_aff_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_isa_multi_aff.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_n_piece.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_product.restype = c_void_p
+isl.isl_pw_multi_aff_product.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_pullback_pw_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_range_factor_domain.restype = c_void_p
+isl.isl_pw_multi_aff_range_factor_domain.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_range_factor_range.restype = c_void_p
+isl.isl_pw_multi_aff_range_factor_range.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_range_product.restype = c_void_p
+isl.isl_pw_multi_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_scale_val.restype = c_void_p
+isl.isl_pw_multi_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_scale_down_val.restype = c_void_p
+isl.isl_pw_multi_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_sub.restype = c_void_p
+isl.isl_pw_multi_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_subtract_domain.restype = c_void_p
+isl.isl_pw_multi_aff_subtract_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_union_add.restype = c_void_p
+isl.isl_pw_multi_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_zero.restype = c_void_p
+isl.isl_pw_multi_aff_zero.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_copy.restype = c_void_p
+isl.isl_pw_multi_aff_copy.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_free.restype = c_void_p
+isl.isl_pw_multi_aff_free.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_to_str.restype = POINTER(c_char)
+isl.isl_pw_multi_aff_to_str.argtypes = [c_void_p]
 
-class ast_build(object):
+class pw_aff(union_pw_aff, pw_multi_aff, multi_pw_aff):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 0:
+        if len(args) == 1 and args[0].__class__ is aff:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_ast_build_alloc(self.ctx)
+            self.ptr = isl.isl_pw_aff_from_aff(isl.isl_aff_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_aff_read_from_str(self.ctx, args[0].encode('ascii'))
             return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_ast_build_free(self.ptr)
-    def access_from(arg0, arg1):
-        if arg1.__class__ is pw_multi_aff:
-            res = isl.isl_ast_build_access_from_pw_multi_aff(arg0.ptr, isl.isl_pw_multi_aff_copy(arg1.ptr))
-            return ast_expr(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is multi_pw_aff:
-            res = isl.isl_ast_build_access_from_multi_pw_aff(arg0.ptr, isl.isl_multi_pw_aff_copy(arg1.ptr))
-            return ast_expr(ctx=arg0.ctx, ptr=res)
-    def call_from(arg0, arg1):
-        if arg1.__class__ is pw_multi_aff:
-            res = isl.isl_ast_build_call_from_pw_multi_aff(arg0.ptr, isl.isl_pw_multi_aff_copy(arg1.ptr))
-            return ast_expr(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is multi_pw_aff:
-            res = isl.isl_ast_build_call_from_multi_pw_aff(arg0.ptr, isl.isl_multi_pw_aff_copy(arg1.ptr))
-            return ast_expr(ctx=arg0.ctx, ptr=res)
-    def expr_from(arg0, arg1):
-        if arg1.__class__ is set:
-            res = isl.isl_ast_build_expr_from_set(arg0.ptr, isl.isl_set_copy(arg1.ptr))
-            return ast_expr(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is pw_aff:
-            res = isl.isl_ast_build_expr_from_pw_aff(arg0.ptr, isl.isl_pw_aff_copy(arg1.ptr))
-            return ast_expr(ctx=arg0.ctx, ptr=res)
-    @staticmethod
-    def from_context(arg0):
+            isl.isl_pw_aff_free(self.ptr)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
+        except:
+            raise
+        ptr = isl.isl_pw_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.pw_aff("""%s""")' % s
+        else:
+            return 'isl.pw_aff("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_ast_build_from_context(isl.isl_set_copy(arg0.ptr))
-        return ast_build(ctx=ctx, ptr=res)
-    def node_from_schedule_map(arg0, arg1):
+        res = isl.isl_pw_aff_add(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def add_constant(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_add_constant_val(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def as_aff(arg0):
         try:
-            if not arg0.__class__ is ast_build:
-                arg0 = ast_build(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_as_aff(isl.isl_pw_aff_copy(arg0.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def bind(*args):
+        if len(args) == 2 and (args[1].__class__ is id or type(args[1]) == str):
+            args = list(args)
+            try:
+                if not args[1].__class__ is id:
+                    args[1] = id(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_bind_id(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_id_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def bind_domain(arg0, arg1):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_pw_aff(arg0).bind_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_ast_build_node_from_schedule_map(arg0.ptr, isl.isl_union_map_copy(arg1.ptr))
-        return ast_node(ctx=ctx, ptr=res)
-
-isl.isl_ast_build_alloc.restype = c_void_p
-isl.isl_ast_build_alloc.argtypes = [Context]
-isl.isl_ast_build_access_from_pw_multi_aff.restype = c_void_p
-isl.isl_ast_build_access_from_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_ast_build_access_from_multi_pw_aff.restype = c_void_p
-isl.isl_ast_build_access_from_multi_pw_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_ast_build_call_from_pw_multi_aff.restype = c_void_p
-isl.isl_ast_build_call_from_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_ast_build_call_from_multi_pw_aff.restype = c_void_p
-isl.isl_ast_build_call_from_multi_pw_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_ast_build_expr_from_set.restype = c_void_p
-isl.isl_ast_build_expr_from_set.argtypes = [c_void_p, c_void_p]
-isl.isl_ast_build_expr_from_pw_aff.restype = c_void_p
-isl.isl_ast_build_expr_from_pw_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_ast_build_from_context.restype = c_void_p
-isl.isl_ast_build_from_context.argtypes = [c_void_p]
-isl.isl_ast_build_node_from_schedule_map.restype = c_void_p
-isl.isl_ast_build_node_from_schedule_map.argtypes = [c_void_p, c_void_p]
-isl.isl_ast_build_copy.restype = c_void_p
-isl.isl_ast_build_copy.argtypes = [c_void_p]
-isl.isl_ast_build_free.restype = c_void_p
-isl.isl_ast_build_free.argtypes = [c_void_p]
-
-class ast_expr(object):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_ast_expr_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_pw_aff_bind_domain(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain_wrapped_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is ast_expr:
-                arg0 = ast_expr(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.ast_expr("""%s""")' % s
-        else:
-            return 'isl.ast_expr("%s")' % s
-    def to_C_str(arg0):
         try:
-            if not arg0.__class__ is ast_expr:
-                arg0 = ast_expr(arg0)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).bind_domain_wrapped_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_ast_expr_to_C_str(arg0.ptr)
-        if res == 0:
-            raise
-        string = cast(res, c_char_p).value.decode('ascii')
-        libc.free(res)
-        return string
-
-isl.isl_ast_expr_to_C_str.restype = POINTER(c_char)
-isl.isl_ast_expr_to_C_str.argtypes = [c_void_p]
-isl.isl_ast_expr_copy.restype = c_void_p
-isl.isl_ast_expr_copy.argtypes = [c_void_p]
-isl.isl_ast_expr_free.restype = c_void_p
-isl.isl_ast_expr_free.argtypes = [c_void_p]
-isl.isl_ast_expr_to_str.restype = POINTER(c_char)
-isl.isl_ast_expr_to_str.argtypes = [c_void_p]
-
-class ast_node(object):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_ast_node_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_pw_aff_bind_domain_wrapped_domain(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def ceil(arg0):
         try:
-            if not arg0.__class__ is ast_node:
-                arg0 = ast_node(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ptr = isl.isl_ast_node_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.ast_node("""%s""")' % s
-        else:
-            return 'isl.ast_node("%s")' % s
-    def to_C_str(arg0):
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_ceil(isl.isl_pw_aff_copy(arg0.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
         try:
-            if not arg0.__class__ is ast_node:
-                arg0 = ast_node(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_ast_node_to_C_str(arg0.ptr)
-        if res == 0:
-            raise
-        string = cast(res, c_char_p).value.decode('ascii')
-        libc.free(res)
-        return string
-
-isl.isl_ast_node_to_C_str.restype = POINTER(c_char)
-isl.isl_ast_node_to_C_str.argtypes = [c_void_p]
-isl.isl_ast_node_copy.restype = c_void_p
-isl.isl_ast_node_copy.argtypes = [c_void_p]
-isl.isl_ast_node_free.restype = c_void_p
-isl.isl_ast_node_free.argtypes = [c_void_p]
-isl.isl_ast_node_to_str.restype = POINTER(c_char)
-isl.isl_ast_node_to_str.argtypes = [c_void_p]
-
-class union_map(object):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        if len(args) == 1 and args[0].__class__ is basic_map:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_map_from_basic_map(isl.isl_basic_map_copy(args[0].ptr))
-            return
-        if len(args) == 1 and args[0].__class__ is map:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_map_from_map(isl.isl_map_copy(args[0].ptr))
-            return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_map_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_union_map_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_pw_aff_coalesce(isl.isl_pw_aff_copy(arg0.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def cond(arg0, arg1, arg2):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ptr = isl.isl_union_map_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.union_map("""%s""")' % s
-        else:
-            return 'isl.union_map("%s")' % s
-    def affine_hull(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).cond(arg1, arg2)
+        try:
+            if not arg2.__class__ is pw_aff:
+                arg2 = pw_aff(arg2)
+        except:
+            return union_pw_aff(arg0).cond(arg1, arg2)
         ctx = arg0.ctx
-        res = isl.isl_union_map_affine_hull(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def apply_domain(arg0, arg1):
+        res = isl.isl_pw_aff_cond(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr), isl.isl_pw_aff_copy(arg2.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def div(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).div(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_apply_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def apply_range(arg0, arg1):
+        res = isl.isl_pw_aff_div(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_domain(isl.isl_pw_aff_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def eq_set(arg0, arg1):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_apply_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def coalesce(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).eq_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_coalesce(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def compute_divs(arg0):
+        res = isl.isl_pw_aff_eq_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def eval(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_compute_divs(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def deltas(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is point:
+                arg1 = point(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).eval(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_deltas(isl.isl_union_map_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def detect_equalities(arg0):
+        res = isl.isl_pw_aff_eval(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_point_copy(arg1.ptr))
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def floor(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_detect_equalities(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def domain(arg0):
+        res = isl.isl_pw_aff_floor(isl.isl_pw_aff_copy(arg0.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def ge_set(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_domain(isl.isl_union_map_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def domain_factor_domain(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).ge_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_domain_factor_domain(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def domain_factor_range(arg0):
+        res = isl.isl_pw_aff_ge_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def gist(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_domain_factor_range(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def domain_map(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).gist(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_domain_map(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def domain_map_union_pw_multi_aff(arg0):
+        res = isl.isl_pw_aff_gist(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def gt_set(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_domain_map_union_pw_multi_aff(isl.isl_union_map_copy(arg0.ptr))
-        return union_pw_multi_aff(ctx=ctx, ptr=res)
-    def domain_product(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).gt_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_gt_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_domain_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def eq_at(arg0, arg1):
-        if arg1.__class__ is multi_union_pw_aff:
-            res = isl.isl_union_map_eq_at_multi_union_pw_aff(isl.isl_union_map_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
-            return union_map(ctx=arg0.ctx, ptr=res)
-    def factor_domain(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).intersect_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_factor_domain(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def factor_range(arg0):
+        res = isl.isl_pw_aff_intersect_domain(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_factor_range(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def fixed_power(arg0, arg1):
-        if arg1.__class__ is val:
-            res = isl.isl_union_map_fixed_power_val(isl.isl_union_map_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-            return union_map(ctx=arg0.ctx, ptr=res)
-    def foreach_map(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            raise
-        exc_info = [None]
-        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
-        def cb_func(cb_arg0, cb_arg1):
-            cb_arg0 = map(ctx=arg0.ctx, ptr=(cb_arg0))
-            try:
-                arg1(cb_arg0)
-            except:
-                import sys
-                exc_info[0] = sys.exc_info()
-                return -1
-            return 0
-        cb = fn(cb_func)
+            return union_pw_aff(arg0).intersect_params(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_foreach_map(arg0.ptr, cb, None)
-        if exc_info[0] != None:
-            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
-        return res
-    @staticmethod
-    def convert_from(arg0):
-        if arg0.__class__ is union_pw_multi_aff:
-            res = isl.isl_union_map_from_union_pw_multi_aff(isl.isl_union_pw_multi_aff_copy(arg0.ptr))
-            return union_map(ctx=arg0.ctx, ptr=res)
-        if arg0.__class__ is multi_union_pw_aff:
-            res = isl.isl_union_map_from_multi_union_pw_aff(isl.isl_multi_union_pw_aff_copy(arg0.ptr))
-            return union_map(ctx=arg0.ctx, ptr=res)
-    @staticmethod
-    def from_domain(arg0):
+        res = isl.isl_pw_aff_intersect_params(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def isa_aff(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_from_domain(isl.isl_union_set_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    @staticmethod
-    def from_domain_and_range(arg0, arg1):
-        try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
-        except:
+        res = isl.isl_pw_aff_isa_aff(arg0.ptr)
+        if res < 0:
             raise
+        return bool(res)
+    def le_set(arg0, arg1):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_from_domain_and_range(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    @staticmethod
-    def from_range(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).le_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_from_range(isl.isl_union_set_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def gist(arg0, arg1):
+        res = isl.isl_pw_aff_le_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def lt_set(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).lt_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_gist(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def gist_domain(arg0, arg1):
+        res = isl.isl_pw_aff_lt_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def max(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).max(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_gist_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def gist_params(arg0, arg1):
+        res = isl.isl_pw_aff_max(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def min(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).min(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_gist_params(isl.isl_union_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def gist_range(arg0, arg1):
+        res = isl.isl_pw_aff_min(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def mod(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_mod_val(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def mul(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).mul(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_gist_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def intersect(arg0, arg1):
+        res = isl.isl_pw_aff_mul(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def ne_set(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).ne_set(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_intersect(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def intersect_domain(arg0, arg1):
+        res = isl.isl_pw_aff_ne_set(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def neg(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_neg(isl.isl_pw_aff_copy(arg0.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def param_on_domain(*args):
+        if len(args) == 2 and args[0].__class__ is set and (args[1].__class__ is id or type(args[1]) == str):
+            args = list(args)
+            try:
+                if not args[1].__class__ is id:
+                    args[1] = id(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_param_on_domain_id(isl.isl_set_copy(args[0].ptr), isl.isl_id_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_pullback_multi_aff(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_pullback_multi_pw_aff(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_pullback_pw_multi_aff(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_scale_val(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale_down(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_pw_aff_scale_down_val(isl.isl_pw_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = pw_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def sub(arg0, arg1):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
+        try:
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
+        except:
+            return union_pw_aff(arg0).sub(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_intersect_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def intersect_params(arg0, arg1):
+        res = isl.isl_pw_aff_sub(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def subtract_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
             if not arg1.__class__ is set:
                 arg1 = set(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).subtract_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_intersect_params(isl.isl_union_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def intersect_range(arg0, arg1):
+        res = isl.isl_pw_aff_subtract_domain(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def tdiv_q(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).tdiv_q(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_intersect_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def is_bijective(arg0):
+        res = isl.isl_pw_aff_tdiv_q(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def tdiv_r(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_is_bijective(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_empty(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).tdiv_r(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_is_empty(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_equal(arg0, arg1):
+        res = isl.isl_pw_aff_tdiv_r(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def union_add(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is pw_aff:
+                arg0 = pw_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
-            raise
+            return union_pw_aff(arg0).union_add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_is_equal(arg0.ptr, arg1.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_injective(arg0):
+        res = isl.isl_pw_aff_union_add(isl.isl_pw_aff_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_pw_aff_from_aff.restype = c_void_p
+isl.isl_pw_aff_from_aff.argtypes = [c_void_p]
+isl.isl_pw_aff_read_from_str.restype = c_void_p
+isl.isl_pw_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_pw_aff_add.restype = c_void_p
+isl.isl_pw_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_add_constant_val.restype = c_void_p
+isl.isl_pw_aff_add_constant_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_as_aff.restype = c_void_p
+isl.isl_pw_aff_as_aff.argtypes = [c_void_p]
+isl.isl_pw_aff_bind_id.restype = c_void_p
+isl.isl_pw_aff_bind_id.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_bind_domain.restype = c_void_p
+isl.isl_pw_aff_bind_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_bind_domain_wrapped_domain.restype = c_void_p
+isl.isl_pw_aff_bind_domain_wrapped_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_ceil.restype = c_void_p
+isl.isl_pw_aff_ceil.argtypes = [c_void_p]
+isl.isl_pw_aff_coalesce.restype = c_void_p
+isl.isl_pw_aff_coalesce.argtypes = [c_void_p]
+isl.isl_pw_aff_cond.restype = c_void_p
+isl.isl_pw_aff_cond.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_pw_aff_div.restype = c_void_p
+isl.isl_pw_aff_div.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_domain.restype = c_void_p
+isl.isl_pw_aff_domain.argtypes = [c_void_p]
+isl.isl_pw_aff_eq_set.restype = c_void_p
+isl.isl_pw_aff_eq_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_eval.restype = c_void_p
+isl.isl_pw_aff_eval.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_floor.restype = c_void_p
+isl.isl_pw_aff_floor.argtypes = [c_void_p]
+isl.isl_pw_aff_ge_set.restype = c_void_p
+isl.isl_pw_aff_ge_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_gist.restype = c_void_p
+isl.isl_pw_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_gt_set.restype = c_void_p
+isl.isl_pw_aff_gt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_intersect_domain.restype = c_void_p
+isl.isl_pw_aff_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_intersect_params.restype = c_void_p
+isl.isl_pw_aff_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_isa_aff.argtypes = [c_void_p]
+isl.isl_pw_aff_le_set.restype = c_void_p
+isl.isl_pw_aff_le_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_lt_set.restype = c_void_p
+isl.isl_pw_aff_lt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_max.restype = c_void_p
+isl.isl_pw_aff_max.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_min.restype = c_void_p
+isl.isl_pw_aff_min.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_mod_val.restype = c_void_p
+isl.isl_pw_aff_mod_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_mul.restype = c_void_p
+isl.isl_pw_aff_mul.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_ne_set.restype = c_void_p
+isl.isl_pw_aff_ne_set.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_neg.restype = c_void_p
+isl.isl_pw_aff_neg.argtypes = [c_void_p]
+isl.isl_pw_aff_param_on_domain_id.restype = c_void_p
+isl.isl_pw_aff_param_on_domain_id.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_pw_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_pullback_multi_pw_aff.restype = c_void_p
+isl.isl_pw_aff_pullback_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_pullback_pw_multi_aff.restype = c_void_p
+isl.isl_pw_aff_pullback_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_scale_val.restype = c_void_p
+isl.isl_pw_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_scale_down_val.restype = c_void_p
+isl.isl_pw_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_sub.restype = c_void_p
+isl.isl_pw_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_subtract_domain.restype = c_void_p
+isl.isl_pw_aff_subtract_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_tdiv_q.restype = c_void_p
+isl.isl_pw_aff_tdiv_q.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_tdiv_r.restype = c_void_p
+isl.isl_pw_aff_tdiv_r.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_union_add.restype = c_void_p
+isl.isl_pw_aff_union_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_copy.restype = c_void_p
+isl.isl_pw_aff_copy.argtypes = [c_void_p]
+isl.isl_pw_aff_free.restype = c_void_p
+isl.isl_pw_aff_free.argtypes = [c_void_p]
+isl.isl_pw_aff_to_str.restype = POINTER(c_char)
+isl.isl_pw_aff_to_str.argtypes = [c_void_p]
+
+class multi_aff(pw_multi_aff, multi_pw_aff):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_aff_from_aff(isl.isl_aff_copy(args[0].ptr))
+            return
+        if len(args) == 2 and args[0].__class__ is space and args[1].__class__ is aff_list:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_aff_from_aff_list(isl.isl_space_copy(args[0].ptr), isl.isl_aff_list_copy(args[1].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_aff_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_multi_aff_free(self.ptr)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_is_injective(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_single_valued(arg0):
+        ptr = isl.isl_multi_aff_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.multi_aff("""%s""")' % s
+        else:
+            return 'isl.multi_aff("%s")' % s
+    def add(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
+        try:
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
+        except:
+            return pw_multi_aff(arg0).add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_is_single_valued(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_strict_subset(arg0, arg1):
+        res = isl.isl_multi_aff_add(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def add_constant(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_add_constant_multi_val(isl.isl_multi_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_add_constant_val(isl.isl_multi_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def bind(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
-            raise
+            return pw_multi_aff(arg0).bind(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_is_strict_subset(arg0.ptr, arg1.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_subset(arg0, arg1):
+        res = isl.isl_multi_aff_bind(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
-            raise
+            return pw_multi_aff(arg0).bind_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_is_subset(arg0.ptr, arg1.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def lexmax(arg0):
+        res = isl.isl_multi_aff_bind_domain(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain_wrapped_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_lexmax(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def lexmin(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
         except:
-            raise
+            return pw_multi_aff(arg0).bind_domain_wrapped_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_lexmin(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def polyhedral_hull(arg0):
+        res = isl.isl_multi_aff_bind_domain_wrapped_domain(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def domain_map(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_polyhedral_hull(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def product(arg0, arg1):
+        res = isl.isl_multi_aff_domain_map(isl.isl_space_copy(arg0.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def flat_range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
         except:
-            raise
+            return pw_multi_aff(arg0).flat_range_product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def project_out_all_params(arg0):
+        res = isl.isl_multi_aff_flat_range_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def floor(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_project_out_all_params(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def range(arg0):
+        res = isl.isl_multi_aff_floor(isl.isl_multi_aff_copy(arg0.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_range(isl.isl_union_map_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def range_factor_domain(arg0):
+        res = isl.isl_multi_aff_get_at(arg0.ptr, arg1)
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def constant_multi_val(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_range_factor_domain(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def range_factor_range(arg0):
+        res = isl.isl_multi_aff_get_constant_multi_val(arg0.ptr)
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def get_constant_multi_val(arg0):
+        return arg0.constant_multi_val()
+    def space(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_range_factor_range(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def range_map(arg0):
+        res = isl.isl_multi_aff_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_map_range_map(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
-            raise
+            return pw_multi_aff(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_multi_aff_gist(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def identity(*args):
+        if len(args) == 1:
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_identity_multi_aff(isl.isl_multi_aff_copy(args[0].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    @staticmethod
+    def identity_on_domain(*args):
+        if len(args) == 1 and args[0].__class__ is space:
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_identity_on_domain_space(isl.isl_space_copy(args[0].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def involves_locals(arg0):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_range_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def reverse(arg0):
+        res = isl.isl_multi_aff_involves_locals(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def neg(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_reverse(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def subtract(arg0, arg1):
+        res = isl.isl_multi_aff_neg(isl.isl_multi_aff_copy(arg0.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def plain_is_equal(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
         except:
-            raise
+            return pw_multi_aff(arg0).plain_is_equal(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_subtract(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def subtract_domain(arg0, arg1):
+        res = isl.isl_multi_aff_plain_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def product(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
         except:
-            raise
+            return pw_multi_aff(arg0).product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_subtract_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def subtract_range(arg0, arg1):
+        res = isl.isl_multi_aff_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_pullback_multi_aff(isl.isl_multi_aff_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    @staticmethod
+    def range_map(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_aff_range_map(isl.isl_space_copy(arg0.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def range_product(arg0, arg1):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
+        try:
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
+        except:
+            return pw_multi_aff(arg0).range_product(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_subtract_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def union(arg0, arg1):
+        res = isl.isl_multi_aff_range_product(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def scale(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_scale_multi_val(isl.isl_multi_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_scale_val(isl.isl_multi_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale_down(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_scale_down_multi_val(isl.isl_multi_aff_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_aff_scale_down_val(isl.isl_multi_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def set_at(arg0, arg1, arg2):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg2.__class__ is aff:
+                arg2 = aff(arg2)
+        except:
+            return pw_multi_aff(arg0).set_at(arg1, arg2)
+        ctx = arg0.ctx
+        res = isl.isl_multi_aff_set_at(isl.isl_multi_aff_copy(arg0.ptr), arg1, isl.isl_aff_copy(arg2.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def size(arg0):
+        try:
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_union(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def wrap(arg0):
+        res = isl.isl_multi_aff_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def sub(arg0, arg1):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is multi_aff:
+                arg0 = multi_aff(arg0)
         except:
             raise
+        try:
+            if not arg1.__class__ is multi_aff:
+                arg1 = multi_aff(arg1)
+        except:
+            return pw_multi_aff(arg0).sub(arg1)
         ctx = arg0.ctx
-        res = isl.isl_union_map_wrap(isl.isl_union_map_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def zip(arg0):
+        res = isl.isl_multi_aff_sub(isl.isl_multi_aff_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def zero(arg0):
         try:
-            if not arg0.__class__ is union_map:
-                arg0 = union_map(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_map_zip(isl.isl_union_map_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
+        res = isl.isl_multi_aff_zero(isl.isl_space_copy(arg0.ptr))
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
 
-isl.isl_union_map_from_basic_map.restype = c_void_p
-isl.isl_union_map_from_basic_map.argtypes = [c_void_p]
-isl.isl_union_map_from_map.restype = c_void_p
-isl.isl_union_map_from_map.argtypes = [c_void_p]
-isl.isl_union_map_read_from_str.restype = c_void_p
-isl.isl_union_map_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_union_map_affine_hull.restype = c_void_p
-isl.isl_union_map_affine_hull.argtypes = [c_void_p]
-isl.isl_union_map_apply_domain.restype = c_void_p
-isl.isl_union_map_apply_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_apply_range.restype = c_void_p
-isl.isl_union_map_apply_range.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_coalesce.restype = c_void_p
-isl.isl_union_map_coalesce.argtypes = [c_void_p]
-isl.isl_union_map_compute_divs.restype = c_void_p
-isl.isl_union_map_compute_divs.argtypes = [c_void_p]
-isl.isl_union_map_deltas.restype = c_void_p
-isl.isl_union_map_deltas.argtypes = [c_void_p]
-isl.isl_union_map_detect_equalities.restype = c_void_p
-isl.isl_union_map_detect_equalities.argtypes = [c_void_p]
-isl.isl_union_map_domain.restype = c_void_p
-isl.isl_union_map_domain.argtypes = [c_void_p]
-isl.isl_union_map_domain_factor_domain.restype = c_void_p
-isl.isl_union_map_domain_factor_domain.argtypes = [c_void_p]
-isl.isl_union_map_domain_factor_range.restype = c_void_p
-isl.isl_union_map_domain_factor_range.argtypes = [c_void_p]
-isl.isl_union_map_domain_map.restype = c_void_p
-isl.isl_union_map_domain_map.argtypes = [c_void_p]
-isl.isl_union_map_domain_map_union_pw_multi_aff.restype = c_void_p
-isl.isl_union_map_domain_map_union_pw_multi_aff.argtypes = [c_void_p]
-isl.isl_union_map_domain_product.restype = c_void_p
-isl.isl_union_map_domain_product.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_eq_at_multi_union_pw_aff.restype = c_void_p
-isl.isl_union_map_eq_at_multi_union_pw_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_factor_domain.restype = c_void_p
-isl.isl_union_map_factor_domain.argtypes = [c_void_p]
-isl.isl_union_map_factor_range.restype = c_void_p
-isl.isl_union_map_factor_range.argtypes = [c_void_p]
-isl.isl_union_map_fixed_power_val.restype = c_void_p
-isl.isl_union_map_fixed_power_val.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_foreach_map.argtypes = [c_void_p, c_void_p, c_void_p]
-isl.isl_union_map_from_union_pw_multi_aff.restype = c_void_p
-isl.isl_union_map_from_union_pw_multi_aff.argtypes = [c_void_p]
-isl.isl_union_map_from_multi_union_pw_aff.restype = c_void_p
-isl.isl_union_map_from_multi_union_pw_aff.argtypes = [c_void_p]
-isl.isl_union_map_from_domain.restype = c_void_p
-isl.isl_union_map_from_domain.argtypes = [c_void_p]
-isl.isl_union_map_from_domain_and_range.restype = c_void_p
-isl.isl_union_map_from_domain_and_range.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_from_range.restype = c_void_p
-isl.isl_union_map_from_range.argtypes = [c_void_p]
-isl.isl_union_map_gist.restype = c_void_p
-isl.isl_union_map_gist.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_gist_domain.restype = c_void_p
-isl.isl_union_map_gist_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_gist_params.restype = c_void_p
-isl.isl_union_map_gist_params.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_gist_range.restype = c_void_p
-isl.isl_union_map_gist_range.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_intersect.restype = c_void_p
-isl.isl_union_map_intersect.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_intersect_domain.restype = c_void_p
-isl.isl_union_map_intersect_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_intersect_params.restype = c_void_p
-isl.isl_union_map_intersect_params.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_intersect_range.restype = c_void_p
-isl.isl_union_map_intersect_range.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_is_bijective.restype = c_bool
-isl.isl_union_map_is_bijective.argtypes = [c_void_p]
-isl.isl_union_map_is_empty.restype = c_bool
-isl.isl_union_map_is_empty.argtypes = [c_void_p]
-isl.isl_union_map_is_equal.restype = c_bool
-isl.isl_union_map_is_equal.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_is_injective.restype = c_bool
-isl.isl_union_map_is_injective.argtypes = [c_void_p]
-isl.isl_union_map_is_single_valued.restype = c_bool
-isl.isl_union_map_is_single_valued.argtypes = [c_void_p]
-isl.isl_union_map_is_strict_subset.restype = c_bool
-isl.isl_union_map_is_strict_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_is_subset.restype = c_bool
-isl.isl_union_map_is_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_lexmax.restype = c_void_p
-isl.isl_union_map_lexmax.argtypes = [c_void_p]
-isl.isl_union_map_lexmin.restype = c_void_p
-isl.isl_union_map_lexmin.argtypes = [c_void_p]
-isl.isl_union_map_polyhedral_hull.restype = c_void_p
-isl.isl_union_map_polyhedral_hull.argtypes = [c_void_p]
-isl.isl_union_map_product.restype = c_void_p
-isl.isl_union_map_product.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_project_out_all_params.restype = c_void_p
-isl.isl_union_map_project_out_all_params.argtypes = [c_void_p]
-isl.isl_union_map_range.restype = c_void_p
-isl.isl_union_map_range.argtypes = [c_void_p]
-isl.isl_union_map_range_factor_domain.restype = c_void_p
-isl.isl_union_map_range_factor_domain.argtypes = [c_void_p]
-isl.isl_union_map_range_factor_range.restype = c_void_p
-isl.isl_union_map_range_factor_range.argtypes = [c_void_p]
-isl.isl_union_map_range_map.restype = c_void_p
-isl.isl_union_map_range_map.argtypes = [c_void_p]
-isl.isl_union_map_range_product.restype = c_void_p
-isl.isl_union_map_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_reverse.restype = c_void_p
-isl.isl_union_map_reverse.argtypes = [c_void_p]
-isl.isl_union_map_subtract.restype = c_void_p
-isl.isl_union_map_subtract.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_subtract_domain.restype = c_void_p
-isl.isl_union_map_subtract_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_subtract_range.restype = c_void_p
-isl.isl_union_map_subtract_range.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_union.restype = c_void_p
-isl.isl_union_map_union.argtypes = [c_void_p, c_void_p]
-isl.isl_union_map_wrap.restype = c_void_p
-isl.isl_union_map_wrap.argtypes = [c_void_p]
-isl.isl_union_map_zip.restype = c_void_p
-isl.isl_union_map_zip.argtypes = [c_void_p]
-isl.isl_union_map_copy.restype = c_void_p
-isl.isl_union_map_copy.argtypes = [c_void_p]
-isl.isl_union_map_free.restype = c_void_p
-isl.isl_union_map_free.argtypes = [c_void_p]
-isl.isl_union_map_to_str.restype = POINTER(c_char)
-isl.isl_union_map_to_str.argtypes = [c_void_p]
+isl.isl_multi_aff_from_aff.restype = c_void_p
+isl.isl_multi_aff_from_aff.argtypes = [c_void_p]
+isl.isl_multi_aff_from_aff_list.restype = c_void_p
+isl.isl_multi_aff_from_aff_list.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_read_from_str.restype = c_void_p
+isl.isl_multi_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_aff_add.restype = c_void_p
+isl.isl_multi_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_add_constant_multi_val.restype = c_void_p
+isl.isl_multi_aff_add_constant_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_add_constant_val.restype = c_void_p
+isl.isl_multi_aff_add_constant_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_bind.restype = c_void_p
+isl.isl_multi_aff_bind.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_bind_domain.restype = c_void_p
+isl.isl_multi_aff_bind_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_bind_domain_wrapped_domain.restype = c_void_p
+isl.isl_multi_aff_bind_domain_wrapped_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_domain_map.restype = c_void_p
+isl.isl_multi_aff_domain_map.argtypes = [c_void_p]
+isl.isl_multi_aff_flat_range_product.restype = c_void_p
+isl.isl_multi_aff_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_floor.restype = c_void_p
+isl.isl_multi_aff_floor.argtypes = [c_void_p]
+isl.isl_multi_aff_get_at.restype = c_void_p
+isl.isl_multi_aff_get_at.argtypes = [c_void_p, c_int]
+isl.isl_multi_aff_get_constant_multi_val.restype = c_void_p
+isl.isl_multi_aff_get_constant_multi_val.argtypes = [c_void_p]
+isl.isl_multi_aff_get_space.restype = c_void_p
+isl.isl_multi_aff_get_space.argtypes = [c_void_p]
+isl.isl_multi_aff_gist.restype = c_void_p
+isl.isl_multi_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_identity_multi_aff.restype = c_void_p
+isl.isl_multi_aff_identity_multi_aff.argtypes = [c_void_p]
+isl.isl_multi_aff_identity_on_domain_space.restype = c_void_p
+isl.isl_multi_aff_identity_on_domain_space.argtypes = [c_void_p]
+isl.isl_multi_aff_involves_locals.argtypes = [c_void_p]
+isl.isl_multi_aff_neg.restype = c_void_p
+isl.isl_multi_aff_neg.argtypes = [c_void_p]
+isl.isl_multi_aff_plain_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_product.restype = c_void_p
+isl.isl_multi_aff_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_multi_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_range_map.restype = c_void_p
+isl.isl_multi_aff_range_map.argtypes = [c_void_p]
+isl.isl_multi_aff_range_product.restype = c_void_p
+isl.isl_multi_aff_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_scale_multi_val.restype = c_void_p
+isl.isl_multi_aff_scale_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_scale_val.restype = c_void_p
+isl.isl_multi_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_scale_down_multi_val.restype = c_void_p
+isl.isl_multi_aff_scale_down_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_scale_down_val.restype = c_void_p
+isl.isl_multi_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_set_at.restype = c_void_p
+isl.isl_multi_aff_set_at.argtypes = [c_void_p, c_int, c_void_p]
+isl.isl_multi_aff_size.argtypes = [c_void_p]
+isl.isl_multi_aff_sub.restype = c_void_p
+isl.isl_multi_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_aff_zero.restype = c_void_p
+isl.isl_multi_aff_zero.argtypes = [c_void_p]
+isl.isl_multi_aff_copy.restype = c_void_p
+isl.isl_multi_aff_copy.argtypes = [c_void_p]
+isl.isl_multi_aff_free.restype = c_void_p
+isl.isl_multi_aff_free.argtypes = [c_void_p]
+isl.isl_multi_aff_to_str.restype = POINTER(c_char)
+isl.isl_multi_aff_to_str.argtypes = [c_void_p]
 
-class map(union_map):
+class aff(pw_aff, multi_aff):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
@@ -2329,1950 +3104,9062 @@ def __init__(self, *args, **keywords):
             return
         if len(args) == 1 and type(args[0]) == str:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_map_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        if len(args) == 1 and args[0].__class__ is basic_map:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_map_from_basic_map(isl.isl_basic_map_copy(args[0].ptr))
+            self.ptr = isl.isl_aff_read_from_str(self.ctx, args[0].encode('ascii'))
             return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_map_free(self.ptr)
+            isl.isl_aff_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
         except:
             raise
-        ptr = isl.isl_map_to_str(arg0.ptr)
+        ptr = isl.isl_aff_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.map("""%s""")' % s
+            return 'isl.aff("""%s""")' % s
         else:
-            return 'isl.map("%s")' % s
-    def affine_hull(arg0):
-        try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
-        except:
-            raise
-        ctx = arg0.ctx
-        res = isl.isl_map_affine_hull(isl.isl_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def apply_domain(arg0, arg1):
+            return 'isl.aff("%s")' % s
+    def add(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
         except:
-            return union_map(arg0).apply_domain(arg1)
+            return pw_aff(arg0).add(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_apply_domain(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def apply_range(arg0, arg1):
+        res = isl.isl_aff_add(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def add_constant(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_aff_add_constant_val(isl.isl_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def bind(*args):
+        if len(args) == 2 and (args[1].__class__ is id or type(args[1]) == str):
+            args = list(args)
+            try:
+                if not args[1].__class__ is id:
+                    args[1] = id(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_aff_bind_id(isl.isl_aff_copy(args[0].ptr), isl.isl_id_copy(args[1].ptr))
+            obj = basic_set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def ceil(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_ceil(isl.isl_aff_copy(arg0.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def div(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).div(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_div(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def eq_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).eq_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_eq_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def eval(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is point:
+                arg1 = point(arg1)
+        except:
+            return pw_aff(arg0).eval(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_eval(isl.isl_aff_copy(arg0.ptr), isl.isl_point_copy(arg1.ptr))
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def floor(arg0):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_floor(isl.isl_aff_copy(arg0.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def ge_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).ge_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_ge_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return pw_aff(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_gist(isl.isl_aff_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def gt_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).gt_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_gt_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def le_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).le_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_le_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def lt_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).lt_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_lt_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def mod(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_aff_mod_val(isl.isl_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def mul(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).mul(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_mul(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def ne_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).ne_set(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_ne_set(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def neg(arg0):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_neg(isl.isl_aff_copy(arg0.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_aff_pullback_multi_aff(isl.isl_aff_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_aff_scale_val(isl.isl_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale_down(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_aff_scale_down_val(isl.isl_aff_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = aff(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def sub(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return pw_aff(arg0).sub(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_sub(isl.isl_aff_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def unbind_params_insert_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff:
+                arg0 = aff(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return pw_aff(arg0).unbind_params_insert_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_aff_unbind_params_insert_domain(isl.isl_aff_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_aff_read_from_str.restype = c_void_p
+isl.isl_aff_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_aff_add.restype = c_void_p
+isl.isl_aff_add.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_add_constant_val.restype = c_void_p
+isl.isl_aff_add_constant_val.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_bind_id.restype = c_void_p
+isl.isl_aff_bind_id.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_ceil.restype = c_void_p
+isl.isl_aff_ceil.argtypes = [c_void_p]
+isl.isl_aff_div.restype = c_void_p
+isl.isl_aff_div.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_eq_set.restype = c_void_p
+isl.isl_aff_eq_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_eval.restype = c_void_p
+isl.isl_aff_eval.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_floor.restype = c_void_p
+isl.isl_aff_floor.argtypes = [c_void_p]
+isl.isl_aff_ge_set.restype = c_void_p
+isl.isl_aff_ge_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_gist.restype = c_void_p
+isl.isl_aff_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_gt_set.restype = c_void_p
+isl.isl_aff_gt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_le_set.restype = c_void_p
+isl.isl_aff_le_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_lt_set.restype = c_void_p
+isl.isl_aff_lt_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_mod_val.restype = c_void_p
+isl.isl_aff_mod_val.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_mul.restype = c_void_p
+isl.isl_aff_mul.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_ne_set.restype = c_void_p
+isl.isl_aff_ne_set.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_neg.restype = c_void_p
+isl.isl_aff_neg.argtypes = [c_void_p]
+isl.isl_aff_pullback_multi_aff.restype = c_void_p
+isl.isl_aff_pullback_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_scale_val.restype = c_void_p
+isl.isl_aff_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_scale_down_val.restype = c_void_p
+isl.isl_aff_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_sub.restype = c_void_p
+isl.isl_aff_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_unbind_params_insert_domain.restype = c_void_p
+isl.isl_aff_unbind_params_insert_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_copy.restype = c_void_p
+isl.isl_aff_copy.argtypes = [c_void_p]
+isl.isl_aff_free.restype = c_void_p
+isl.isl_aff_free.argtypes = [c_void_p]
+isl.isl_aff_to_str.restype = POINTER(c_char)
+isl.isl_aff_to_str.argtypes = [c_void_p]
+
+class aff_list(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_aff_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and args[0].__class__ is aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_aff_list_from_aff(isl.isl_aff_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_aff_list_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is aff_list:
+                arg0 = aff_list(arg0)
+        except:
+            raise
+        ptr = isl.isl_aff_list_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.aff_list("""%s""")' % s
+        else:
+            return 'isl.aff_list("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff_list:
+                arg0 = aff_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_list_add(isl.isl_aff_list_copy(arg0.ptr), isl.isl_aff_copy(arg1.ptr))
+        obj = aff_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
+        try:
+            if not arg0.__class__ is aff_list:
+                arg0 = aff_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_list_clear(isl.isl_aff_list_copy(arg0.ptr))
+        obj = aff_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff_list:
+                arg0 = aff_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff_list:
+                arg1 = aff_list(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_list_concat(isl.isl_aff_list_copy(arg0.ptr), isl.isl_aff_list_copy(arg1.ptr))
+        obj = aff_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff_list:
+                arg0 = aff_list(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = aff(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_aff_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def at(arg0, arg1):
+        try:
+            if not arg0.__class__ is aff_list:
+                arg0 = aff_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_list_get_at(arg0.ptr, arg1)
+        obj = aff(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
+        try:
+            if not arg0.__class__ is aff_list:
+                arg0 = aff_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_aff_list_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+
+isl.isl_aff_list_alloc.restype = c_void_p
+isl.isl_aff_list_alloc.argtypes = [Context, c_int]
+isl.isl_aff_list_from_aff.restype = c_void_p
+isl.isl_aff_list_from_aff.argtypes = [c_void_p]
+isl.isl_aff_list_add.restype = c_void_p
+isl.isl_aff_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_list_clear.restype = c_void_p
+isl.isl_aff_list_clear.argtypes = [c_void_p]
+isl.isl_aff_list_concat.restype = c_void_p
+isl.isl_aff_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_aff_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_aff_list_get_at.restype = c_void_p
+isl.isl_aff_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_aff_list_size.argtypes = [c_void_p]
+isl.isl_aff_list_copy.restype = c_void_p
+isl.isl_aff_list_copy.argtypes = [c_void_p]
+isl.isl_aff_list_free.restype = c_void_p
+isl.isl_aff_list_free.argtypes = [c_void_p]
+isl.isl_aff_list_to_str.restype = POINTER(c_char)
+isl.isl_aff_list_to_str.argtypes = [c_void_p]
+
+class ast_build(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 0:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_ast_build_alloc(self.ctx)
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_build_free(self.ptr)
+    def copy_callbacks(self, obj):
+        if hasattr(obj, 'at_each_domain'):
+            self.at_each_domain = obj.at_each_domain
+    def set_at_each_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_build:
+                arg0 = ast_build(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1, cb_arg2):
+            cb_arg0 = ast_node(ctx=arg0.ctx, ptr=(cb_arg0))
+            cb_arg1 = ast_build(ctx=arg0.ctx, ptr=isl.isl_ast_build_copy(cb_arg1))
+            try:
+                res = arg1(cb_arg0, cb_arg1)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return None
+            return isl.isl_ast_node_copy(res.ptr)
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_ast_build_set_at_each_domain(isl.isl_ast_build_copy(arg0.ptr), cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if hasattr(arg0, 'at_each_domain') and arg0.at_each_domain['exc_info'] != None:
+            exc_info = arg0.at_each_domain['exc_info'][0]
+            arg0.at_each_domain['exc_info'][0] = None
+            if exc_info != None:
+                raise (exc_info[0], exc_info[1], exc_info[2])
+        obj = ast_build(ctx=ctx, ptr=res)
+        obj.copy_callbacks(arg0)
+        obj.at_each_domain = { 'func': cb, 'exc_info': exc_info }
+        return obj
+    def access_from(*args):
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_ast_build_access_from_multi_pw_aff(args[0].ptr, isl.isl_multi_pw_aff_copy(args[1].ptr))
+            if hasattr(args[0], 'at_each_domain') and args[0].at_each_domain['exc_info'] != None:
+                exc_info = args[0].at_each_domain['exc_info'][0]
+                args[0].at_each_domain['exc_info'][0] = None
+                if exc_info != None:
+                    raise (exc_info[0], exc_info[1], exc_info[2])
+            obj = ast_expr(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_ast_build_access_from_pw_multi_aff(args[0].ptr, isl.isl_pw_multi_aff_copy(args[1].ptr))
+            if hasattr(args[0], 'at_each_domain') and args[0].at_each_domain['exc_info'] != None:
+                exc_info = args[0].at_each_domain['exc_info'][0]
+                args[0].at_each_domain['exc_info'][0] = None
+                if exc_info != None:
+                    raise (exc_info[0], exc_info[1], exc_info[2])
+            obj = ast_expr(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def call_from(*args):
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_ast_build_call_from_multi_pw_aff(args[0].ptr, isl.isl_multi_pw_aff_copy(args[1].ptr))
+            if hasattr(args[0], 'at_each_domain') and args[0].at_each_domain['exc_info'] != None:
+                exc_info = args[0].at_each_domain['exc_info'][0]
+                args[0].at_each_domain['exc_info'][0] = None
+                if exc_info != None:
+                    raise (exc_info[0], exc_info[1], exc_info[2])
+            obj = ast_expr(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_ast_build_call_from_pw_multi_aff(args[0].ptr, isl.isl_pw_multi_aff_copy(args[1].ptr))
+            if hasattr(args[0], 'at_each_domain') and args[0].at_each_domain['exc_info'] != None:
+                exc_info = args[0].at_each_domain['exc_info'][0]
+                args[0].at_each_domain['exc_info'][0] = None
+                if exc_info != None:
+                    raise (exc_info[0], exc_info[1], exc_info[2])
+            obj = ast_expr(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def expr_from(*args):
+        if len(args) == 2 and args[1].__class__ is pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_ast_build_expr_from_pw_aff(args[0].ptr, isl.isl_pw_aff_copy(args[1].ptr))
+            if hasattr(args[0], 'at_each_domain') and args[0].at_each_domain['exc_info'] != None:
+                exc_info = args[0].at_each_domain['exc_info'][0]
+                args[0].at_each_domain['exc_info'][0] = None
+                if exc_info != None:
+                    raise (exc_info[0], exc_info[1], exc_info[2])
+            obj = ast_expr(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is set:
+            ctx = args[0].ctx
+            res = isl.isl_ast_build_expr_from_set(args[0].ptr, isl.isl_set_copy(args[1].ptr))
+            if hasattr(args[0], 'at_each_domain') and args[0].at_each_domain['exc_info'] != None:
+                exc_info = args[0].at_each_domain['exc_info'][0]
+                args[0].at_each_domain['exc_info'][0] = None
+                if exc_info != None:
+                    raise (exc_info[0], exc_info[1], exc_info[2])
+            obj = ast_expr(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    @staticmethod
+    def from_context(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_build_from_context(isl.isl_set_copy(arg0.ptr))
+        obj = ast_build(ctx=ctx, ptr=res)
+        return obj
+    def schedule(arg0):
+        try:
+            if not arg0.__class__ is ast_build:
+                arg0 = ast_build(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_build_get_schedule(arg0.ptr)
+        if hasattr(arg0, 'at_each_domain') and arg0.at_each_domain['exc_info'] != None:
+            exc_info = arg0.at_each_domain['exc_info'][0]
+            arg0.at_each_domain['exc_info'][0] = None
+            if exc_info != None:
+                raise (exc_info[0], exc_info[1], exc_info[2])
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_schedule(arg0):
+        return arg0.schedule()
+    def node_from(*args):
+        if len(args) == 2 and args[1].__class__ is schedule:
+            ctx = args[0].ctx
+            res = isl.isl_ast_build_node_from_schedule(args[0].ptr, isl.isl_schedule_copy(args[1].ptr))
+            if hasattr(args[0], 'at_each_domain') and args[0].at_each_domain['exc_info'] != None:
+                exc_info = args[0].at_each_domain['exc_info'][0]
+                args[0].at_each_domain['exc_info'][0] = None
+                if exc_info != None:
+                    raise (exc_info[0], exc_info[1], exc_info[2])
+            obj = ast_node(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def node_from_schedule_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_build:
+                arg0 = ast_build(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_build_node_from_schedule_map(arg0.ptr, isl.isl_union_map_copy(arg1.ptr))
+        if hasattr(arg0, 'at_each_domain') and arg0.at_each_domain['exc_info'] != None:
+            exc_info = arg0.at_each_domain['exc_info'][0]
+            arg0.at_each_domain['exc_info'][0] = None
+            if exc_info != None:
+                raise (exc_info[0], exc_info[1], exc_info[2])
+        obj = ast_node(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_ast_build_alloc.restype = c_void_p
+isl.isl_ast_build_alloc.argtypes = [Context]
+isl.isl_ast_build_set_at_each_domain.restype = c_void_p
+isl.isl_ast_build_set_at_each_domain.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_ast_build_access_from_multi_pw_aff.restype = c_void_p
+isl.isl_ast_build_access_from_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_access_from_pw_multi_aff.restype = c_void_p
+isl.isl_ast_build_access_from_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_call_from_multi_pw_aff.restype = c_void_p
+isl.isl_ast_build_call_from_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_call_from_pw_multi_aff.restype = c_void_p
+isl.isl_ast_build_call_from_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_expr_from_pw_aff.restype = c_void_p
+isl.isl_ast_build_expr_from_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_expr_from_set.restype = c_void_p
+isl.isl_ast_build_expr_from_set.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_from_context.restype = c_void_p
+isl.isl_ast_build_from_context.argtypes = [c_void_p]
+isl.isl_ast_build_get_schedule.restype = c_void_p
+isl.isl_ast_build_get_schedule.argtypes = [c_void_p]
+isl.isl_ast_build_node_from_schedule.restype = c_void_p
+isl.isl_ast_build_node_from_schedule.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_node_from_schedule_map.restype = c_void_p
+isl.isl_ast_build_node_from_schedule_map.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_build_copy.restype = c_void_p
+isl.isl_ast_build_copy.argtypes = [c_void_p]
+isl.isl_ast_build_free.restype = c_void_p
+isl.isl_ast_build_free.argtypes = [c_void_p]
+
+class ast_expr(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_id):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_int):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        if "ptr" in keywords:
+            type = isl.isl_ast_expr_get_type(keywords["ptr"])
+            if type == 0:
+                return ast_expr_op(**keywords)
+            if type == 1:
+                return ast_expr_id(**keywords)
+            if type == 2:
+                return ast_expr_int(**keywords)
+            raise
+        return super(ast_expr, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr("""%s""")' % s
+        else:
+            return 'isl.ast_expr("%s")' % s
+    def to_C_str(arg0):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_expr_to_C_str(arg0.ptr)
+        if res == 0:
+            raise
+        string = cast(res, c_char_p).value.decode('ascii')
+        libc.free(res)
+        return string
+
+isl.isl_ast_expr_to_C_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_C_str.argtypes = [c_void_p]
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+isl.isl_ast_expr_get_type.argtypes = [c_void_p]
+
+class ast_expr_id(ast_expr):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_id, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_id:
+                arg0 = ast_expr_id(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_id("""%s""")' % s
+        else:
+            return 'isl.ast_expr_id("%s")' % s
+    def id(arg0):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_expr_id_get_id(arg0.ptr)
+        obj = id(ctx=ctx, ptr=res)
+        return obj
+    def get_id(arg0):
+        return arg0.id()
+
+isl.isl_ast_expr_id_get_id.restype = c_void_p
+isl.isl_ast_expr_id_get_id.argtypes = [c_void_p]
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_int(ast_expr):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_int, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_int:
+                arg0 = ast_expr_int(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_int("""%s""")' % s
+        else:
+            return 'isl.ast_expr_int("%s")' % s
+    def val(arg0):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_expr_int_get_val(arg0.ptr)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def get_val(arg0):
+        return arg0.val()
+
+isl.isl_ast_expr_int_get_val.restype = c_void_p
+isl.isl_ast_expr_int_get_val.argtypes = [c_void_p]
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op(ast_expr):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_and):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_and_then):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_or):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_or_else):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_max):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_min):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_minus):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_add):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_sub):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_mul):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_div):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_fdiv_q):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_pdiv_q):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_pdiv_r):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_zdiv_r):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_cond):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_select):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_eq):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_le):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_lt):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_ge):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_gt):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_call):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_access):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_member):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_expr_op_address_of):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_expr_copy(args[0].ptr)
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        if "ptr" in keywords:
+            type = isl.isl_ast_expr_op_get_type(keywords["ptr"])
+            if type == 0:
+                return ast_expr_op_and(**keywords)
+            if type == 1:
+                return ast_expr_op_and_then(**keywords)
+            if type == 2:
+                return ast_expr_op_or(**keywords)
+            if type == 3:
+                return ast_expr_op_or_else(**keywords)
+            if type == 4:
+                return ast_expr_op_max(**keywords)
+            if type == 5:
+                return ast_expr_op_min(**keywords)
+            if type == 6:
+                return ast_expr_op_minus(**keywords)
+            if type == 7:
+                return ast_expr_op_add(**keywords)
+            if type == 8:
+                return ast_expr_op_sub(**keywords)
+            if type == 9:
+                return ast_expr_op_mul(**keywords)
+            if type == 10:
+                return ast_expr_op_div(**keywords)
+            if type == 11:
+                return ast_expr_op_fdiv_q(**keywords)
+            if type == 12:
+                return ast_expr_op_pdiv_q(**keywords)
+            if type == 13:
+                return ast_expr_op_pdiv_r(**keywords)
+            if type == 14:
+                return ast_expr_op_zdiv_r(**keywords)
+            if type == 15:
+                return ast_expr_op_cond(**keywords)
+            if type == 16:
+                return ast_expr_op_select(**keywords)
+            if type == 17:
+                return ast_expr_op_eq(**keywords)
+            if type == 18:
+                return ast_expr_op_le(**keywords)
+            if type == 19:
+                return ast_expr_op_lt(**keywords)
+            if type == 20:
+                return ast_expr_op_ge(**keywords)
+            if type == 21:
+                return ast_expr_op_gt(**keywords)
+            if type == 22:
+                return ast_expr_op_call(**keywords)
+            if type == 23:
+                return ast_expr_op_access(**keywords)
+            if type == 24:
+                return ast_expr_op_member(**keywords)
+            if type == 25:
+                return ast_expr_op_address_of(**keywords)
+            raise
+        return super(ast_expr_op, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op:
+                arg0 = ast_expr_op(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op("%s")' % s
+    def arg(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_expr_op_get_arg(arg0.ptr, arg1)
+        obj = ast_expr(ctx=ctx, ptr=res)
+        return obj
+    def get_arg(arg0, arg1):
+        return arg0.arg(arg1)
+    def n_arg(arg0):
+        try:
+            if not arg0.__class__ is ast_expr:
+                arg0 = ast_expr(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_expr_op_get_n_arg(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def get_n_arg(arg0):
+        return arg0.n_arg()
+
+isl.isl_ast_expr_op_get_arg.restype = c_void_p
+isl.isl_ast_expr_op_get_arg.argtypes = [c_void_p, c_int]
+isl.isl_ast_expr_op_get_n_arg.argtypes = [c_void_p]
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+isl.isl_ast_expr_op_get_type.argtypes = [c_void_p]
+
+class ast_expr_op_access(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_access, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_access:
+                arg0 = ast_expr_op_access(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_access("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_access("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_add(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_add, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_add:
+                arg0 = ast_expr_op_add(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_add("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_add("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_address_of(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_address_of, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_address_of:
+                arg0 = ast_expr_op_address_of(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_address_of("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_address_of("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_and(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_and, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_and:
+                arg0 = ast_expr_op_and(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_and("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_and("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_and_then(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_and_then, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_and_then:
+                arg0 = ast_expr_op_and_then(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_and_then("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_and_then("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_call(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_call, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_call:
+                arg0 = ast_expr_op_call(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_call("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_call("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_cond(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_cond, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_cond:
+                arg0 = ast_expr_op_cond(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_cond("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_cond("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_div(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_div, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_div:
+                arg0 = ast_expr_op_div(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_div("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_div("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_eq(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_eq, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_eq:
+                arg0 = ast_expr_op_eq(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_eq("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_eq("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_fdiv_q(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_fdiv_q, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_fdiv_q:
+                arg0 = ast_expr_op_fdiv_q(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_fdiv_q("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_fdiv_q("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_ge(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_ge, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_ge:
+                arg0 = ast_expr_op_ge(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_ge("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_ge("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_gt(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_gt, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_gt:
+                arg0 = ast_expr_op_gt(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_gt("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_gt("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_le(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_le, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_le:
+                arg0 = ast_expr_op_le(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_le("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_le("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_lt(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_lt, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_lt:
+                arg0 = ast_expr_op_lt(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_lt("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_lt("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_max(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_max, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_max:
+                arg0 = ast_expr_op_max(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_max("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_max("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_member(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_member, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_member:
+                arg0 = ast_expr_op_member(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_member("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_member("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_min(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_min, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_min:
+                arg0 = ast_expr_op_min(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_min("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_min("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_minus(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_minus, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_minus:
+                arg0 = ast_expr_op_minus(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_minus("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_minus("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_mul(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_mul, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_mul:
+                arg0 = ast_expr_op_mul(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_mul("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_mul("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_or(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_or, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_or:
+                arg0 = ast_expr_op_or(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_or("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_or("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_or_else(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_or_else, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_or_else:
+                arg0 = ast_expr_op_or_else(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_or_else("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_or_else("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_pdiv_q(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_pdiv_q, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_pdiv_q:
+                arg0 = ast_expr_op_pdiv_q(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_pdiv_q("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_pdiv_q("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_pdiv_r(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_pdiv_r, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_pdiv_r:
+                arg0 = ast_expr_op_pdiv_r(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_pdiv_r("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_pdiv_r("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_select(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_select, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_select:
+                arg0 = ast_expr_op_select(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_select("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_select("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_sub(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_sub, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_sub:
+                arg0 = ast_expr_op_sub(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_sub("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_sub("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_expr_op_zdiv_r(ast_expr_op):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_expr_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_expr_op_zdiv_r, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_expr_op_zdiv_r:
+                arg0 = ast_expr_op_zdiv_r(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_expr_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_expr_op_zdiv_r("""%s""")' % s
+        else:
+            return 'isl.ast_expr_op_zdiv_r("%s")' % s
+
+isl.isl_ast_expr_copy.restype = c_void_p
+isl.isl_ast_expr_copy.argtypes = [c_void_p]
+isl.isl_ast_expr_free.restype = c_void_p
+isl.isl_ast_expr_free.argtypes = [c_void_p]
+isl.isl_ast_expr_to_str.restype = POINTER(c_char)
+isl.isl_ast_expr_to_str.argtypes = [c_void_p]
+
+class ast_node(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and isinstance(args[0], ast_node_for):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_node_if):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_node_block):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_node_mark):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], ast_node_user):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_ast_node_copy(args[0].ptr)
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        if "ptr" in keywords:
+            type = isl.isl_ast_node_get_type(keywords["ptr"])
+            if type == 1:
+                return ast_node_for(**keywords)
+            if type == 2:
+                return ast_node_if(**keywords)
+            if type == 3:
+                return ast_node_block(**keywords)
+            if type == 4:
+                return ast_node_mark(**keywords)
+            if type == 5:
+                return ast_node_user(**keywords)
+            raise
+        return super(ast_node, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node("""%s""")' % s
+        else:
+            return 'isl.ast_node("%s")' % s
+    def to_C_str(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_to_C_str(arg0.ptr)
+        if res == 0:
+            raise
+        string = cast(res, c_char_p).value.decode('ascii')
+        libc.free(res)
+        return string
+
+isl.isl_ast_node_to_C_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_C_str.argtypes = [c_void_p]
+isl.isl_ast_node_copy.restype = c_void_p
+isl.isl_ast_node_copy.argtypes = [c_void_p]
+isl.isl_ast_node_free.restype = c_void_p
+isl.isl_ast_node_free.argtypes = [c_void_p]
+isl.isl_ast_node_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_str.argtypes = [c_void_p]
+isl.isl_ast_node_get_type.argtypes = [c_void_p]
+
+class ast_node_block(ast_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_node_block, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node_block:
+                arg0 = ast_node_block(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node_block("""%s""")' % s
+        else:
+            return 'isl.ast_node_block("%s")' % s
+    def children(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_block_get_children(arg0.ptr)
+        obj = ast_node_list(ctx=ctx, ptr=res)
+        return obj
+    def get_children(arg0):
+        return arg0.children()
+
+isl.isl_ast_node_block_get_children.restype = c_void_p
+isl.isl_ast_node_block_get_children.argtypes = [c_void_p]
+isl.isl_ast_node_copy.restype = c_void_p
+isl.isl_ast_node_copy.argtypes = [c_void_p]
+isl.isl_ast_node_free.restype = c_void_p
+isl.isl_ast_node_free.argtypes = [c_void_p]
+isl.isl_ast_node_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_str.argtypes = [c_void_p]
+
+class ast_node_for(ast_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_node_for, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node_for:
+                arg0 = ast_node_for(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node_for("""%s""")' % s
+        else:
+            return 'isl.ast_node_for("%s")' % s
+    def body(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_for_get_body(arg0.ptr)
+        obj = ast_node(ctx=ctx, ptr=res)
+        return obj
+    def get_body(arg0):
+        return arg0.body()
+    def cond(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_for_get_cond(arg0.ptr)
+        obj = ast_expr(ctx=ctx, ptr=res)
+        return obj
+    def get_cond(arg0):
+        return arg0.cond()
+    def inc(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_for_get_inc(arg0.ptr)
+        obj = ast_expr(ctx=ctx, ptr=res)
+        return obj
+    def get_inc(arg0):
+        return arg0.inc()
+    def init(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_for_get_init(arg0.ptr)
+        obj = ast_expr(ctx=ctx, ptr=res)
+        return obj
+    def get_init(arg0):
+        return arg0.init()
+    def iterator(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_for_get_iterator(arg0.ptr)
+        obj = ast_expr(ctx=ctx, ptr=res)
+        return obj
+    def get_iterator(arg0):
+        return arg0.iterator()
+    def is_degenerate(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_for_is_degenerate(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+
+isl.isl_ast_node_for_get_body.restype = c_void_p
+isl.isl_ast_node_for_get_body.argtypes = [c_void_p]
+isl.isl_ast_node_for_get_cond.restype = c_void_p
+isl.isl_ast_node_for_get_cond.argtypes = [c_void_p]
+isl.isl_ast_node_for_get_inc.restype = c_void_p
+isl.isl_ast_node_for_get_inc.argtypes = [c_void_p]
+isl.isl_ast_node_for_get_init.restype = c_void_p
+isl.isl_ast_node_for_get_init.argtypes = [c_void_p]
+isl.isl_ast_node_for_get_iterator.restype = c_void_p
+isl.isl_ast_node_for_get_iterator.argtypes = [c_void_p]
+isl.isl_ast_node_for_is_degenerate.argtypes = [c_void_p]
+isl.isl_ast_node_copy.restype = c_void_p
+isl.isl_ast_node_copy.argtypes = [c_void_p]
+isl.isl_ast_node_free.restype = c_void_p
+isl.isl_ast_node_free.argtypes = [c_void_p]
+isl.isl_ast_node_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_str.argtypes = [c_void_p]
+
+class ast_node_if(ast_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_node_if, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node_if:
+                arg0 = ast_node_if(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node_if("""%s""")' % s
+        else:
+            return 'isl.ast_node_if("%s")' % s
+    def cond(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_if_get_cond(arg0.ptr)
+        obj = ast_expr(ctx=ctx, ptr=res)
+        return obj
+    def get_cond(arg0):
+        return arg0.cond()
+    def else_node(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_if_get_else_node(arg0.ptr)
+        obj = ast_node(ctx=ctx, ptr=res)
+        return obj
+    def get_else_node(arg0):
+        return arg0.else_node()
+    def then_node(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_if_get_then_node(arg0.ptr)
+        obj = ast_node(ctx=ctx, ptr=res)
+        return obj
+    def get_then_node(arg0):
+        return arg0.then_node()
+    def has_else_node(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_if_has_else_node(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+
+isl.isl_ast_node_if_get_cond.restype = c_void_p
+isl.isl_ast_node_if_get_cond.argtypes = [c_void_p]
+isl.isl_ast_node_if_get_else_node.restype = c_void_p
+isl.isl_ast_node_if_get_else_node.argtypes = [c_void_p]
+isl.isl_ast_node_if_get_then_node.restype = c_void_p
+isl.isl_ast_node_if_get_then_node.argtypes = [c_void_p]
+isl.isl_ast_node_if_has_else_node.argtypes = [c_void_p]
+isl.isl_ast_node_copy.restype = c_void_p
+isl.isl_ast_node_copy.argtypes = [c_void_p]
+isl.isl_ast_node_free.restype = c_void_p
+isl.isl_ast_node_free.argtypes = [c_void_p]
+isl.isl_ast_node_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_str.argtypes = [c_void_p]
+
+class ast_node_list(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_ast_node_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and args[0].__class__ is ast_node:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_ast_node_list_from_ast_node(isl.isl_ast_node_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_list_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node_list:
+                arg0 = ast_node_list(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_list_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node_list("""%s""")' % s
+        else:
+            return 'isl.ast_node_list("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_node_list:
+                arg0 = ast_node_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is ast_node:
+                arg1 = ast_node(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_list_add(isl.isl_ast_node_list_copy(arg0.ptr), isl.isl_ast_node_copy(arg1.ptr))
+        obj = ast_node_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
+        try:
+            if not arg0.__class__ is ast_node_list:
+                arg0 = ast_node_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_list_clear(isl.isl_ast_node_list_copy(arg0.ptr))
+        obj = ast_node_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_node_list:
+                arg0 = ast_node_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is ast_node_list:
+                arg1 = ast_node_list(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_list_concat(isl.isl_ast_node_list_copy(arg0.ptr), isl.isl_ast_node_list_copy(arg1.ptr))
+        obj = ast_node_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_node_list:
+                arg0 = ast_node_list(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = ast_node(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def at(arg0, arg1):
+        try:
+            if not arg0.__class__ is ast_node_list:
+                arg0 = ast_node_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_list_get_at(arg0.ptr, arg1)
+        obj = ast_node(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
+        try:
+            if not arg0.__class__ is ast_node_list:
+                arg0 = ast_node_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_list_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+
+isl.isl_ast_node_list_alloc.restype = c_void_p
+isl.isl_ast_node_list_alloc.argtypes = [Context, c_int]
+isl.isl_ast_node_list_from_ast_node.restype = c_void_p
+isl.isl_ast_node_list_from_ast_node.argtypes = [c_void_p]
+isl.isl_ast_node_list_add.restype = c_void_p
+isl.isl_ast_node_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_node_list_clear.restype = c_void_p
+isl.isl_ast_node_list_clear.argtypes = [c_void_p]
+isl.isl_ast_node_list_concat.restype = c_void_p
+isl.isl_ast_node_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_ast_node_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_ast_node_list_get_at.restype = c_void_p
+isl.isl_ast_node_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_ast_node_list_size.argtypes = [c_void_p]
+isl.isl_ast_node_list_copy.restype = c_void_p
+isl.isl_ast_node_list_copy.argtypes = [c_void_p]
+isl.isl_ast_node_list_free.restype = c_void_p
+isl.isl_ast_node_list_free.argtypes = [c_void_p]
+isl.isl_ast_node_list_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_list_to_str.argtypes = [c_void_p]
+
+class ast_node_mark(ast_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_node_mark, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node_mark:
+                arg0 = ast_node_mark(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node_mark("""%s""")' % s
+        else:
+            return 'isl.ast_node_mark("%s")' % s
+    def id(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_mark_get_id(arg0.ptr)
+        obj = id(ctx=ctx, ptr=res)
+        return obj
+    def get_id(arg0):
+        return arg0.id()
+    def node(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_mark_get_node(arg0.ptr)
+        obj = ast_node(ctx=ctx, ptr=res)
+        return obj
+    def get_node(arg0):
+        return arg0.node()
+
+isl.isl_ast_node_mark_get_id.restype = c_void_p
+isl.isl_ast_node_mark_get_id.argtypes = [c_void_p]
+isl.isl_ast_node_mark_get_node.restype = c_void_p
+isl.isl_ast_node_mark_get_node.argtypes = [c_void_p]
+isl.isl_ast_node_copy.restype = c_void_p
+isl.isl_ast_node_copy.argtypes = [c_void_p]
+isl.isl_ast_node_free.restype = c_void_p
+isl.isl_ast_node_free.argtypes = [c_void_p]
+isl.isl_ast_node_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_str.argtypes = [c_void_p]
+
+class ast_node_user(ast_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_ast_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(ast_node_user, cls).__new__(cls)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is ast_node_user:
+                arg0 = ast_node_user(arg0)
+        except:
+            raise
+        ptr = isl.isl_ast_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.ast_node_user("""%s""")' % s
+        else:
+            return 'isl.ast_node_user("%s")' % s
+    def expr(arg0):
+        try:
+            if not arg0.__class__ is ast_node:
+                arg0 = ast_node(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_ast_node_user_get_expr(arg0.ptr)
+        obj = ast_expr(ctx=ctx, ptr=res)
+        return obj
+    def get_expr(arg0):
+        return arg0.expr()
+
+isl.isl_ast_node_user_get_expr.restype = c_void_p
+isl.isl_ast_node_user_get_expr.argtypes = [c_void_p]
+isl.isl_ast_node_copy.restype = c_void_p
+isl.isl_ast_node_copy.argtypes = [c_void_p]
+isl.isl_ast_node_free.restype = c_void_p
+isl.isl_ast_node_free.argtypes = [c_void_p]
+isl.isl_ast_node_to_str.restype = POINTER(c_char)
+isl.isl_ast_node_to_str.argtypes = [c_void_p]
+
+class union_map(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is basic_map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_map_from_basic_map(isl.isl_basic_map_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_map_from_map(isl.isl_map_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_map_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_map_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_map_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_map("""%s""")' % s
+        else:
+            return 'isl.union_map("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_affine_hull(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def apply_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_apply_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def apply_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_apply_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def bind_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_bind_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_coalesce(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def compute_divs(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_compute_divs(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def curry(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_curry(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def deltas(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_deltas(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_detect_equalities(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def domain_factor_domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_factor_domain(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def domain_factor_range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_factor_range(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def domain_map(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_map(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def domain_map_union_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_map_union_pw_multi_aff(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def domain_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_domain_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def empty(*args):
+        if len(args) == 0:
+            ctx = Context.getDefaultInstance()
+            res = isl.isl_union_map_empty_ctx(ctx)
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def eq_at(*args):
+        if len(args) == 2 and args[1].__class__ is multi_union_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_eq_at_multi_union_pw_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_multi_union_pw_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def every_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = map(ctx=arg0.ctx, ptr=isl.isl_map_copy(cb_arg0))
+            try:
+                res = arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 1 if res else 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_map_every_map(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+        return bool(res)
+    def extract_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is space:
+                arg1 = space(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_extract_map(arg0.ptr, isl.isl_space_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def factor_domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_factor_domain(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def factor_range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_factor_range(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def fixed_power(*args):
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_union_map_fixed_power_val(isl.isl_union_map_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def foreach_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = map(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_map_foreach_map(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    @staticmethod
+    def convert_from(*args):
+        if len(args) == 1 and args[0].__class__ is multi_union_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_from_multi_union_pw_aff(isl.isl_multi_union_pw_aff_copy(args[0].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 1 and args[0].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_from_union_pw_multi_aff(isl.isl_union_pw_multi_aff_copy(args[0].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    @staticmethod
+    def from_domain(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_from_domain(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def from_domain_and_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_from_domain_and_range(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def from_range(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_from_range(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def space(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def gist_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def gist_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist_params(isl.isl_union_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def gist_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_gist_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect_params(isl.isl_union_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_intersect_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def is_bijective(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_bijective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_disjoint(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_disjoint(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_injective(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_injective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_single_valued(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_single_valued(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def isa_map(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_isa_map(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_lexmax(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_lexmin(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def polyhedral_hull(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_polyhedral_hull(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def preimage_domain(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_preimage_domain_multi_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_preimage_domain_multi_pw_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_preimage_domain_pw_multi_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_preimage_domain_union_pw_multi_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_union_pw_multi_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def preimage_range(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_preimage_range_multi_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_preimage_range_pw_multi_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_map_preimage_range_union_pw_multi_aff(isl.isl_union_map_copy(args[0].ptr), isl.isl_union_pw_multi_aff_copy(args[1].ptr))
+            obj = union_map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def product(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def project_out_all_params(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_project_out_all_params(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def range_factor_domain(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_factor_domain(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def range_factor_range(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_factor_range(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def range_map(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_map(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_product(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def range_reverse(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_range_reverse(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def reverse(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_reverse(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_subtract(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def subtract_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_subtract_domain(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def subtract_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_subtract_range(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def uncurry(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_uncurry(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_union(isl.isl_union_map_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def universe(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_universe(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def wrap(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_wrap(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def zip(arg0):
+        try:
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_map_zip(isl.isl_union_map_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_union_map_from_basic_map.restype = c_void_p
+isl.isl_union_map_from_basic_map.argtypes = [c_void_p]
+isl.isl_union_map_from_map.restype = c_void_p
+isl.isl_union_map_from_map.argtypes = [c_void_p]
+isl.isl_union_map_read_from_str.restype = c_void_p
+isl.isl_union_map_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_union_map_affine_hull.restype = c_void_p
+isl.isl_union_map_affine_hull.argtypes = [c_void_p]
+isl.isl_union_map_apply_domain.restype = c_void_p
+isl.isl_union_map_apply_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_apply_range.restype = c_void_p
+isl.isl_union_map_apply_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_bind_range.restype = c_void_p
+isl.isl_union_map_bind_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_coalesce.restype = c_void_p
+isl.isl_union_map_coalesce.argtypes = [c_void_p]
+isl.isl_union_map_compute_divs.restype = c_void_p
+isl.isl_union_map_compute_divs.argtypes = [c_void_p]
+isl.isl_union_map_curry.restype = c_void_p
+isl.isl_union_map_curry.argtypes = [c_void_p]
+isl.isl_union_map_deltas.restype = c_void_p
+isl.isl_union_map_deltas.argtypes = [c_void_p]
+isl.isl_union_map_detect_equalities.restype = c_void_p
+isl.isl_union_map_detect_equalities.argtypes = [c_void_p]
+isl.isl_union_map_domain.restype = c_void_p
+isl.isl_union_map_domain.argtypes = [c_void_p]
+isl.isl_union_map_domain_factor_domain.restype = c_void_p
+isl.isl_union_map_domain_factor_domain.argtypes = [c_void_p]
+isl.isl_union_map_domain_factor_range.restype = c_void_p
+isl.isl_union_map_domain_factor_range.argtypes = [c_void_p]
+isl.isl_union_map_domain_map.restype = c_void_p
+isl.isl_union_map_domain_map.argtypes = [c_void_p]
+isl.isl_union_map_domain_map_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_domain_map_union_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_union_map_domain_product.restype = c_void_p
+isl.isl_union_map_domain_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_empty_ctx.restype = c_void_p
+isl.isl_union_map_empty_ctx.argtypes = [Context]
+isl.isl_union_map_eq_at_multi_union_pw_aff.restype = c_void_p
+isl.isl_union_map_eq_at_multi_union_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_every_map.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_map_extract_map.restype = c_void_p
+isl.isl_union_map_extract_map.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_factor_domain.restype = c_void_p
+isl.isl_union_map_factor_domain.argtypes = [c_void_p]
+isl.isl_union_map_factor_range.restype = c_void_p
+isl.isl_union_map_factor_range.argtypes = [c_void_p]
+isl.isl_union_map_fixed_power_val.restype = c_void_p
+isl.isl_union_map_fixed_power_val.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_foreach_map.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_map_from_multi_union_pw_aff.restype = c_void_p
+isl.isl_union_map_from_multi_union_pw_aff.argtypes = [c_void_p]
+isl.isl_union_map_from_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_from_union_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_union_map_from_domain.restype = c_void_p
+isl.isl_union_map_from_domain.argtypes = [c_void_p]
+isl.isl_union_map_from_domain_and_range.restype = c_void_p
+isl.isl_union_map_from_domain_and_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_from_range.restype = c_void_p
+isl.isl_union_map_from_range.argtypes = [c_void_p]
+isl.isl_union_map_get_space.restype = c_void_p
+isl.isl_union_map_get_space.argtypes = [c_void_p]
+isl.isl_union_map_gist.restype = c_void_p
+isl.isl_union_map_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_gist_domain.restype = c_void_p
+isl.isl_union_map_gist_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_gist_params.restype = c_void_p
+isl.isl_union_map_gist_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_gist_range.restype = c_void_p
+isl.isl_union_map_gist_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect.restype = c_void_p
+isl.isl_union_map_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect_domain.restype = c_void_p
+isl.isl_union_map_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect_params.restype = c_void_p
+isl.isl_union_map_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_intersect_range.restype = c_void_p
+isl.isl_union_map_intersect_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_is_bijective.argtypes = [c_void_p]
+isl.isl_union_map_is_disjoint.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_is_empty.argtypes = [c_void_p]
+isl.isl_union_map_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_is_injective.argtypes = [c_void_p]
+isl.isl_union_map_is_single_valued.argtypes = [c_void_p]
+isl.isl_union_map_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_isa_map.argtypes = [c_void_p]
+isl.isl_union_map_lexmax.restype = c_void_p
+isl.isl_union_map_lexmax.argtypes = [c_void_p]
+isl.isl_union_map_lexmin.restype = c_void_p
+isl.isl_union_map_lexmin.argtypes = [c_void_p]
+isl.isl_union_map_polyhedral_hull.restype = c_void_p
+isl.isl_union_map_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_union_map_preimage_domain_multi_aff.restype = c_void_p
+isl.isl_union_map_preimage_domain_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_preimage_domain_multi_pw_aff.restype = c_void_p
+isl.isl_union_map_preimage_domain_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_preimage_domain_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_preimage_domain_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_preimage_domain_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_preimage_domain_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_preimage_range_multi_aff.restype = c_void_p
+isl.isl_union_map_preimage_range_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_preimage_range_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_preimage_range_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_preimage_range_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_map_preimage_range_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_product.restype = c_void_p
+isl.isl_union_map_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_project_out_all_params.restype = c_void_p
+isl.isl_union_map_project_out_all_params.argtypes = [c_void_p]
+isl.isl_union_map_range.restype = c_void_p
+isl.isl_union_map_range.argtypes = [c_void_p]
+isl.isl_union_map_range_factor_domain.restype = c_void_p
+isl.isl_union_map_range_factor_domain.argtypes = [c_void_p]
+isl.isl_union_map_range_factor_range.restype = c_void_p
+isl.isl_union_map_range_factor_range.argtypes = [c_void_p]
+isl.isl_union_map_range_map.restype = c_void_p
+isl.isl_union_map_range_map.argtypes = [c_void_p]
+isl.isl_union_map_range_product.restype = c_void_p
+isl.isl_union_map_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_range_reverse.restype = c_void_p
+isl.isl_union_map_range_reverse.argtypes = [c_void_p]
+isl.isl_union_map_reverse.restype = c_void_p
+isl.isl_union_map_reverse.argtypes = [c_void_p]
+isl.isl_union_map_subtract.restype = c_void_p
+isl.isl_union_map_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_subtract_domain.restype = c_void_p
+isl.isl_union_map_subtract_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_subtract_range.restype = c_void_p
+isl.isl_union_map_subtract_range.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_uncurry.restype = c_void_p
+isl.isl_union_map_uncurry.argtypes = [c_void_p]
+isl.isl_union_map_union.restype = c_void_p
+isl.isl_union_map_union.argtypes = [c_void_p, c_void_p]
+isl.isl_union_map_universe.restype = c_void_p
+isl.isl_union_map_universe.argtypes = [c_void_p]
+isl.isl_union_map_wrap.restype = c_void_p
+isl.isl_union_map_wrap.argtypes = [c_void_p]
+isl.isl_union_map_zip.restype = c_void_p
+isl.isl_union_map_zip.argtypes = [c_void_p]
+isl.isl_union_map_copy.restype = c_void_p
+isl.isl_union_map_copy.argtypes = [c_void_p]
+isl.isl_union_map_free.restype = c_void_p
+isl.isl_union_map_free.argtypes = [c_void_p]
+isl.isl_union_map_to_str.restype = POINTER(c_char)
+isl.isl_union_map_to_str.argtypes = [c_void_p]
+
+class map(union_map):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is basic_map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_map_from_basic_map(isl.isl_basic_map_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_map_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_map_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ptr = isl.isl_map_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.map("""%s""")' % s
+        else:
+            return 'isl.map("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_affine_hull(isl.isl_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def apply_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).apply_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_apply_domain(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def apply_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).apply_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_apply_range(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def bind_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_map(arg0).bind_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_bind_domain(isl.isl_map_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def bind_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_map(arg0).bind_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_bind_range(isl.isl_map_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_coalesce(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def complement(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_complement(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def curry(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_curry(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def deltas(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_deltas(isl.isl_map_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_detect_equalities(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def domain(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_domain(isl.isl_map_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def domain_factor_domain(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_domain_factor_domain(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def domain_factor_range(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_domain_factor_range(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def domain_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).domain_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_domain_product(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def empty(arg0):
+        try:
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_empty(isl.isl_space_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def factor_domain(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_factor_domain(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def factor_range(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_factor_range(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def flatten(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_flatten(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def flatten_domain(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_flatten_domain(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def flatten_range(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_flatten_range(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def foreach_basic_map(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = basic_map(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_map_foreach_basic_map(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def range_simple_fixed_box_hull(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_get_range_simple_fixed_box_hull(arg0.ptr)
+        obj = fixed_box(ctx=ctx, ptr=res)
+        return obj
+    def get_range_simple_fixed_box_hull(arg0):
+        return arg0.range_simple_fixed_box_hull()
+    def space(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_gist(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def gist_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).gist_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_gist_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).intersect(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).intersect_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).intersect_params(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect_params(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_map(arg0).intersect_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_intersect_range(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def is_bijective(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_bijective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_disjoint(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_disjoint(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_disjoint(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_equal(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_injective(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_injective(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_single_valued(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_is_single_valued(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_strict_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).is_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_lexmax(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def lexmax_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_lexmax_pw_multi_aff(isl.isl_map_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_lexmin(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def lexmin_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_lexmin_pw_multi_aff(isl.isl_map_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def lower_bound(*args):
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_map_lower_bound_multi_pw_aff(isl.isl_map_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_map_lower_bound_multi_val(isl.isl_map_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def polyhedral_hull(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_polyhedral_hull(isl.isl_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def preimage_domain(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_map_preimage_domain_multi_aff(isl.isl_map_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_map_preimage_domain_multi_pw_aff(isl.isl_map_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_map_preimage_domain_pw_multi_aff(isl.isl_map_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def preimage_range(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_map_preimage_range_multi_aff(isl.isl_map_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_map_preimage_range_pw_multi_aff(isl.isl_map_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def project_out_all_params(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_project_out_all_params(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def range(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_range(isl.isl_map_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def range_factor_domain(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_range_factor_domain(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def range_factor_range(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_range_factor_range(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).range_product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_range_product(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def range_reverse(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_range_reverse(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def reverse(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_reverse(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def sample(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_sample(isl.isl_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).subtract(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_subtract(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def uncurry(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_uncurry(isl.isl_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_map(arg0).union(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_map_union(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def universe(arg0):
+        try:
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_universe(isl.isl_space_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def unshifted_simple_hull(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_unshifted_simple_hull(isl.isl_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def upper_bound(*args):
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_map_upper_bound_multi_pw_aff(isl.isl_map_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_map_upper_bound_multi_val(isl.isl_map_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = map(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def wrap(arg0):
+        try:
+            if not arg0.__class__ is map:
+                arg0 = map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_map_wrap(isl.isl_map_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_map_from_basic_map.restype = c_void_p
+isl.isl_map_from_basic_map.argtypes = [c_void_p]
+isl.isl_map_read_from_str.restype = c_void_p
+isl.isl_map_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_map_affine_hull.restype = c_void_p
+isl.isl_map_affine_hull.argtypes = [c_void_p]
+isl.isl_map_apply_domain.restype = c_void_p
+isl.isl_map_apply_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_map_apply_range.restype = c_void_p
+isl.isl_map_apply_range.argtypes = [c_void_p, c_void_p]
+isl.isl_map_bind_domain.restype = c_void_p
+isl.isl_map_bind_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_map_bind_range.restype = c_void_p
+isl.isl_map_bind_range.argtypes = [c_void_p, c_void_p]
+isl.isl_map_coalesce.restype = c_void_p
+isl.isl_map_coalesce.argtypes = [c_void_p]
+isl.isl_map_complement.restype = c_void_p
+isl.isl_map_complement.argtypes = [c_void_p]
+isl.isl_map_curry.restype = c_void_p
+isl.isl_map_curry.argtypes = [c_void_p]
+isl.isl_map_deltas.restype = c_void_p
+isl.isl_map_deltas.argtypes = [c_void_p]
+isl.isl_map_detect_equalities.restype = c_void_p
+isl.isl_map_detect_equalities.argtypes = [c_void_p]
+isl.isl_map_domain.restype = c_void_p
+isl.isl_map_domain.argtypes = [c_void_p]
+isl.isl_map_domain_factor_domain.restype = c_void_p
+isl.isl_map_domain_factor_domain.argtypes = [c_void_p]
+isl.isl_map_domain_factor_range.restype = c_void_p
+isl.isl_map_domain_factor_range.argtypes = [c_void_p]
+isl.isl_map_domain_product.restype = c_void_p
+isl.isl_map_domain_product.argtypes = [c_void_p, c_void_p]
+isl.isl_map_empty.restype = c_void_p
+isl.isl_map_empty.argtypes = [c_void_p]
+isl.isl_map_factor_domain.restype = c_void_p
+isl.isl_map_factor_domain.argtypes = [c_void_p]
+isl.isl_map_factor_range.restype = c_void_p
+isl.isl_map_factor_range.argtypes = [c_void_p]
+isl.isl_map_flatten.restype = c_void_p
+isl.isl_map_flatten.argtypes = [c_void_p]
+isl.isl_map_flatten_domain.restype = c_void_p
+isl.isl_map_flatten_domain.argtypes = [c_void_p]
+isl.isl_map_flatten_range.restype = c_void_p
+isl.isl_map_flatten_range.argtypes = [c_void_p]
+isl.isl_map_foreach_basic_map.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_map_get_range_simple_fixed_box_hull.restype = c_void_p
+isl.isl_map_get_range_simple_fixed_box_hull.argtypes = [c_void_p]
+isl.isl_map_get_space.restype = c_void_p
+isl.isl_map_get_space.argtypes = [c_void_p]
+isl.isl_map_gist.restype = c_void_p
+isl.isl_map_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_map_gist_domain.restype = c_void_p
+isl.isl_map_gist_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect.restype = c_void_p
+isl.isl_map_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect_domain.restype = c_void_p
+isl.isl_map_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect_params.restype = c_void_p
+isl.isl_map_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_map_intersect_range.restype = c_void_p
+isl.isl_map_intersect_range.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_bijective.argtypes = [c_void_p]
+isl.isl_map_is_disjoint.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_empty.argtypes = [c_void_p]
+isl.isl_map_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_injective.argtypes = [c_void_p]
+isl.isl_map_is_single_valued.argtypes = [c_void_p]
+isl.isl_map_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_map_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_map_lexmax.restype = c_void_p
+isl.isl_map_lexmax.argtypes = [c_void_p]
+isl.isl_map_lexmax_pw_multi_aff.restype = c_void_p
+isl.isl_map_lexmax_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_map_lexmin.restype = c_void_p
+isl.isl_map_lexmin.argtypes = [c_void_p]
+isl.isl_map_lexmin_pw_multi_aff.restype = c_void_p
+isl.isl_map_lexmin_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_map_lower_bound_multi_pw_aff.restype = c_void_p
+isl.isl_map_lower_bound_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_map_lower_bound_multi_val.restype = c_void_p
+isl.isl_map_lower_bound_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_map_polyhedral_hull.restype = c_void_p
+isl.isl_map_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_map_preimage_domain_multi_aff.restype = c_void_p
+isl.isl_map_preimage_domain_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_map_preimage_domain_multi_pw_aff.restype = c_void_p
+isl.isl_map_preimage_domain_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_map_preimage_domain_pw_multi_aff.restype = c_void_p
+isl.isl_map_preimage_domain_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_map_preimage_range_multi_aff.restype = c_void_p
+isl.isl_map_preimage_range_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_map_preimage_range_pw_multi_aff.restype = c_void_p
+isl.isl_map_preimage_range_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_map_project_out_all_params.restype = c_void_p
+isl.isl_map_project_out_all_params.argtypes = [c_void_p]
+isl.isl_map_range.restype = c_void_p
+isl.isl_map_range.argtypes = [c_void_p]
+isl.isl_map_range_factor_domain.restype = c_void_p
+isl.isl_map_range_factor_domain.argtypes = [c_void_p]
+isl.isl_map_range_factor_range.restype = c_void_p
+isl.isl_map_range_factor_range.argtypes = [c_void_p]
+isl.isl_map_range_product.restype = c_void_p
+isl.isl_map_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_map_range_reverse.restype = c_void_p
+isl.isl_map_range_reverse.argtypes = [c_void_p]
+isl.isl_map_reverse.restype = c_void_p
+isl.isl_map_reverse.argtypes = [c_void_p]
+isl.isl_map_sample.restype = c_void_p
+isl.isl_map_sample.argtypes = [c_void_p]
+isl.isl_map_subtract.restype = c_void_p
+isl.isl_map_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_map_uncurry.restype = c_void_p
+isl.isl_map_uncurry.argtypes = [c_void_p]
+isl.isl_map_union.restype = c_void_p
+isl.isl_map_union.argtypes = [c_void_p, c_void_p]
+isl.isl_map_universe.restype = c_void_p
+isl.isl_map_universe.argtypes = [c_void_p]
+isl.isl_map_unshifted_simple_hull.restype = c_void_p
+isl.isl_map_unshifted_simple_hull.argtypes = [c_void_p]
+isl.isl_map_upper_bound_multi_pw_aff.restype = c_void_p
+isl.isl_map_upper_bound_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_map_upper_bound_multi_val.restype = c_void_p
+isl.isl_map_upper_bound_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_map_wrap.restype = c_void_p
+isl.isl_map_wrap.argtypes = [c_void_p]
+isl.isl_map_copy.restype = c_void_p
+isl.isl_map_copy.argtypes = [c_void_p]
+isl.isl_map_free.restype = c_void_p
+isl.isl_map_free.argtypes = [c_void_p]
+isl.isl_map_to_str.restype = POINTER(c_char)
+isl.isl_map_to_str.argtypes = [c_void_p]
+
+class basic_map(map):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_basic_map_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_basic_map_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ptr = isl.isl_basic_map_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.basic_map("""%s""")' % s
+        else:
+            return 'isl.basic_map("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_affine_hull(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def apply_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).apply_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_apply_domain(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def apply_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).apply_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_apply_range(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def deltas(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_deltas(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_detect_equalities(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def flatten(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_flatten(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def flatten_domain(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_flatten_domain(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def flatten_range(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_flatten_range(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_gist(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).intersect(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_intersect(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return map(arg0).intersect_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_intersect_domain(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect_range(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return map(arg0).intersect_range(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_intersect_range(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).is_equal(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).is_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_lexmax(isl.isl_basic_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_lexmin(isl.isl_basic_map_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def reverse(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_reverse(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def sample(arg0):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_sample(isl.isl_basic_map_copy(arg0.ptr))
+        obj = basic_map(ctx=ctx, ptr=res)
+        return obj
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_map:
+                arg0 = basic_map(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return map(arg0).union(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_map_union(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_basic_map_read_from_str.restype = c_void_p
+isl.isl_basic_map_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_basic_map_affine_hull.restype = c_void_p
+isl.isl_basic_map_affine_hull.argtypes = [c_void_p]
+isl.isl_basic_map_apply_domain.restype = c_void_p
+isl.isl_basic_map_apply_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_apply_range.restype = c_void_p
+isl.isl_basic_map_apply_range.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_deltas.restype = c_void_p
+isl.isl_basic_map_deltas.argtypes = [c_void_p]
+isl.isl_basic_map_detect_equalities.restype = c_void_p
+isl.isl_basic_map_detect_equalities.argtypes = [c_void_p]
+isl.isl_basic_map_flatten.restype = c_void_p
+isl.isl_basic_map_flatten.argtypes = [c_void_p]
+isl.isl_basic_map_flatten_domain.restype = c_void_p
+isl.isl_basic_map_flatten_domain.argtypes = [c_void_p]
+isl.isl_basic_map_flatten_range.restype = c_void_p
+isl.isl_basic_map_flatten_range.argtypes = [c_void_p]
+isl.isl_basic_map_gist.restype = c_void_p
+isl.isl_basic_map_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_intersect.restype = c_void_p
+isl.isl_basic_map_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_intersect_domain.restype = c_void_p
+isl.isl_basic_map_intersect_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_intersect_range.restype = c_void_p
+isl.isl_basic_map_intersect_range.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_is_empty.argtypes = [c_void_p]
+isl.isl_basic_map_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_lexmax.restype = c_void_p
+isl.isl_basic_map_lexmax.argtypes = [c_void_p]
+isl.isl_basic_map_lexmin.restype = c_void_p
+isl.isl_basic_map_lexmin.argtypes = [c_void_p]
+isl.isl_basic_map_reverse.restype = c_void_p
+isl.isl_basic_map_reverse.argtypes = [c_void_p]
+isl.isl_basic_map_sample.restype = c_void_p
+isl.isl_basic_map_sample.argtypes = [c_void_p]
+isl.isl_basic_map_union.restype = c_void_p
+isl.isl_basic_map_union.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_map_copy.restype = c_void_p
+isl.isl_basic_map_copy.argtypes = [c_void_p]
+isl.isl_basic_map_free.restype = c_void_p
+isl.isl_basic_map_free.argtypes = [c_void_p]
+isl.isl_basic_map_to_str.restype = POINTER(c_char)
+isl.isl_basic_map_to_str.argtypes = [c_void_p]
+
+class union_set(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is basic_set:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_from_basic_set(isl.isl_basic_set_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is point:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_from_point(isl.isl_point_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is set:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_from_set(isl.isl_set_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_set_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_set_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_set("""%s""")' % s
+        else:
+            return 'isl.union_set("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_affine_hull(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def apply(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_apply(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_coalesce(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def compute_divs(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_compute_divs(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_detect_equalities(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def empty(*args):
+        if len(args) == 0:
+            ctx = Context.getDefaultInstance()
+            res = isl.isl_union_set_empty_ctx(ctx)
+            obj = union_set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def every_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = set(ctx=arg0.ctx, ptr=isl.isl_set_copy(cb_arg0))
+            try:
+                res = arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 1 if res else 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_set_every_set(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+        return bool(res)
+    def extract_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is space:
+                arg1 = space(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_extract_set(arg0.ptr, isl.isl_space_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def foreach_point(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = point(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_set_foreach_point(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def foreach_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = set(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_union_set_foreach_set(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def space(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_gist(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def gist_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_gist_params(isl.isl_union_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def identity(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_identity(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_intersect(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_intersect_params(isl.isl_union_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def is_disjoint(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_disjoint(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def isa_set(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_isa_set(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_lexmax(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_lexmin(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def polyhedral_hull(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_polyhedral_hull(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def preimage(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_set_preimage_multi_aff(isl.isl_union_set_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = union_set(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_set_preimage_pw_multi_aff(isl.isl_union_set_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = union_set(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_union_set_preimage_union_pw_multi_aff(isl.isl_union_set_copy(args[0].ptr), isl.isl_union_pw_multi_aff_copy(args[1].ptr))
+            obj = union_set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def sample_point(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_sample_point(isl.isl_union_set_copy(arg0.ptr))
+        obj = point(ctx=ctx, ptr=res)
+        return obj
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_subtract(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_union(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def universe(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_universe(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def unwrap(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_set_unwrap(isl.isl_union_set_copy(arg0.ptr))
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_union_set_from_basic_set.restype = c_void_p
+isl.isl_union_set_from_basic_set.argtypes = [c_void_p]
+isl.isl_union_set_from_point.restype = c_void_p
+isl.isl_union_set_from_point.argtypes = [c_void_p]
+isl.isl_union_set_from_set.restype = c_void_p
+isl.isl_union_set_from_set.argtypes = [c_void_p]
+isl.isl_union_set_read_from_str.restype = c_void_p
+isl.isl_union_set_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_union_set_affine_hull.restype = c_void_p
+isl.isl_union_set_affine_hull.argtypes = [c_void_p]
+isl.isl_union_set_apply.restype = c_void_p
+isl.isl_union_set_apply.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_coalesce.restype = c_void_p
+isl.isl_union_set_coalesce.argtypes = [c_void_p]
+isl.isl_union_set_compute_divs.restype = c_void_p
+isl.isl_union_set_compute_divs.argtypes = [c_void_p]
+isl.isl_union_set_detect_equalities.restype = c_void_p
+isl.isl_union_set_detect_equalities.argtypes = [c_void_p]
+isl.isl_union_set_empty_ctx.restype = c_void_p
+isl.isl_union_set_empty_ctx.argtypes = [Context]
+isl.isl_union_set_every_set.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_set_extract_set.restype = c_void_p
+isl.isl_union_set_extract_set.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_foreach_point.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_set_foreach_set.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_set_get_space.restype = c_void_p
+isl.isl_union_set_get_space.argtypes = [c_void_p]
+isl.isl_union_set_gist.restype = c_void_p
+isl.isl_union_set_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_gist_params.restype = c_void_p
+isl.isl_union_set_gist_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_identity.restype = c_void_p
+isl.isl_union_set_identity.argtypes = [c_void_p]
+isl.isl_union_set_intersect.restype = c_void_p
+isl.isl_union_set_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_intersect_params.restype = c_void_p
+isl.isl_union_set_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_is_disjoint.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_is_empty.argtypes = [c_void_p]
+isl.isl_union_set_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_isa_set.argtypes = [c_void_p]
+isl.isl_union_set_lexmax.restype = c_void_p
+isl.isl_union_set_lexmax.argtypes = [c_void_p]
+isl.isl_union_set_lexmin.restype = c_void_p
+isl.isl_union_set_lexmin.argtypes = [c_void_p]
+isl.isl_union_set_polyhedral_hull.restype = c_void_p
+isl.isl_union_set_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_union_set_preimage_multi_aff.restype = c_void_p
+isl.isl_union_set_preimage_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_preimage_pw_multi_aff.restype = c_void_p
+isl.isl_union_set_preimage_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_preimage_union_pw_multi_aff.restype = c_void_p
+isl.isl_union_set_preimage_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_sample_point.restype = c_void_p
+isl.isl_union_set_sample_point.argtypes = [c_void_p]
+isl.isl_union_set_subtract.restype = c_void_p
+isl.isl_union_set_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_union.restype = c_void_p
+isl.isl_union_set_union.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_universe.restype = c_void_p
+isl.isl_union_set_universe.argtypes = [c_void_p]
+isl.isl_union_set_unwrap.restype = c_void_p
+isl.isl_union_set_unwrap.argtypes = [c_void_p]
+isl.isl_union_set_copy.restype = c_void_p
+isl.isl_union_set_copy.argtypes = [c_void_p]
+isl.isl_union_set_free.restype = c_void_p
+isl.isl_union_set_free.argtypes = [c_void_p]
+isl.isl_union_set_to_str.restype = POINTER(c_char)
+isl.isl_union_set_to_str.argtypes = [c_void_p]
+
+class set(union_set):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is basic_set:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_set_from_basic_set(isl.isl_basic_set_copy(args[0].ptr))
+            return
+        if len(args) == 1 and args[0].__class__ is point:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_set_from_point(isl.isl_point_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_set_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_set_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ptr = isl.isl_set_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.set("""%s""")' % s
+        else:
+            return 'isl.set("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_affine_hull(isl.isl_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def apply(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is map:
+                arg1 = map(arg1)
+        except:
+            return union_set(arg0).apply(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_apply(isl.isl_set_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def bind(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_set(arg0).bind(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_bind(isl.isl_set_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def coalesce(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_coalesce(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def complement(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_complement(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_detect_equalities(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def empty(arg0):
+        try:
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_empty(isl.isl_space_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def flatten(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_flatten(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def foreach_basic_set(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = basic_set(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_set_foreach_basic_set(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def foreach_point(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = point(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_set_foreach_point(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def plain_multi_val_if_fixed(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_get_plain_multi_val_if_fixed(arg0.ptr)
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def get_plain_multi_val_if_fixed(arg0):
+        return arg0.plain_multi_val_if_fixed()
+    def simple_fixed_box_hull(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_get_simple_fixed_box_hull(arg0.ptr)
+        obj = fixed_box(ctx=ctx, ptr=res)
+        return obj
+    def get_simple_fixed_box_hull(arg0):
+        return arg0.simple_fixed_box_hull()
+    def space(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def stride(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_get_stride(arg0.ptr, arg1)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def get_stride(arg0, arg1):
+        return arg0.stride(arg1)
+    def gist(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).gist(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_gist(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def identity(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_identity(isl.isl_set_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def indicator_function(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_indicator_function(isl.isl_set_copy(arg0.ptr))
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def intersect(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).intersect(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_intersect(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).intersect_params(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_intersect_params(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def is_disjoint(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_disjoint(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_disjoint(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_empty(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_equal(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_singleton(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_is_singleton(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_strict_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_strict_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_strict_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).is_subset(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_wrapping(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_is_wrapping(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_lexmax(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def lexmax_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_lexmax_pw_multi_aff(isl.isl_set_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def lexmin(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_lexmin(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def lexmin_pw_multi_aff(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_lexmin_pw_multi_aff(isl.isl_set_copy(arg0.ptr))
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def lower_bound(*args):
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_set_lower_bound_multi_pw_aff(isl.isl_set_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_set_lower_bound_multi_val(isl.isl_set_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def max_val(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return union_set(arg0).max_val(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_max_val(arg0.ptr, arg1.ptr)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def min_val(arg0, arg1):
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
         except:
-            return union_map(arg0).apply_range(arg1)
+            raise
+        try:
+            if not arg1.__class__ is aff:
+                arg1 = aff(arg1)
+        except:
+            return union_set(arg0).min_val(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_apply_range(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def coalesce(arg0):
+        res = isl.isl_set_min_val(arg0.ptr, arg1.ptr)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def params(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_coalesce(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def complement(arg0):
+        res = isl.isl_set_params(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def polyhedral_hull(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_complement(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def deltas(arg0):
+        res = isl.isl_set_polyhedral_hull(isl.isl_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def preimage(*args):
+        if len(args) == 2 and args[1].__class__ is multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_set_preimage_multi_aff(isl.isl_set_copy(args[0].ptr), isl.isl_multi_aff_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_set_preimage_multi_pw_aff(isl.isl_set_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_set_preimage_pw_multi_aff(isl.isl_set_copy(args[0].ptr), isl.isl_pw_multi_aff_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def product(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).product(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_product(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def project_out_all_params(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_project_out_all_params(isl.isl_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def project_out_param(*args):
+        if len(args) == 2 and (args[1].__class__ is id or type(args[1]) == str):
+            args = list(args)
+            try:
+                if not args[1].__class__ is id:
+                    args[1] = id(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_set_project_out_param_id(isl.isl_set_copy(args[0].ptr), isl.isl_id_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is id_list:
+            ctx = args[0].ctx
+            res = isl.isl_set_project_out_param_id_list(isl.isl_set_copy(args[0].ptr), isl.isl_id_list_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def sample(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_sample(isl.isl_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def sample_point(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_sample_point(isl.isl_set_copy(arg0.ptr))
+        obj = point(ctx=ctx, ptr=res)
+        return obj
+    def subtract(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).subtract(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_subtract(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def unbind_params(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_set(arg0).unbind_params(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_unbind_params(isl.isl_set_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def unbind_params_insert_domain(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            return union_set(arg0).unbind_params_insert_domain(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_unbind_params_insert_domain(isl.isl_set_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def union(arg0, arg1):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
+        except:
+            return union_set(arg0).union(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_set_union(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def universe(arg0):
+        try:
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_universe(isl.isl_space_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def unshifted_simple_hull(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_unshifted_simple_hull(isl.isl_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def unwrap(arg0):
+        try:
+            if not arg0.__class__ is set:
+                arg0 = set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_set_unwrap(isl.isl_set_copy(arg0.ptr))
+        obj = map(ctx=ctx, ptr=res)
+        return obj
+    def upper_bound(*args):
+        if len(args) == 2 and args[1].__class__ is multi_pw_aff:
+            ctx = args[0].ctx
+            res = isl.isl_set_upper_bound_multi_pw_aff(isl.isl_set_copy(args[0].ptr), isl.isl_multi_pw_aff_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_set_upper_bound_multi_val(isl.isl_set_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = set(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+
+isl.isl_set_from_basic_set.restype = c_void_p
+isl.isl_set_from_basic_set.argtypes = [c_void_p]
+isl.isl_set_from_point.restype = c_void_p
+isl.isl_set_from_point.argtypes = [c_void_p]
+isl.isl_set_read_from_str.restype = c_void_p
+isl.isl_set_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_set_affine_hull.restype = c_void_p
+isl.isl_set_affine_hull.argtypes = [c_void_p]
+isl.isl_set_apply.restype = c_void_p
+isl.isl_set_apply.argtypes = [c_void_p, c_void_p]
+isl.isl_set_bind.restype = c_void_p
+isl.isl_set_bind.argtypes = [c_void_p, c_void_p]
+isl.isl_set_coalesce.restype = c_void_p
+isl.isl_set_coalesce.argtypes = [c_void_p]
+isl.isl_set_complement.restype = c_void_p
+isl.isl_set_complement.argtypes = [c_void_p]
+isl.isl_set_detect_equalities.restype = c_void_p
+isl.isl_set_detect_equalities.argtypes = [c_void_p]
+isl.isl_set_empty.restype = c_void_p
+isl.isl_set_empty.argtypes = [c_void_p]
+isl.isl_set_flatten.restype = c_void_p
+isl.isl_set_flatten.argtypes = [c_void_p]
+isl.isl_set_foreach_basic_set.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_set_foreach_point.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_set_get_plain_multi_val_if_fixed.restype = c_void_p
+isl.isl_set_get_plain_multi_val_if_fixed.argtypes = [c_void_p]
+isl.isl_set_get_simple_fixed_box_hull.restype = c_void_p
+isl.isl_set_get_simple_fixed_box_hull.argtypes = [c_void_p]
+isl.isl_set_get_space.restype = c_void_p
+isl.isl_set_get_space.argtypes = [c_void_p]
+isl.isl_set_get_stride.restype = c_void_p
+isl.isl_set_get_stride.argtypes = [c_void_p, c_int]
+isl.isl_set_gist.restype = c_void_p
+isl.isl_set_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_set_identity.restype = c_void_p
+isl.isl_set_identity.argtypes = [c_void_p]
+isl.isl_set_indicator_function.restype = c_void_p
+isl.isl_set_indicator_function.argtypes = [c_void_p]
+isl.isl_set_intersect.restype = c_void_p
+isl.isl_set_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_set_intersect_params.restype = c_void_p
+isl.isl_set_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_disjoint.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_empty.argtypes = [c_void_p]
+isl.isl_set_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_singleton.argtypes = [c_void_p]
+isl.isl_set_is_strict_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_set_is_wrapping.argtypes = [c_void_p]
+isl.isl_set_lexmax.restype = c_void_p
+isl.isl_set_lexmax.argtypes = [c_void_p]
+isl.isl_set_lexmax_pw_multi_aff.restype = c_void_p
+isl.isl_set_lexmax_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_set_lexmin.restype = c_void_p
+isl.isl_set_lexmin.argtypes = [c_void_p]
+isl.isl_set_lexmin_pw_multi_aff.restype = c_void_p
+isl.isl_set_lexmin_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_set_lower_bound_multi_pw_aff.restype = c_void_p
+isl.isl_set_lower_bound_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_set_lower_bound_multi_val.restype = c_void_p
+isl.isl_set_lower_bound_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_set_max_val.restype = c_void_p
+isl.isl_set_max_val.argtypes = [c_void_p, c_void_p]
+isl.isl_set_min_val.restype = c_void_p
+isl.isl_set_min_val.argtypes = [c_void_p, c_void_p]
+isl.isl_set_params.restype = c_void_p
+isl.isl_set_params.argtypes = [c_void_p]
+isl.isl_set_polyhedral_hull.restype = c_void_p
+isl.isl_set_polyhedral_hull.argtypes = [c_void_p]
+isl.isl_set_preimage_multi_aff.restype = c_void_p
+isl.isl_set_preimage_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_set_preimage_multi_pw_aff.restype = c_void_p
+isl.isl_set_preimage_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_set_preimage_pw_multi_aff.restype = c_void_p
+isl.isl_set_preimage_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_set_product.restype = c_void_p
+isl.isl_set_product.argtypes = [c_void_p, c_void_p]
+isl.isl_set_project_out_all_params.restype = c_void_p
+isl.isl_set_project_out_all_params.argtypes = [c_void_p]
+isl.isl_set_project_out_param_id.restype = c_void_p
+isl.isl_set_project_out_param_id.argtypes = [c_void_p, c_void_p]
+isl.isl_set_project_out_param_id_list.restype = c_void_p
+isl.isl_set_project_out_param_id_list.argtypes = [c_void_p, c_void_p]
+isl.isl_set_sample.restype = c_void_p
+isl.isl_set_sample.argtypes = [c_void_p]
+isl.isl_set_sample_point.restype = c_void_p
+isl.isl_set_sample_point.argtypes = [c_void_p]
+isl.isl_set_subtract.restype = c_void_p
+isl.isl_set_subtract.argtypes = [c_void_p, c_void_p]
+isl.isl_set_unbind_params.restype = c_void_p
+isl.isl_set_unbind_params.argtypes = [c_void_p, c_void_p]
+isl.isl_set_unbind_params_insert_domain.restype = c_void_p
+isl.isl_set_unbind_params_insert_domain.argtypes = [c_void_p, c_void_p]
+isl.isl_set_union.restype = c_void_p
+isl.isl_set_union.argtypes = [c_void_p, c_void_p]
+isl.isl_set_universe.restype = c_void_p
+isl.isl_set_universe.argtypes = [c_void_p]
+isl.isl_set_unshifted_simple_hull.restype = c_void_p
+isl.isl_set_unshifted_simple_hull.argtypes = [c_void_p]
+isl.isl_set_unwrap.restype = c_void_p
+isl.isl_set_unwrap.argtypes = [c_void_p]
+isl.isl_set_upper_bound_multi_pw_aff.restype = c_void_p
+isl.isl_set_upper_bound_multi_pw_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_set_upper_bound_multi_val.restype = c_void_p
+isl.isl_set_upper_bound_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_set_copy.restype = c_void_p
+isl.isl_set_copy.argtypes = [c_void_p]
+isl.isl_set_free.restype = c_void_p
+isl.isl_set_free.argtypes = [c_void_p]
+isl.isl_set_to_str.restype = POINTER(c_char)
+isl.isl_set_to_str.argtypes = [c_void_p]
+
+class basic_set(set):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is point:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_basic_set_from_point(isl.isl_point_copy(args[0].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_basic_set_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_basic_set_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ptr = isl.isl_basic_set_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.basic_set("""%s""")' % s
+        else:
+            return 'isl.basic_set("%s")' % s
+    def affine_hull(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_affine_hull(isl.isl_basic_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def apply(arg0, arg1):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is basic_map:
+                arg1 = basic_map(arg1)
+        except:
+            return set(arg0).apply(arg1)
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_apply(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def detect_equalities(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_deltas(isl.isl_map_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def detect_equalities(arg0):
+        res = isl.isl_basic_set_detect_equalities(isl.isl_basic_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def dim_max_val(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_detect_equalities(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
+        res = isl.isl_basic_set_dim_max_val(isl.isl_basic_set_copy(arg0.ptr), arg1)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def flatten(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_flatten(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def flatten_domain(arg0):
+        res = isl.isl_basic_set_flatten(isl.isl_basic_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def gist(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_map_flatten_domain(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def flatten_range(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
         except:
-            raise
+            return set(arg0).gist(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_flatten_range(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def foreach_basic_map(arg0, arg1):
+        res = isl.isl_basic_set_gist(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def intersect(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
-        exc_info = [None]
-        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
-        def cb_func(cb_arg0, cb_arg1):
-            cb_arg0 = basic_map(ctx=arg0.ctx, ptr=(cb_arg0))
-            try:
-                arg1(cb_arg0)
-            except:
-                import sys
-                exc_info[0] = sys.exc_info()
-                return -1
-            return 0
-        cb = fn(cb_func)
+        try:
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
+        except:
+            return set(arg0).intersect(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_foreach_basic_map(arg0.ptr, cb, None)
-        if exc_info[0] != None:
-            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
-        return res
-    def gist(arg0, arg1):
+        res = isl.isl_basic_set_intersect(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def intersect_params(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
         except:
-            return union_map(arg0).gist(arg1)
+            return set(arg0).intersect_params(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_gist(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def gist_domain(arg0, arg1):
+        res = isl.isl_basic_set_intersect_params(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def is_empty(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
-        except:
-            return union_map(arg0).gist_domain(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_gist_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def intersect(arg0, arg1):
+        res = isl.isl_basic_set_is_empty(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_equal(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
         except:
-            return union_map(arg0).intersect(arg1)
+            return set(arg0).is_equal(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_intersect(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def intersect_domain(arg0, arg1):
+        res = isl.isl_basic_set_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_subset(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
         except:
-            return union_map(arg0).intersect_domain(arg1)
+            return set(arg0).is_subset(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_intersect_domain(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def intersect_params(arg0, arg1):
+        res = isl.isl_basic_set_is_subset(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_wrapping(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_is_wrapping(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def lexmax(arg0):
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
-            return union_map(arg0).intersect_params(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_map_intersect_params(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def intersect_range(arg0, arg1):
+        res = isl.isl_basic_set_lexmax(isl.isl_basic_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def lexmin(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_lexmin(isl.isl_basic_set_copy(arg0.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def params(arg0):
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
-            return union_map(arg0).intersect_range(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_map_intersect_range(isl.isl_map_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def is_bijective(arg0):
+        res = isl.isl_basic_set_params(isl.isl_basic_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def sample(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_is_bijective(arg0.ptr)
-        if res < 0:
+        res = isl.isl_basic_set_sample(isl.isl_basic_set_copy(arg0.ptr))
+        obj = basic_set(ctx=ctx, ptr=res)
+        return obj
+    def sample_point(arg0):
+        try:
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
+        except:
             raise
-        return bool(res)
-    def is_disjoint(arg0, arg1):
+        ctx = arg0.ctx
+        res = isl.isl_basic_set_sample_point(isl.isl_basic_set_copy(arg0.ptr))
+        obj = point(ctx=ctx, ptr=res)
+        return obj
+    def union(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is basic_set:
+                arg0 = basic_set(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg1.__class__ is basic_set:
+                arg1 = basic_set(arg1)
         except:
-            return union_map(arg0).is_disjoint(arg1)
+            return set(arg0).union(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_is_disjoint(arg0.ptr, arg1.ptr)
-        if res < 0:
+        res = isl.isl_basic_set_union(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_basic_set_from_point.restype = c_void_p
+isl.isl_basic_set_from_point.argtypes = [c_void_p]
+isl.isl_basic_set_read_from_str.restype = c_void_p
+isl.isl_basic_set_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_basic_set_affine_hull.restype = c_void_p
+isl.isl_basic_set_affine_hull.argtypes = [c_void_p]
+isl.isl_basic_set_apply.restype = c_void_p
+isl.isl_basic_set_apply.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_detect_equalities.restype = c_void_p
+isl.isl_basic_set_detect_equalities.argtypes = [c_void_p]
+isl.isl_basic_set_dim_max_val.restype = c_void_p
+isl.isl_basic_set_dim_max_val.argtypes = [c_void_p, c_int]
+isl.isl_basic_set_flatten.restype = c_void_p
+isl.isl_basic_set_flatten.argtypes = [c_void_p]
+isl.isl_basic_set_gist.restype = c_void_p
+isl.isl_basic_set_gist.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_intersect.restype = c_void_p
+isl.isl_basic_set_intersect.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_intersect_params.restype = c_void_p
+isl.isl_basic_set_intersect_params.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_is_empty.argtypes = [c_void_p]
+isl.isl_basic_set_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_is_subset.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_is_wrapping.argtypes = [c_void_p]
+isl.isl_basic_set_lexmax.restype = c_void_p
+isl.isl_basic_set_lexmax.argtypes = [c_void_p]
+isl.isl_basic_set_lexmin.restype = c_void_p
+isl.isl_basic_set_lexmin.argtypes = [c_void_p]
+isl.isl_basic_set_params.restype = c_void_p
+isl.isl_basic_set_params.argtypes = [c_void_p]
+isl.isl_basic_set_sample.restype = c_void_p
+isl.isl_basic_set_sample.argtypes = [c_void_p]
+isl.isl_basic_set_sample_point.restype = c_void_p
+isl.isl_basic_set_sample_point.argtypes = [c_void_p]
+isl.isl_basic_set_union.restype = c_void_p
+isl.isl_basic_set_union.argtypes = [c_void_p, c_void_p]
+isl.isl_basic_set_copy.restype = c_void_p
+isl.isl_basic_set_copy.argtypes = [c_void_p]
+isl.isl_basic_set_free.restype = c_void_p
+isl.isl_basic_set_free.argtypes = [c_void_p]
+isl.isl_basic_set_to_str.restype = POINTER(c_char)
+isl.isl_basic_set_to_str.argtypes = [c_void_p]
+
+class fixed_box(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_fixed_box_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is fixed_box:
+                arg0 = fixed_box(arg0)
+        except:
             raise
-        return bool(res)
-    def is_empty(arg0):
+        ptr = isl.isl_fixed_box_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.fixed_box("""%s""")' % s
+        else:
+            return 'isl.fixed_box("%s")' % s
+    def offset(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is fixed_box:
+                arg0 = fixed_box(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_is_empty(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_equal(arg0, arg1):
+        res = isl.isl_fixed_box_get_offset(arg0.ptr)
+        obj = multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_offset(arg0):
+        return arg0.offset()
+    def size(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is fixed_box:
+                arg0 = fixed_box(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
-        except:
-            return union_map(arg0).is_equal(arg1)
         ctx = arg0.ctx
-        res = isl.isl_map_is_equal(arg0.ptr, arg1.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_injective(arg0):
+        res = isl.isl_fixed_box_get_size(arg0.ptr)
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def get_size(arg0):
+        return arg0.size()
+    def space(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is fixed_box:
+                arg0 = fixed_box(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_is_injective(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_single_valued(arg0):
+        res = isl.isl_fixed_box_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def is_valid(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is fixed_box:
+                arg0 = fixed_box(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_is_single_valued(arg0.ptr)
+        res = isl.isl_fixed_box_is_valid(arg0.ptr)
         if res < 0:
             raise
         return bool(res)
-    def is_strict_subset(arg0, arg1):
+
+isl.isl_fixed_box_get_offset.restype = c_void_p
+isl.isl_fixed_box_get_offset.argtypes = [c_void_p]
+isl.isl_fixed_box_get_size.restype = c_void_p
+isl.isl_fixed_box_get_size.argtypes = [c_void_p]
+isl.isl_fixed_box_get_space.restype = c_void_p
+isl.isl_fixed_box_get_space.argtypes = [c_void_p]
+isl.isl_fixed_box_is_valid.argtypes = [c_void_p]
+isl.isl_fixed_box_copy.restype = c_void_p
+isl.isl_fixed_box_copy.argtypes = [c_void_p]
+isl.isl_fixed_box_free.restype = c_void_p
+isl.isl_fixed_box_free.argtypes = [c_void_p]
+isl.isl_fixed_box_to_str.restype = POINTER(c_char)
+isl.isl_fixed_box_to_str.argtypes = [c_void_p]
+
+class id(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_id_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_id_free(self.ptr)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is id:
+                arg0 = id(arg0)
         except:
             raise
+        ptr = isl.isl_id_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.id("""%s""")' % s
+        else:
+            return 'isl.id("%s")' % s
+    def name(arg0):
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg0.__class__ is id:
+                arg0 = id(arg0)
         except:
-            return union_map(arg0).is_strict_subset(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_map_is_strict_subset(arg0.ptr, arg1.ptr)
-        if res < 0:
+        res = isl.isl_id_get_name(arg0.ptr)
+        if res == 0:
             raise
-        return bool(res)
-    def is_subset(arg0, arg1):
+        string = cast(res, c_char_p).value.decode('ascii')
+        return string
+    def get_name(arg0):
+        return arg0.name()
+
+isl.isl_id_read_from_str.restype = c_void_p
+isl.isl_id_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_id_get_name.restype = POINTER(c_char)
+isl.isl_id_get_name.argtypes = [c_void_p]
+isl.isl_id_copy.restype = c_void_p
+isl.isl_id_copy.argtypes = [c_void_p]
+isl.isl_id_free.restype = c_void_p
+isl.isl_id_free.argtypes = [c_void_p]
+isl.isl_id_to_str.restype = POINTER(c_char)
+isl.isl_id_to_str.argtypes = [c_void_p]
+
+class id_list(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_id_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and (args[0].__class__ is id or type(args[0]) == str):
+            args = list(args)
+            try:
+                if not args[0].__class__ is id:
+                    args[0] = id(args[0])
+            except:
+                raise
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_id_list_from_id(isl.isl_id_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_id_list_free(self.ptr)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is id_list:
+                arg0 = id_list(arg0)
         except:
             raise
+        ptr = isl.isl_id_list_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.id_list("""%s""")' % s
+        else:
+            return 'isl.id_list("%s")' % s
+    def add(arg0, arg1):
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg0.__class__ is id_list:
+                arg0 = id_list(arg0)
         except:
-            return union_map(arg0).is_subset(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_map_is_subset(arg0.ptr, arg1.ptr)
-        if res < 0:
             raise
-        return bool(res)
-    def lexmax(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg1.__class__ is id:
+                arg1 = id(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_lexmax(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def lexmin(arg0):
+        res = isl.isl_id_list_add(isl.isl_id_list_copy(arg0.ptr), isl.isl_id_copy(arg1.ptr))
+        obj = id_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is id_list:
+                arg0 = id_list(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_lexmin(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def polyhedral_hull(arg0):
+        res = isl.isl_id_list_clear(isl.isl_id_list_copy(arg0.ptr))
+        obj = id_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is id_list:
+                arg0 = id_list(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_map_polyhedral_hull(isl.isl_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def reverse(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg1.__class__ is id_list:
+                arg1 = id_list(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_reverse(isl.isl_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def sample(arg0):
+        res = isl.isl_id_list_concat(isl.isl_id_list_copy(arg0.ptr), isl.isl_id_list_copy(arg1.ptr))
+        obj = id_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is id_list:
+                arg0 = id_list(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = id(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_map_sample(isl.isl_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def subtract(arg0, arg1):
+        res = isl.isl_id_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is id_list:
+                arg0 = id_list(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_id_list_get_at(arg0.ptr, arg1)
+        obj = id(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg0.__class__ is id_list:
+                arg0 = id_list(arg0)
         except:
-            return union_map(arg0).subtract(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_map_subtract(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def union(arg0, arg1):
+        res = isl.isl_id_list_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+
+isl.isl_id_list_alloc.restype = c_void_p
+isl.isl_id_list_alloc.argtypes = [Context, c_int]
+isl.isl_id_list_from_id.restype = c_void_p
+isl.isl_id_list_from_id.argtypes = [c_void_p]
+isl.isl_id_list_add.restype = c_void_p
+isl.isl_id_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_id_list_clear.restype = c_void_p
+isl.isl_id_list_clear.argtypes = [c_void_p]
+isl.isl_id_list_concat.restype = c_void_p
+isl.isl_id_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_id_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_id_list_get_at.restype = c_void_p
+isl.isl_id_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_id_list_size.argtypes = [c_void_p]
+isl.isl_id_list_copy.restype = c_void_p
+isl.isl_id_list_copy.argtypes = [c_void_p]
+isl.isl_id_list_free.restype = c_void_p
+isl.isl_id_list_free.argtypes = [c_void_p]
+isl.isl_id_list_to_str.restype = POINTER(c_char)
+isl.isl_id_list_to_str.argtypes = [c_void_p]
+
+class multi_id(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 2 and args[0].__class__ is space and args[1].__class__ is id_list:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_id_from_id_list(isl.isl_space_copy(args[0].ptr), isl.isl_id_list_copy(args[1].ptr))
+            return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_id_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_multi_id_free(self.ptr)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
         except:
             raise
+        ptr = isl.isl_multi_id_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.multi_id("""%s""")' % s
+        else:
+            return 'isl.multi_id("%s")' % s
+    def flat_range_product(arg0, arg1):
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
         except:
-            return union_map(arg0).union(arg1)
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            raise
         ctx = arg0.ctx
-        res = isl.isl_map_union(isl.isl_map_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
-    def unshifted_simple_hull(arg0):
+        res = isl.isl_multi_id_flat_range_product(isl.isl_multi_id_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = multi_id(ctx=ctx, ptr=res)
+        return obj
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is map:
-                arg0 = map(arg0)
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_map_unshifted_simple_hull(isl.isl_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-
-isl.isl_map_read_from_str.restype = c_void_p
-isl.isl_map_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_map_from_basic_map.restype = c_void_p
-isl.isl_map_from_basic_map.argtypes = [c_void_p]
-isl.isl_map_affine_hull.restype = c_void_p
-isl.isl_map_affine_hull.argtypes = [c_void_p]
-isl.isl_map_apply_domain.restype = c_void_p
-isl.isl_map_apply_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_map_apply_range.restype = c_void_p
-isl.isl_map_apply_range.argtypes = [c_void_p, c_void_p]
-isl.isl_map_coalesce.restype = c_void_p
-isl.isl_map_coalesce.argtypes = [c_void_p]
-isl.isl_map_complement.restype = c_void_p
-isl.isl_map_complement.argtypes = [c_void_p]
-isl.isl_map_deltas.restype = c_void_p
-isl.isl_map_deltas.argtypes = [c_void_p]
-isl.isl_map_detect_equalities.restype = c_void_p
-isl.isl_map_detect_equalities.argtypes = [c_void_p]
-isl.isl_map_flatten.restype = c_void_p
-isl.isl_map_flatten.argtypes = [c_void_p]
-isl.isl_map_flatten_domain.restype = c_void_p
-isl.isl_map_flatten_domain.argtypes = [c_void_p]
-isl.isl_map_flatten_range.restype = c_void_p
-isl.isl_map_flatten_range.argtypes = [c_void_p]
-isl.isl_map_foreach_basic_map.argtypes = [c_void_p, c_void_p, c_void_p]
-isl.isl_map_gist.restype = c_void_p
-isl.isl_map_gist.argtypes = [c_void_p, c_void_p]
-isl.isl_map_gist_domain.restype = c_void_p
-isl.isl_map_gist_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_map_intersect.restype = c_void_p
-isl.isl_map_intersect.argtypes = [c_void_p, c_void_p]
-isl.isl_map_intersect_domain.restype = c_void_p
-isl.isl_map_intersect_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_map_intersect_params.restype = c_void_p
-isl.isl_map_intersect_params.argtypes = [c_void_p, c_void_p]
-isl.isl_map_intersect_range.restype = c_void_p
-isl.isl_map_intersect_range.argtypes = [c_void_p, c_void_p]
-isl.isl_map_is_bijective.restype = c_bool
-isl.isl_map_is_bijective.argtypes = [c_void_p]
-isl.isl_map_is_disjoint.restype = c_bool
-isl.isl_map_is_disjoint.argtypes = [c_void_p, c_void_p]
-isl.isl_map_is_empty.restype = c_bool
-isl.isl_map_is_empty.argtypes = [c_void_p]
-isl.isl_map_is_equal.restype = c_bool
-isl.isl_map_is_equal.argtypes = [c_void_p, c_void_p]
-isl.isl_map_is_injective.restype = c_bool
-isl.isl_map_is_injective.argtypes = [c_void_p]
-isl.isl_map_is_single_valued.restype = c_bool
-isl.isl_map_is_single_valued.argtypes = [c_void_p]
-isl.isl_map_is_strict_subset.restype = c_bool
-isl.isl_map_is_strict_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_map_is_subset.restype = c_bool
-isl.isl_map_is_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_map_lexmax.restype = c_void_p
-isl.isl_map_lexmax.argtypes = [c_void_p]
-isl.isl_map_lexmin.restype = c_void_p
-isl.isl_map_lexmin.argtypes = [c_void_p]
-isl.isl_map_polyhedral_hull.restype = c_void_p
-isl.isl_map_polyhedral_hull.argtypes = [c_void_p]
-isl.isl_map_reverse.restype = c_void_p
-isl.isl_map_reverse.argtypes = [c_void_p]
-isl.isl_map_sample.restype = c_void_p
-isl.isl_map_sample.argtypes = [c_void_p]
-isl.isl_map_subtract.restype = c_void_p
-isl.isl_map_subtract.argtypes = [c_void_p, c_void_p]
-isl.isl_map_union.restype = c_void_p
-isl.isl_map_union.argtypes = [c_void_p, c_void_p]
-isl.isl_map_unshifted_simple_hull.restype = c_void_p
-isl.isl_map_unshifted_simple_hull.argtypes = [c_void_p]
-isl.isl_map_copy.restype = c_void_p
-isl.isl_map_copy.argtypes = [c_void_p]
-isl.isl_map_free.restype = c_void_p
-isl.isl_map_free.argtypes = [c_void_p]
-isl.isl_map_to_str.restype = POINTER(c_char)
-isl.isl_map_to_str.argtypes = [c_void_p]
+        res = isl.isl_multi_id_get_at(arg0.ptr, arg1)
+        obj = id(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def space(arg0):
+        try:
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_id_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def plain_is_equal(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_id_plain_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def range_product(arg0, arg1):
+        try:
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_id:
+                arg1 = multi_id(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_id_range_product(isl.isl_multi_id_copy(arg0.ptr), isl.isl_multi_id_copy(arg1.ptr))
+        obj = multi_id(ctx=ctx, ptr=res)
+        return obj
+    def set_at(arg0, arg1, arg2):
+        try:
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
+        except:
+            raise
+        try:
+            if not arg2.__class__ is id:
+                arg2 = id(arg2)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_id_set_at(isl.isl_multi_id_copy(arg0.ptr), arg1, isl.isl_id_copy(arg2.ptr))
+        obj = multi_id(ctx=ctx, ptr=res)
+        return obj
+    def size(arg0):
+        try:
+            if not arg0.__class__ is multi_id:
+                arg0 = multi_id(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_id_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
 
-class basic_map(map):
+isl.isl_multi_id_from_id_list.restype = c_void_p
+isl.isl_multi_id_from_id_list.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_id_read_from_str.restype = c_void_p
+isl.isl_multi_id_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_id_flat_range_product.restype = c_void_p
+isl.isl_multi_id_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_id_get_at.restype = c_void_p
+isl.isl_multi_id_get_at.argtypes = [c_void_p, c_int]
+isl.isl_multi_id_get_space.restype = c_void_p
+isl.isl_multi_id_get_space.argtypes = [c_void_p]
+isl.isl_multi_id_plain_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_id_range_product.restype = c_void_p
+isl.isl_multi_id_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_id_set_at.restype = c_void_p
+isl.isl_multi_id_set_at.argtypes = [c_void_p, c_int, c_void_p]
+isl.isl_multi_id_size.argtypes = [c_void_p]
+isl.isl_multi_id_copy.restype = c_void_p
+isl.isl_multi_id_copy.argtypes = [c_void_p]
+isl.isl_multi_id_free.restype = c_void_p
+isl.isl_multi_id_free.argtypes = [c_void_p]
+isl.isl_multi_id_to_str.restype = POINTER(c_char)
+isl.isl_multi_id_to_str.argtypes = [c_void_p]
+
+class multi_val(object):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
+        if len(args) == 2 and args[0].__class__ is space and args[1].__class__ is val_list:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_multi_val_from_val_list(isl.isl_space_copy(args[0].ptr), isl.isl_val_list_copy(args[1].ptr))
+            return
         if len(args) == 1 and type(args[0]) == str:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_basic_map_read_from_str(self.ctx, args[0].encode('ascii'))
+            self.ptr = isl.isl_multi_val_read_from_str(self.ctx, args[0].encode('ascii'))
             return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_basic_map_free(self.ptr)
+            isl.isl_multi_val_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
         except:
             raise
-        ptr = isl.isl_basic_map_to_str(arg0.ptr)
+        ptr = isl.isl_multi_val_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.basic_map("""%s""")' % s
+            return 'isl.multi_val("""%s""")' % s
         else:
-            return 'isl.basic_map("%s")' % s
-    def affine_hull(arg0):
+            return 'isl.multi_val("%s")' % s
+    def add(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_val_add(isl.isl_multi_val_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_val(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_val_add_val(isl.isl_multi_val_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_val(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def flat_range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_basic_map_affine_hull(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def apply_domain(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_val_flat_range_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def at(arg0, arg1):
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
         except:
-            return map(arg0).apply_domain(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_apply_domain(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def apply_range(arg0, arg1):
+        res = isl.isl_multi_val_get_at(arg0.ptr, arg1)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def space(arg0):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_val_get_space(arg0.ptr)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def get_space(arg0):
+        return arg0.space()
+    def neg(arg0):
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
         except:
-            return map(arg0).apply_range(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_apply_range(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def deltas(arg0):
+        res = isl.isl_multi_val_neg(isl.isl_multi_val_copy(arg0.ptr))
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def plain_is_equal(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_deltas(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def detect_equalities(arg0):
+        res = isl.isl_multi_val_plain_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def product(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_detect_equalities(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def flatten(arg0):
+        res = isl.isl_multi_val_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def range_product(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_flatten(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def flatten_domain(arg0):
+        res = isl.isl_multi_val_range_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def scale(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_val_scale_multi_val(isl.isl_multi_val_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_val(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_val_scale_val(isl.isl_multi_val_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_val(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def scale_down(*args):
+        if len(args) == 2 and args[1].__class__ is multi_val:
+            ctx = args[0].ctx
+            res = isl.isl_multi_val_scale_down_multi_val(isl.isl_multi_val_copy(args[0].ptr), isl.isl_multi_val_copy(args[1].ptr))
+            obj = multi_val(ctx=ctx, ptr=res)
+            return obj
+        if len(args) == 2 and (args[1].__class__ is val or type(args[1]) == int):
+            args = list(args)
+            try:
+                if not args[1].__class__ is val:
+                    args[1] = val(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_multi_val_scale_down_val(isl.isl_multi_val_copy(args[0].ptr), isl.isl_val_copy(args[1].ptr))
+            obj = multi_val(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def set_at(arg0, arg1, arg2):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
+        except:
+            raise
+        try:
+            if not arg2.__class__ is val:
+                arg2 = val(arg2)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_flatten_domain(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def flatten_range(arg0):
+        res = isl.isl_multi_val_set_at(isl.isl_multi_val_copy(arg0.ptr), arg1, isl.isl_val_copy(arg2.ptr))
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def size(arg0):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_flatten_range(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def gist(arg0, arg1):
+        res = isl.isl_multi_val_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def sub(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is multi_val:
+                arg0 = multi_val(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
-            return map(arg0).gist(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_gist(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def intersect(arg0, arg1):
+        res = isl.isl_multi_val_sub(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def zero(arg0):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_multi_val_zero(isl.isl_space_copy(arg0.ptr))
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_multi_val_from_val_list.restype = c_void_p
+isl.isl_multi_val_from_val_list.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_read_from_str.restype = c_void_p
+isl.isl_multi_val_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_multi_val_add.restype = c_void_p
+isl.isl_multi_val_add.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_add_val.restype = c_void_p
+isl.isl_multi_val_add_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_flat_range_product.restype = c_void_p
+isl.isl_multi_val_flat_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_get_at.restype = c_void_p
+isl.isl_multi_val_get_at.argtypes = [c_void_p, c_int]
+isl.isl_multi_val_get_space.restype = c_void_p
+isl.isl_multi_val_get_space.argtypes = [c_void_p]
+isl.isl_multi_val_neg.restype = c_void_p
+isl.isl_multi_val_neg.argtypes = [c_void_p]
+isl.isl_multi_val_plain_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_product.restype = c_void_p
+isl.isl_multi_val_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_range_product.restype = c_void_p
+isl.isl_multi_val_range_product.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_scale_multi_val.restype = c_void_p
+isl.isl_multi_val_scale_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_scale_val.restype = c_void_p
+isl.isl_multi_val_scale_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_scale_down_multi_val.restype = c_void_p
+isl.isl_multi_val_scale_down_multi_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_scale_down_val.restype = c_void_p
+isl.isl_multi_val_scale_down_val.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_set_at.restype = c_void_p
+isl.isl_multi_val_set_at.argtypes = [c_void_p, c_int, c_void_p]
+isl.isl_multi_val_size.argtypes = [c_void_p]
+isl.isl_multi_val_sub.restype = c_void_p
+isl.isl_multi_val_sub.argtypes = [c_void_p, c_void_p]
+isl.isl_multi_val_zero.restype = c_void_p
+isl.isl_multi_val_zero.argtypes = [c_void_p]
+isl.isl_multi_val_copy.restype = c_void_p
+isl.isl_multi_val_copy.argtypes = [c_void_p]
+isl.isl_multi_val_free.restype = c_void_p
+isl.isl_multi_val_free.argtypes = [c_void_p]
+isl.isl_multi_val_to_str.restype = POINTER(c_char)
+isl.isl_multi_val_to_str.argtypes = [c_void_p]
+
+class point(basic_set):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_point_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is point:
+                arg0 = point(arg0)
         except:
             raise
+        ptr = isl.isl_point_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.point("""%s""")' % s
+        else:
+            return 'isl.point("%s")' % s
+    def multi_val(arg0):
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg0.__class__ is point:
+                arg0 = point(arg0)
         except:
-            return map(arg0).intersect(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_intersect(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def intersect_domain(arg0, arg1):
+        res = isl.isl_point_get_multi_val(arg0.ptr)
+        obj = multi_val(ctx=ctx, ptr=res)
+        return obj
+    def get_multi_val(arg0):
+        return arg0.multi_val()
+
+isl.isl_point_get_multi_val.restype = c_void_p
+isl.isl_point_get_multi_val.argtypes = [c_void_p]
+isl.isl_point_copy.restype = c_void_p
+isl.isl_point_copy.argtypes = [c_void_p]
+isl.isl_point_free.restype = c_void_p
+isl.isl_point_free.argtypes = [c_void_p]
+isl.isl_point_to_str.restype = POINTER(c_char)
+isl.isl_point_to_str.argtypes = [c_void_p]
+
+class pw_aff_list(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_aff_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and args[0].__class__ is pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_aff_list_from_pw_aff(isl.isl_pw_aff_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_pw_aff_list_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is pw_aff_list:
+                arg0 = pw_aff_list(arg0)
+        except:
+            raise
+        ptr = isl.isl_pw_aff_list_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.pw_aff_list("""%s""")' % s
+        else:
+            return 'isl.pw_aff_list("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is pw_aff_list:
+                arg0 = pw_aff_list(arg0)
+        except:
+            raise
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg1.__class__ is pw_aff:
+                arg1 = pw_aff(arg1)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_list_add(isl.isl_pw_aff_list_copy(arg0.ptr), isl.isl_pw_aff_copy(arg1.ptr))
+        obj = pw_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg0.__class__ is pw_aff_list:
+                arg0 = pw_aff_list(arg0)
         except:
-            return map(arg0).intersect_domain(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_intersect_domain(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def intersect_range(arg0, arg1):
+        res = isl.isl_pw_aff_list_clear(isl.isl_pw_aff_list_copy(arg0.ptr))
+        obj = pw_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_aff_list:
+                arg0 = pw_aff_list(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg1.__class__ is pw_aff_list:
+                arg1 = pw_aff_list(arg1)
         except:
-            return map(arg0).intersect_range(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_intersect_range(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def is_empty(arg0):
+        res = isl.isl_pw_aff_list_concat(isl.isl_pw_aff_list_copy(arg0.ptr), isl.isl_pw_aff_list_copy(arg1.ptr))
+        obj = pw_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_aff_list:
+                arg0 = pw_aff_list(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = pw_aff(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_basic_map_is_empty(arg0.ptr)
+        res = isl.isl_pw_aff_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
         if res < 0:
             raise
-        return bool(res)
-    def is_equal(arg0, arg1):
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_aff_list:
+                arg0 = pw_aff_list(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_aff_list_get_at(arg0.ptr, arg1)
+        obj = pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg0.__class__ is pw_aff_list:
+                arg0 = pw_aff_list(arg0)
         except:
-            return map(arg0).is_equal(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_is_equal(arg0.ptr, arg1.ptr)
+        res = isl.isl_pw_aff_list_size(arg0.ptr)
         if res < 0:
             raise
-        return bool(res)
-    def is_subset(arg0, arg1):
+        return int(res)
+
+isl.isl_pw_aff_list_alloc.restype = c_void_p
+isl.isl_pw_aff_list_alloc.argtypes = [Context, c_int]
+isl.isl_pw_aff_list_from_pw_aff.restype = c_void_p
+isl.isl_pw_aff_list_from_pw_aff.argtypes = [c_void_p]
+isl.isl_pw_aff_list_add.restype = c_void_p
+isl.isl_pw_aff_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_list_clear.restype = c_void_p
+isl.isl_pw_aff_list_clear.argtypes = [c_void_p]
+isl.isl_pw_aff_list_concat.restype = c_void_p
+isl.isl_pw_aff_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_aff_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_pw_aff_list_get_at.restype = c_void_p
+isl.isl_pw_aff_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_pw_aff_list_size.argtypes = [c_void_p]
+isl.isl_pw_aff_list_copy.restype = c_void_p
+isl.isl_pw_aff_list_copy.argtypes = [c_void_p]
+isl.isl_pw_aff_list_free.restype = c_void_p
+isl.isl_pw_aff_list_free.argtypes = [c_void_p]
+isl.isl_pw_aff_list_to_str.restype = POINTER(c_char)
+isl.isl_pw_aff_list_to_str.argtypes = [c_void_p]
+
+class pw_multi_aff_list(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and args[0].__class__ is pw_multi_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_pw_multi_aff_list_from_pw_multi_aff(isl.isl_pw_multi_aff_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_pw_multi_aff_list_free(self.ptr)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_multi_aff_list:
+                arg0 = pw_multi_aff_list(arg0)
         except:
             raise
+        ptr = isl.isl_pw_multi_aff_list_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.pw_multi_aff_list("""%s""")' % s
+        else:
+            return 'isl.pw_multi_aff_list("%s")' % s
+    def add(arg0, arg1):
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg0.__class__ is pw_multi_aff_list:
+                arg0 = pw_multi_aff_list(arg0)
         except:
-            return map(arg0).is_subset(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_basic_map_is_subset(arg0.ptr, arg1.ptr)
-        if res < 0:
             raise
-        return bool(res)
-    def lexmax(arg0):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg1.__class__ is pw_multi_aff:
+                arg1 = pw_multi_aff(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_lexmax(isl.isl_basic_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def lexmin(arg0):
+        res = isl.isl_pw_multi_aff_list_add(isl.isl_pw_multi_aff_list_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
+        obj = pw_multi_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_multi_aff_list:
+                arg0 = pw_multi_aff_list(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_lexmin(isl.isl_basic_map_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def reverse(arg0):
+        res = isl.isl_pw_multi_aff_list_clear(isl.isl_pw_multi_aff_list_copy(arg0.ptr))
+        obj = pw_multi_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_multi_aff_list:
+                arg0 = pw_multi_aff_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is pw_multi_aff_list:
+                arg1 = pw_multi_aff_list(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_reverse(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def sample(arg0):
+        res = isl.isl_pw_multi_aff_list_concat(isl.isl_pw_multi_aff_list_copy(arg0.ptr), isl.isl_pw_multi_aff_list_copy(arg1.ptr))
+        obj = pw_multi_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_multi_aff_list:
+                arg0 = pw_multi_aff_list(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = pw_multi_aff(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_basic_map_sample(isl.isl_basic_map_copy(arg0.ptr))
-        return basic_map(ctx=ctx, ptr=res)
-    def union(arg0, arg1):
+        res = isl.isl_pw_multi_aff_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_map:
-                arg0 = basic_map(arg0)
+            if not arg0.__class__ is pw_multi_aff_list:
+                arg0 = pw_multi_aff_list(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_pw_multi_aff_list_get_at(arg0.ptr, arg1)
+        obj = pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg0.__class__ is pw_multi_aff_list:
+                arg0 = pw_multi_aff_list(arg0)
         except:
-            return map(arg0).union(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_map_union(isl.isl_basic_map_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
-        return map(ctx=ctx, ptr=res)
+        res = isl.isl_pw_multi_aff_list_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
 
-isl.isl_basic_map_read_from_str.restype = c_void_p
-isl.isl_basic_map_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_basic_map_affine_hull.restype = c_void_p
-isl.isl_basic_map_affine_hull.argtypes = [c_void_p]
-isl.isl_basic_map_apply_domain.restype = c_void_p
-isl.isl_basic_map_apply_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_apply_range.restype = c_void_p
-isl.isl_basic_map_apply_range.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_deltas.restype = c_void_p
-isl.isl_basic_map_deltas.argtypes = [c_void_p]
-isl.isl_basic_map_detect_equalities.restype = c_void_p
-isl.isl_basic_map_detect_equalities.argtypes = [c_void_p]
-isl.isl_basic_map_flatten.restype = c_void_p
-isl.isl_basic_map_flatten.argtypes = [c_void_p]
-isl.isl_basic_map_flatten_domain.restype = c_void_p
-isl.isl_basic_map_flatten_domain.argtypes = [c_void_p]
-isl.isl_basic_map_flatten_range.restype = c_void_p
-isl.isl_basic_map_flatten_range.argtypes = [c_void_p]
-isl.isl_basic_map_gist.restype = c_void_p
-isl.isl_basic_map_gist.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_intersect.restype = c_void_p
-isl.isl_basic_map_intersect.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_intersect_domain.restype = c_void_p
-isl.isl_basic_map_intersect_domain.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_intersect_range.restype = c_void_p
-isl.isl_basic_map_intersect_range.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_is_empty.restype = c_bool
-isl.isl_basic_map_is_empty.argtypes = [c_void_p]
-isl.isl_basic_map_is_equal.restype = c_bool
-isl.isl_basic_map_is_equal.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_is_subset.restype = c_bool
-isl.isl_basic_map_is_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_lexmax.restype = c_void_p
-isl.isl_basic_map_lexmax.argtypes = [c_void_p]
-isl.isl_basic_map_lexmin.restype = c_void_p
-isl.isl_basic_map_lexmin.argtypes = [c_void_p]
-isl.isl_basic_map_reverse.restype = c_void_p
-isl.isl_basic_map_reverse.argtypes = [c_void_p]
-isl.isl_basic_map_sample.restype = c_void_p
-isl.isl_basic_map_sample.argtypes = [c_void_p]
-isl.isl_basic_map_union.restype = c_void_p
-isl.isl_basic_map_union.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_map_copy.restype = c_void_p
-isl.isl_basic_map_copy.argtypes = [c_void_p]
-isl.isl_basic_map_free.restype = c_void_p
-isl.isl_basic_map_free.argtypes = [c_void_p]
-isl.isl_basic_map_to_str.restype = POINTER(c_char)
-isl.isl_basic_map_to_str.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_list_alloc.restype = c_void_p
+isl.isl_pw_multi_aff_list_alloc.argtypes = [Context, c_int]
+isl.isl_pw_multi_aff_list_from_pw_multi_aff.restype = c_void_p
+isl.isl_pw_multi_aff_list_from_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_list_add.restype = c_void_p
+isl.isl_pw_multi_aff_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_list_clear.restype = c_void_p
+isl.isl_pw_multi_aff_list_clear.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_list_concat.restype = c_void_p
+isl.isl_pw_multi_aff_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_pw_multi_aff_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_pw_multi_aff_list_get_at.restype = c_void_p
+isl.isl_pw_multi_aff_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_pw_multi_aff_list_size.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_list_copy.restype = c_void_p
+isl.isl_pw_multi_aff_list_copy.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_list_free.restype = c_void_p
+isl.isl_pw_multi_aff_list_free.argtypes = [c_void_p]
+isl.isl_pw_multi_aff_list_to_str.restype = POINTER(c_char)
+isl.isl_pw_multi_aff_list_to_str.argtypes = [c_void_p]
 
-class union_set(object):
+class schedule(object):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and args[0].__class__ is basic_set:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_set_from_basic_set(isl.isl_basic_set_copy(args[0].ptr))
-            return
-        if len(args) == 1 and args[0].__class__ is set:
+        if len(args) == 1 and type(args[0]) == str:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_set_from_set(isl.isl_set_copy(args[0].ptr))
+            self.ptr = isl.isl_schedule_read_from_str(self.ctx, args[0].encode('ascii'))
             return
-        if len(args) == 1 and args[0].__class__ is point:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_set_from_point(isl.isl_point_copy(args[0].ptr))
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is schedule:
+                arg0 = schedule(arg0)
+        except:
+            raise
+        ptr = isl.isl_schedule_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule("""%s""")' % s
+        else:
+            return 'isl.schedule("%s")' % s
+    @staticmethod
+    def from_domain(arg0):
+        try:
+            if not arg0.__class__ is union_set:
+                arg0 = union_set(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_from_domain(isl.isl_union_set_copy(arg0.ptr))
+        obj = schedule(ctx=ctx, ptr=res)
+        return obj
+    def map(arg0):
+        try:
+            if not arg0.__class__ is schedule:
+                arg0 = schedule(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_get_map(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_map(arg0):
+        return arg0.map()
+    def root(arg0):
+        try:
+            if not arg0.__class__ is schedule:
+                arg0 = schedule(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_get_root(arg0.ptr)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def get_root(arg0):
+        return arg0.root()
+    def pullback(*args):
+        if len(args) == 2 and args[1].__class__ is union_pw_multi_aff:
+            ctx = args[0].ctx
+            res = isl.isl_schedule_pullback_union_pw_multi_aff(isl.isl_schedule_copy(args[0].ptr), isl.isl_union_pw_multi_aff_copy(args[1].ptr))
+            obj = schedule(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+
+isl.isl_schedule_read_from_str.restype = c_void_p
+isl.isl_schedule_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_schedule_from_domain.restype = c_void_p
+isl.isl_schedule_from_domain.argtypes = [c_void_p]
+isl.isl_schedule_get_map.restype = c_void_p
+isl.isl_schedule_get_map.argtypes = [c_void_p]
+isl.isl_schedule_get_root.restype = c_void_p
+isl.isl_schedule_get_root.argtypes = [c_void_p]
+isl.isl_schedule_pullback_union_pw_multi_aff.restype = c_void_p
+isl.isl_schedule_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_copy.restype = c_void_p
+isl.isl_schedule_copy.argtypes = [c_void_p]
+isl.isl_schedule_free.restype = c_void_p
+isl.isl_schedule_free.argtypes = [c_void_p]
+isl.isl_schedule_to_str.restype = POINTER(c_char)
+isl.isl_schedule_to_str.argtypes = [c_void_p]
+
+class schedule_constraints(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
             return
         if len(args) == 1 and type(args[0]) == str:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_set_read_from_str(self.ctx, args[0].encode('ascii'))
+            self.ptr = isl.isl_schedule_constraints_read_from_str(self.ctx, args[0].encode('ascii'))
             return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_union_set_free(self.ptr)
+            isl.isl_schedule_constraints_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
-        ptr = isl.isl_union_set_to_str(arg0.ptr)
+        ptr = isl.isl_schedule_constraints_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.union_set("""%s""")' % s
+            return 'isl.schedule_constraints("""%s""")' % s
         else:
-            return 'isl.union_set("%s")' % s
-    def affine_hull(arg0):
+            return 'isl.schedule_constraints("%s")' % s
+    def compute_schedule(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_affine_hull(isl.isl_union_set_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def apply(arg0, arg1):
+        res = isl.isl_schedule_constraints_compute_schedule(isl.isl_schedule_constraints_copy(arg0.ptr))
+        obj = schedule(ctx=ctx, ptr=res)
+        return obj
+    def coincidence(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_get_coincidence(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_coincidence(arg0):
+        return arg0.coincidence()
+    def conditional_validity(arg0):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_apply(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def coalesce(arg0):
+        res = isl.isl_schedule_constraints_get_conditional_validity(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_conditional_validity(arg0):
+        return arg0.conditional_validity()
+    def conditional_validity_condition(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_coalesce(isl.isl_union_set_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def compute_divs(arg0):
+        res = isl.isl_schedule_constraints_get_conditional_validity_condition(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_conditional_validity_condition(arg0):
+        return arg0.conditional_validity_condition()
+    def context(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_compute_divs(isl.isl_union_set_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def detect_equalities(arg0):
+        res = isl.isl_schedule_constraints_get_context(arg0.ptr)
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def get_context(arg0):
+        return arg0.context()
+    def domain(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_detect_equalities(isl.isl_union_set_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def foreach_point(arg0, arg1):
+        res = isl.isl_schedule_constraints_get_domain(arg0.ptr)
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def get_domain(arg0):
+        return arg0.domain()
+    def proximity(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
-        exc_info = [None]
-        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
-        def cb_func(cb_arg0, cb_arg1):
-            cb_arg0 = point(ctx=arg0.ctx, ptr=(cb_arg0))
-            try:
-                arg1(cb_arg0)
-            except:
-                import sys
-                exc_info[0] = sys.exc_info()
-                return -1
-            return 0
-        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_union_set_foreach_point(arg0.ptr, cb, None)
-        if exc_info[0] != None:
-            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
-        return res
-    def foreach_set(arg0, arg1):
+        res = isl.isl_schedule_constraints_get_proximity(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_proximity(arg0):
+        return arg0.proximity()
+    def validity(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
-        exc_info = [None]
-        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
-        def cb_func(cb_arg0, cb_arg1):
-            cb_arg0 = set(ctx=arg0.ctx, ptr=(cb_arg0))
-            try:
-                arg1(cb_arg0)
-            except:
-                import sys
-                exc_info[0] = sys.exc_info()
-                return -1
-            return 0
-        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_union_set_foreach_set(arg0.ptr, cb, None)
-        if exc_info[0] != None:
-            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
-        return res
-    def gist(arg0, arg1):
+        res = isl.isl_schedule_constraints_get_validity(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_validity(arg0):
+        return arg0.validity()
+    @staticmethod
+    def on_domain(arg0):
         try:
             if not arg0.__class__ is union_set:
                 arg0 = union_set(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_constraints_on_domain(isl.isl_union_set_copy(arg0.ptr))
+        obj = schedule_constraints(ctx=ctx, ptr=res)
+        return obj
+    def set_coincidence(arg0, arg1):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_gist(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def gist_params(arg0, arg1):
+        res = isl.isl_schedule_constraints_set_coincidence(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = schedule_constraints(ctx=ctx, ptr=res)
+        return obj
+    def set_conditional_validity(arg0, arg1, arg2):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
+        except:
+            raise
+        try:
+            if not arg2.__class__ is union_map:
+                arg2 = union_map(arg2)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_gist_params(isl.isl_union_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def identity(arg0):
+        res = isl.isl_schedule_constraints_set_conditional_validity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr), isl.isl_union_map_copy(arg2.ptr))
+        obj = schedule_constraints(ctx=ctx, ptr=res)
+        return obj
+    def set_context(arg0, arg1):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is set:
+                arg1 = set(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_identity(isl.isl_union_set_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-    def intersect(arg0, arg1):
+        res = isl.isl_schedule_constraints_set_context(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = schedule_constraints(ctx=ctx, ptr=res)
+        return obj
+    def set_proximity(arg0, arg1):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_intersect(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def intersect_params(arg0, arg1):
+        res = isl.isl_schedule_constraints_set_proximity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = schedule_constraints(ctx=ctx, ptr=res)
+        return obj
+    def set_validity(arg0, arg1):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_constraints:
+                arg0 = schedule_constraints(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_intersect_params(isl.isl_union_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def is_empty(arg0):
+        res = isl.isl_schedule_constraints_set_validity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = schedule_constraints(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_schedule_constraints_read_from_str.restype = c_void_p
+isl.isl_schedule_constraints_read_from_str.argtypes = [Context, c_char_p]
+isl.isl_schedule_constraints_compute_schedule.restype = c_void_p
+isl.isl_schedule_constraints_compute_schedule.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_coincidence.restype = c_void_p
+isl.isl_schedule_constraints_get_coincidence.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_conditional_validity.restype = c_void_p
+isl.isl_schedule_constraints_get_conditional_validity.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_conditional_validity_condition.restype = c_void_p
+isl.isl_schedule_constraints_get_conditional_validity_condition.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_context.restype = c_void_p
+isl.isl_schedule_constraints_get_context.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_domain.restype = c_void_p
+isl.isl_schedule_constraints_get_domain.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_proximity.restype = c_void_p
+isl.isl_schedule_constraints_get_proximity.argtypes = [c_void_p]
+isl.isl_schedule_constraints_get_validity.restype = c_void_p
+isl.isl_schedule_constraints_get_validity.argtypes = [c_void_p]
+isl.isl_schedule_constraints_on_domain.restype = c_void_p
+isl.isl_schedule_constraints_on_domain.argtypes = [c_void_p]
+isl.isl_schedule_constraints_set_coincidence.restype = c_void_p
+isl.isl_schedule_constraints_set_coincidence.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_conditional_validity.restype = c_void_p
+isl.isl_schedule_constraints_set_conditional_validity.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_context.restype = c_void_p
+isl.isl_schedule_constraints_set_context.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_proximity.restype = c_void_p
+isl.isl_schedule_constraints_set_proximity.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_set_validity.restype = c_void_p
+isl.isl_schedule_constraints_set_validity.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_constraints_copy.restype = c_void_p
+isl.isl_schedule_constraints_copy.argtypes = [c_void_p]
+isl.isl_schedule_constraints_free.restype = c_void_p
+isl.isl_schedule_constraints_free.argtypes = [c_void_p]
+isl.isl_schedule_constraints_to_str.restype = POINTER(c_char)
+isl.isl_schedule_constraints_to_str.argtypes = [c_void_p]
+
+class schedule_node(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_band):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_context):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_domain):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_expansion):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_extension):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_filter):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_leaf):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_guard):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_mark):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_sequence):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        if len(args) == 1 and isinstance(args[0], schedule_node_set):
+            self.ctx = args[0].ctx
+            self.ptr = isl.isl_schedule_node_copy(args[0].ptr)
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        if "ptr" in keywords:
+            type = isl.isl_schedule_node_get_type(keywords["ptr"])
+            if type == 0:
+                return schedule_node_band(**keywords)
+            if type == 1:
+                return schedule_node_context(**keywords)
+            if type == 2:
+                return schedule_node_domain(**keywords)
+            if type == 3:
+                return schedule_node_expansion(**keywords)
+            if type == 4:
+                return schedule_node_extension(**keywords)
+            if type == 5:
+                return schedule_node_filter(**keywords)
+            if type == 6:
+                return schedule_node_leaf(**keywords)
+            if type == 7:
+                return schedule_node_guard(**keywords)
+            if type == 8:
+                return schedule_node_mark(**keywords)
+            if type == 9:
+                return schedule_node_sequence(**keywords)
+            if type == 10:
+                return schedule_node_set(**keywords)
+            raise
+        return super(schedule_node, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node("""%s""")' % s
+        else:
+            return 'isl.schedule_node("%s")' % s
+    def ancestor(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_is_empty(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_equal(arg0, arg1):
+        res = isl.isl_schedule_node_ancestor(isl.isl_schedule_node_copy(arg0.ptr), arg1)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def child(arg0, arg1):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_child(isl.isl_schedule_node_copy(arg0.ptr), arg1)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def every_descendant(arg0, arg1):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = schedule_node(ctx=arg0.ctx, ptr=isl.isl_schedule_node_copy(cb_arg0))
+            try:
+                res = arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 1 if res else 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_union_set_is_equal(arg0.ptr, arg1.ptr)
+        res = isl.isl_schedule_node_every_descendant(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
         if res < 0:
             raise
         return bool(res)
-    def is_strict_subset(arg0, arg1):
+    def first_child(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_first_child(isl.isl_schedule_node_copy(arg0.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def foreach_ancestor_top_down(arg0, arg1):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = schedule_node(ctx=arg0.ctx, ptr=isl.isl_schedule_node_copy(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_union_set_is_strict_subset(arg0.ptr, arg1.ptr)
+        res = isl.isl_schedule_node_foreach_ancestor_top_down(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
         if res < 0:
             raise
-        return bool(res)
-    def is_subset(arg0, arg1):
-        try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
-        except:
-            raise
+    def foreach_descendant_top_down(arg0, arg1):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = schedule_node(ctx=arg0.ctx, ptr=isl.isl_schedule_node_copy(cb_arg0))
+            try:
+                res = arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 1 if res else 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_union_set_is_subset(arg0.ptr, arg1.ptr)
+        res = isl.isl_schedule_node_foreach_descendant_top_down(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
         if res < 0:
             raise
-        return bool(res)
-    def lexmax(arg0):
+    @staticmethod
+    def from_domain(arg0):
         try:
             if not arg0.__class__ is union_set:
                 arg0 = union_set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_lexmax(isl.isl_union_set_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def lexmin(arg0):
+        res = isl.isl_schedule_node_from_domain(isl.isl_union_set_copy(arg0.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    @staticmethod
+    def from_extension(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is union_map:
+                arg0 = union_map(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_lexmin(isl.isl_union_set_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def polyhedral_hull(arg0):
+        res = isl.isl_schedule_node_from_extension(isl.isl_union_map_copy(arg0.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def ancestor_child_position(arg0, arg1):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_set_polyhedral_hull(isl.isl_union_set_copy(arg0.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def preimage(arg0, arg1):
-        if arg1.__class__ is multi_aff:
-            res = isl.isl_union_set_preimage_multi_aff(isl.isl_union_set_copy(arg0.ptr), isl.isl_multi_aff_copy(arg1.ptr))
-            return union_set(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is pw_multi_aff:
-            res = isl.isl_union_set_preimage_pw_multi_aff(isl.isl_union_set_copy(arg0.ptr), isl.isl_pw_multi_aff_copy(arg1.ptr))
-            return union_set(ctx=arg0.ctx, ptr=res)
-        if arg1.__class__ is union_pw_multi_aff:
-            res = isl.isl_union_set_preimage_union_pw_multi_aff(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-            return union_set(ctx=arg0.ctx, ptr=res)
-    def sample_point(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg1.__class__ is schedule_node:
+                arg1 = schedule_node(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_sample_point(isl.isl_union_set_copy(arg0.ptr))
-        return point(ctx=ctx, ptr=res)
-    def subtract(arg0, arg1):
+        res = isl.isl_schedule_node_get_ancestor_child_position(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def get_ancestor_child_position(arg0, arg1):
+        return arg0.ancestor_child_position(arg1)
+    def child_position(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_get_child_position(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def get_child_position(arg0):
+        return arg0.child_position()
+    def prefix_schedule_multi_union_pw_aff(arg0):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_subtract(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def union(arg0, arg1):
+        res = isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(arg0.ptr)
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_prefix_schedule_multi_union_pw_aff(arg0):
+        return arg0.prefix_schedule_multi_union_pw_aff()
+    def prefix_schedule_union_map(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_get_prefix_schedule_union_map(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_prefix_schedule_union_map(arg0):
+        return arg0.prefix_schedule_union_map()
+    def prefix_schedule_union_pw_multi_aff(arg0):
         try:
-            if not arg1.__class__ is union_set:
-                arg1 = union_set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_union(isl.isl_union_set_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
-        return union_set(ctx=ctx, ptr=res)
-    def unwrap(arg0):
+        res = isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(arg0.ptr)
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_prefix_schedule_union_pw_multi_aff(arg0):
+        return arg0.prefix_schedule_union_pw_multi_aff()
+    def schedule(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_set_unwrap(isl.isl_union_set_copy(arg0.ptr))
-        return union_map(ctx=ctx, ptr=res)
-
-isl.isl_union_set_from_basic_set.restype = c_void_p
-isl.isl_union_set_from_basic_set.argtypes = [c_void_p]
-isl.isl_union_set_from_set.restype = c_void_p
-isl.isl_union_set_from_set.argtypes = [c_void_p]
-isl.isl_union_set_from_point.restype = c_void_p
-isl.isl_union_set_from_point.argtypes = [c_void_p]
-isl.isl_union_set_read_from_str.restype = c_void_p
-isl.isl_union_set_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_union_set_affine_hull.restype = c_void_p
-isl.isl_union_set_affine_hull.argtypes = [c_void_p]
-isl.isl_union_set_apply.restype = c_void_p
-isl.isl_union_set_apply.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_coalesce.restype = c_void_p
-isl.isl_union_set_coalesce.argtypes = [c_void_p]
-isl.isl_union_set_compute_divs.restype = c_void_p
-isl.isl_union_set_compute_divs.argtypes = [c_void_p]
-isl.isl_union_set_detect_equalities.restype = c_void_p
-isl.isl_union_set_detect_equalities.argtypes = [c_void_p]
-isl.isl_union_set_foreach_point.argtypes = [c_void_p, c_void_p, c_void_p]
-isl.isl_union_set_foreach_set.argtypes = [c_void_p, c_void_p, c_void_p]
-isl.isl_union_set_gist.restype = c_void_p
-isl.isl_union_set_gist.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_gist_params.restype = c_void_p
-isl.isl_union_set_gist_params.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_identity.restype = c_void_p
-isl.isl_union_set_identity.argtypes = [c_void_p]
-isl.isl_union_set_intersect.restype = c_void_p
-isl.isl_union_set_intersect.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_intersect_params.restype = c_void_p
-isl.isl_union_set_intersect_params.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_is_empty.restype = c_bool
-isl.isl_union_set_is_empty.argtypes = [c_void_p]
-isl.isl_union_set_is_equal.restype = c_bool
-isl.isl_union_set_is_equal.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_is_strict_subset.restype = c_bool
-isl.isl_union_set_is_strict_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_is_subset.restype = c_bool
-isl.isl_union_set_is_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_lexmax.restype = c_void_p
-isl.isl_union_set_lexmax.argtypes = [c_void_p]
-isl.isl_union_set_lexmin.restype = c_void_p
-isl.isl_union_set_lexmin.argtypes = [c_void_p]
-isl.isl_union_set_polyhedral_hull.restype = c_void_p
-isl.isl_union_set_polyhedral_hull.argtypes = [c_void_p]
-isl.isl_union_set_preimage_multi_aff.restype = c_void_p
-isl.isl_union_set_preimage_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_preimage_pw_multi_aff.restype = c_void_p
-isl.isl_union_set_preimage_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_preimage_union_pw_multi_aff.restype = c_void_p
-isl.isl_union_set_preimage_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_sample_point.restype = c_void_p
-isl.isl_union_set_sample_point.argtypes = [c_void_p]
-isl.isl_union_set_subtract.restype = c_void_p
-isl.isl_union_set_subtract.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_union.restype = c_void_p
-isl.isl_union_set_union.argtypes = [c_void_p, c_void_p]
-isl.isl_union_set_unwrap.restype = c_void_p
-isl.isl_union_set_unwrap.argtypes = [c_void_p]
-isl.isl_union_set_copy.restype = c_void_p
-isl.isl_union_set_copy.argtypes = [c_void_p]
-isl.isl_union_set_free.restype = c_void_p
-isl.isl_union_set_free.argtypes = [c_void_p]
-isl.isl_union_set_to_str.restype = POINTER(c_char)
-isl.isl_union_set_to_str.argtypes = [c_void_p]
-
-class set(union_set):
-    def __init__(self, *args, **keywords):
-        if "ptr" in keywords:
-            self.ctx = keywords["ctx"]
-            self.ptr = keywords["ptr"]
-            return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_set_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        if len(args) == 1 and args[0].__class__ is basic_set:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_set_from_basic_set(isl.isl_basic_set_copy(args[0].ptr))
-            return
-        if len(args) == 1 and args[0].__class__ is point:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_set_from_point(isl.isl_point_copy(args[0].ptr))
-            return
-        raise Error
-    def __del__(self):
-        if hasattr(self, 'ptr'):
-            isl.isl_set_free(self.ptr)
-    def __str__(arg0):
+        res = isl.isl_schedule_node_get_schedule(arg0.ptr)
+        obj = schedule(ctx=ctx, ptr=res)
+        return obj
+    def get_schedule(arg0):
+        return arg0.schedule()
+    def shared_ancestor(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
-        ptr = isl.isl_set_to_str(arg0.ptr)
-        res = cast(ptr, c_char_p).value.decode('ascii')
-        libc.free(ptr)
-        return res
-    def __repr__(self):
-        s = str(self)
-        if '"' in s:
-            return 'isl.set("""%s""")' % s
-        else:
-            return 'isl.set("%s")' % s
-    def affine_hull(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg1.__class__ is schedule_node:
+                arg1 = schedule_node(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_affine_hull(isl.isl_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def apply(arg0, arg1):
+        res = isl.isl_schedule_node_get_shared_ancestor(arg0.ptr, arg1.ptr)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def get_shared_ancestor(arg0, arg1):
+        return arg0.shared_ancestor(arg1)
+    def tree_depth(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_get_tree_depth(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def get_tree_depth(arg0):
+        return arg0.tree_depth()
+    def graft_after(arg0, arg1):
         try:
-            if not arg1.__class__ is map:
-                arg1 = map(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is schedule_node:
+                arg1 = schedule_node(arg1)
         except:
-            return union_set(arg0).apply(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_set_apply(isl.isl_set_copy(arg0.ptr), isl.isl_map_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def coalesce(arg0):
+        res = isl.isl_schedule_node_graft_after(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_schedule_node_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def graft_before(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_set_coalesce(isl.isl_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def complement(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg1.__class__ is schedule_node:
+                arg1 = schedule_node(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_complement(isl.isl_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def detect_equalities(arg0):
+        res = isl.isl_schedule_node_graft_before(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_schedule_node_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def has_children(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_detect_equalities(isl.isl_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def flatten(arg0):
+        res = isl.isl_schedule_node_has_children(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def has_next_sibling(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_flatten(isl.isl_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def foreach_basic_set(arg0, arg1):
+        res = isl.isl_schedule_node_has_next_sibling(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def has_parent(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
-        exc_info = [None]
-        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
-        def cb_func(cb_arg0, cb_arg1):
-            cb_arg0 = basic_set(ctx=arg0.ctx, ptr=(cb_arg0))
-            try:
-                arg1(cb_arg0)
-            except:
-                import sys
-                exc_info[0] = sys.exc_info()
-                return -1
-            return 0
-        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_set_foreach_basic_set(arg0.ptr, cb, None)
-        if exc_info[0] != None:
-            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
-        return res
-    def get_stride(arg0, arg1):
+        res = isl.isl_schedule_node_has_parent(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def has_previous_sibling(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_get_stride(arg0.ptr, arg1)
-        return val(ctx=ctx, ptr=res)
-    def gist(arg0, arg1):
+        res = isl.isl_schedule_node_has_previous_sibling(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def insert_context(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
             if not arg1.__class__ is set:
                 arg1 = set(arg1)
-        except:
-            return union_set(arg0).gist(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_set_gist(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def identity(arg0):
-        try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_identity(isl.isl_set_copy(arg0.ptr))
-        return map(ctx=ctx, ptr=res)
-    def intersect(arg0, arg1):
+        res = isl.isl_schedule_node_insert_context(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def insert_filter(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
-            return union_set(arg0).intersect(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_set_intersect(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def intersect_params(arg0, arg1):
+        res = isl.isl_schedule_node_insert_filter(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def insert_guard(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
             if not arg1.__class__ is set:
                 arg1 = set(arg1)
         except:
-            return union_set(arg0).intersect_params(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_set_intersect_params(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def is_disjoint(arg0, arg1):
+        res = isl.isl_schedule_node_insert_guard(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def insert_mark(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is id:
+                arg1 = id(arg1)
         except:
-            return union_set(arg0).is_disjoint(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_set_is_disjoint(arg0.ptr, arg1.ptr)
-        if res < 0:
+        res = isl.isl_schedule_node_insert_mark(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_id_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def insert_partial_schedule(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
             raise
-        return bool(res)
-    def is_empty(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_is_empty(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def is_equal(arg0, arg1):
+        res = isl.isl_schedule_node_insert_partial_schedule(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def insert_sequence(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is union_set_list:
+                arg1 = union_set_list(arg1)
         except:
-            return union_set(arg0).is_equal(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_set_is_equal(arg0.ptr, arg1.ptr)
-        if res < 0:
             raise
-        return bool(res)
-    def is_strict_subset(arg0, arg1):
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_insert_sequence(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_union_set_list_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def insert_set(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is union_set_list:
+                arg1 = union_set_list(arg1)
         except:
-            return union_set(arg0).is_strict_subset(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_set_is_strict_subset(arg0.ptr, arg1.ptr)
-        if res < 0:
             raise
-        return bool(res)
-    def is_subset(arg0, arg1):
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_insert_set(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_union_set_list_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def is_equal(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is schedule_node:
+                arg1 = schedule_node(arg1)
         except:
-            return union_set(arg0).is_subset(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_set_is_subset(arg0.ptr, arg1.ptr)
+        res = isl.isl_schedule_node_is_equal(arg0.ptr, arg1.ptr)
         if res < 0:
             raise
         return bool(res)
-    def is_wrapping(arg0):
+    def is_subtree_anchored(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_is_wrapping(arg0.ptr)
+        res = isl.isl_schedule_node_is_subtree_anchored(arg0.ptr)
         if res < 0:
             raise
         return bool(res)
-    def lexmax(arg0):
+    def map_descendant_bottom_up(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_void_p, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = schedule_node(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                res = arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return None
+            return isl.isl_schedule_node_copy(res.ptr)
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_set_lexmax(isl.isl_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def lexmin(arg0):
+        res = isl.isl_schedule_node_map_descendant_bottom_up(isl.isl_schedule_node_copy(arg0.ptr), cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def n_children(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_lexmin(isl.isl_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def max_val(arg0, arg1):
-        try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
-        except:
+        res = isl.isl_schedule_node_n_children(arg0.ptr)
+        if res < 0:
             raise
+        return int(res)
+    def next_sibling(arg0):
         try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
-        except:
-            return union_set(arg0).max_val(arg1)
-        ctx = arg0.ctx
-        res = isl.isl_set_max_val(arg0.ptr, arg1.ptr)
-        return val(ctx=ctx, ptr=res)
-    def min_val(arg0, arg1):
-        try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
-        try:
-            if not arg1.__class__ is aff:
-                arg1 = aff(arg1)
-        except:
-            return union_set(arg0).min_val(arg1)
         ctx = arg0.ctx
-        res = isl.isl_set_min_val(arg0.ptr, arg1.ptr)
-        return val(ctx=ctx, ptr=res)
-    def polyhedral_hull(arg0):
+        res = isl.isl_schedule_node_next_sibling(isl.isl_schedule_node_copy(arg0.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def order_after(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_set_polyhedral_hull(isl.isl_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def sample(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_sample(isl.isl_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def sample_point(arg0):
+        res = isl.isl_schedule_node_order_after(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def order_before(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_set_sample_point(isl.isl_set_copy(arg0.ptr))
-        return point(ctx=ctx, ptr=res)
-    def subtract(arg0, arg1):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
             raise
-        try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
-        except:
-            return union_set(arg0).subtract(arg1)
         ctx = arg0.ctx
-        res = isl.isl_set_subtract(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def union(arg0, arg1):
+        res = isl.isl_schedule_node_order_before(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def parent(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_parent(isl.isl_schedule_node_copy(arg0.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def previous_sibling(arg0):
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
-            return union_set(arg0).union(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_set_union(isl.isl_set_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
-    def unshifted_simple_hull(arg0):
+        res = isl.isl_schedule_node_previous_sibling(isl.isl_schedule_node_copy(arg0.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def root(arg0):
         try:
-            if not arg0.__class__ is set:
-                arg0 = set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_set_unshifted_simple_hull(isl.isl_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
+        res = isl.isl_schedule_node_root(isl.isl_schedule_node_copy(arg0.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
 
-isl.isl_set_read_from_str.restype = c_void_p
-isl.isl_set_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_set_from_basic_set.restype = c_void_p
-isl.isl_set_from_basic_set.argtypes = [c_void_p]
-isl.isl_set_from_point.restype = c_void_p
-isl.isl_set_from_point.argtypes = [c_void_p]
-isl.isl_set_affine_hull.restype = c_void_p
-isl.isl_set_affine_hull.argtypes = [c_void_p]
-isl.isl_set_apply.restype = c_void_p
-isl.isl_set_apply.argtypes = [c_void_p, c_void_p]
-isl.isl_set_coalesce.restype = c_void_p
-isl.isl_set_coalesce.argtypes = [c_void_p]
-isl.isl_set_complement.restype = c_void_p
-isl.isl_set_complement.argtypes = [c_void_p]
-isl.isl_set_detect_equalities.restype = c_void_p
-isl.isl_set_detect_equalities.argtypes = [c_void_p]
-isl.isl_set_flatten.restype = c_void_p
-isl.isl_set_flatten.argtypes = [c_void_p]
-isl.isl_set_foreach_basic_set.argtypes = [c_void_p, c_void_p, c_void_p]
-isl.isl_set_get_stride.restype = c_void_p
-isl.isl_set_get_stride.argtypes = [c_void_p, c_int]
-isl.isl_set_gist.restype = c_void_p
-isl.isl_set_gist.argtypes = [c_void_p, c_void_p]
-isl.isl_set_identity.restype = c_void_p
-isl.isl_set_identity.argtypes = [c_void_p]
-isl.isl_set_intersect.restype = c_void_p
-isl.isl_set_intersect.argtypes = [c_void_p, c_void_p]
-isl.isl_set_intersect_params.restype = c_void_p
-isl.isl_set_intersect_params.argtypes = [c_void_p, c_void_p]
-isl.isl_set_is_disjoint.restype = c_bool
-isl.isl_set_is_disjoint.argtypes = [c_void_p, c_void_p]
-isl.isl_set_is_empty.restype = c_bool
-isl.isl_set_is_empty.argtypes = [c_void_p]
-isl.isl_set_is_equal.restype = c_bool
-isl.isl_set_is_equal.argtypes = [c_void_p, c_void_p]
-isl.isl_set_is_strict_subset.restype = c_bool
-isl.isl_set_is_strict_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_set_is_subset.restype = c_bool
-isl.isl_set_is_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_set_is_wrapping.restype = c_bool
-isl.isl_set_is_wrapping.argtypes = [c_void_p]
-isl.isl_set_lexmax.restype = c_void_p
-isl.isl_set_lexmax.argtypes = [c_void_p]
-isl.isl_set_lexmin.restype = c_void_p
-isl.isl_set_lexmin.argtypes = [c_void_p]
-isl.isl_set_max_val.restype = c_void_p
-isl.isl_set_max_val.argtypes = [c_void_p, c_void_p]
-isl.isl_set_min_val.restype = c_void_p
-isl.isl_set_min_val.argtypes = [c_void_p, c_void_p]
-isl.isl_set_polyhedral_hull.restype = c_void_p
-isl.isl_set_polyhedral_hull.argtypes = [c_void_p]
-isl.isl_set_sample.restype = c_void_p
-isl.isl_set_sample.argtypes = [c_void_p]
-isl.isl_set_sample_point.restype = c_void_p
-isl.isl_set_sample_point.argtypes = [c_void_p]
-isl.isl_set_subtract.restype = c_void_p
-isl.isl_set_subtract.argtypes = [c_void_p, c_void_p]
-isl.isl_set_union.restype = c_void_p
-isl.isl_set_union.argtypes = [c_void_p, c_void_p]
-isl.isl_set_unshifted_simple_hull.restype = c_void_p
-isl.isl_set_unshifted_simple_hull.argtypes = [c_void_p]
-isl.isl_set_copy.restype = c_void_p
-isl.isl_set_copy.argtypes = [c_void_p]
-isl.isl_set_free.restype = c_void_p
-isl.isl_set_free.argtypes = [c_void_p]
-isl.isl_set_to_str.restype = POINTER(c_char)
-isl.isl_set_to_str.argtypes = [c_void_p]
+isl.isl_schedule_node_ancestor.restype = c_void_p
+isl.isl_schedule_node_ancestor.argtypes = [c_void_p, c_int]
+isl.isl_schedule_node_child.restype = c_void_p
+isl.isl_schedule_node_child.argtypes = [c_void_p, c_int]
+isl.isl_schedule_node_every_descendant.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_schedule_node_first_child.restype = c_void_p
+isl.isl_schedule_node_first_child.argtypes = [c_void_p]
+isl.isl_schedule_node_foreach_ancestor_top_down.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_schedule_node_foreach_descendant_top_down.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_schedule_node_from_domain.restype = c_void_p
+isl.isl_schedule_node_from_domain.argtypes = [c_void_p]
+isl.isl_schedule_node_from_extension.restype = c_void_p
+isl.isl_schedule_node_from_extension.argtypes = [c_void_p]
+isl.isl_schedule_node_get_ancestor_child_position.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_get_child_position.argtypes = [c_void_p]
+isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff.restype = c_void_p
+isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff.argtypes = [c_void_p]
+isl.isl_schedule_node_get_prefix_schedule_union_map.restype = c_void_p
+isl.isl_schedule_node_get_prefix_schedule_union_map.argtypes = [c_void_p]
+isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff.restype = c_void_p
+isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff.argtypes = [c_void_p]
+isl.isl_schedule_node_get_schedule.restype = c_void_p
+isl.isl_schedule_node_get_schedule.argtypes = [c_void_p]
+isl.isl_schedule_node_get_shared_ancestor.restype = c_void_p
+isl.isl_schedule_node_get_shared_ancestor.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_get_tree_depth.argtypes = [c_void_p]
+isl.isl_schedule_node_graft_after.restype = c_void_p
+isl.isl_schedule_node_graft_after.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_graft_before.restype = c_void_p
+isl.isl_schedule_node_graft_before.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_has_children.argtypes = [c_void_p]
+isl.isl_schedule_node_has_next_sibling.argtypes = [c_void_p]
+isl.isl_schedule_node_has_parent.argtypes = [c_void_p]
+isl.isl_schedule_node_has_previous_sibling.argtypes = [c_void_p]
+isl.isl_schedule_node_insert_context.restype = c_void_p
+isl.isl_schedule_node_insert_context.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_insert_filter.restype = c_void_p
+isl.isl_schedule_node_insert_filter.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_insert_guard.restype = c_void_p
+isl.isl_schedule_node_insert_guard.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_insert_mark.restype = c_void_p
+isl.isl_schedule_node_insert_mark.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_insert_partial_schedule.restype = c_void_p
+isl.isl_schedule_node_insert_partial_schedule.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_insert_sequence.restype = c_void_p
+isl.isl_schedule_node_insert_sequence.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_insert_set.restype = c_void_p
+isl.isl_schedule_node_insert_set.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_is_subtree_anchored.argtypes = [c_void_p]
+isl.isl_schedule_node_map_descendant_bottom_up.restype = c_void_p
+isl.isl_schedule_node_map_descendant_bottom_up.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_schedule_node_n_children.argtypes = [c_void_p]
+isl.isl_schedule_node_next_sibling.restype = c_void_p
+isl.isl_schedule_node_next_sibling.argtypes = [c_void_p]
+isl.isl_schedule_node_order_after.restype = c_void_p
+isl.isl_schedule_node_order_after.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_order_before.restype = c_void_p
+isl.isl_schedule_node_order_before.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_parent.restype = c_void_p
+isl.isl_schedule_node_parent.argtypes = [c_void_p]
+isl.isl_schedule_node_previous_sibling.restype = c_void_p
+isl.isl_schedule_node_previous_sibling.argtypes = [c_void_p]
+isl.isl_schedule_node_root.restype = c_void_p
+isl.isl_schedule_node_root.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+isl.isl_schedule_node_get_type.argtypes = [c_void_p]
 
-class basic_set(set):
+class schedule_node_band(schedule_node):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_basic_set_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
-        if len(args) == 1 and args[0].__class__ is point:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_basic_set_from_point(isl.isl_point_copy(args[0].ptr))
-            return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_basic_set_free(self.ptr)
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_band, cls).__new__(cls)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node_band:
+                arg0 = schedule_node_band(arg0)
         except:
             raise
-        ptr = isl.isl_basic_set_to_str(arg0.ptr)
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.basic_set("""%s""")' % s
+            return 'isl.schedule_node_band("""%s""")' % s
         else:
-            return 'isl.basic_set("%s")' % s
-    def affine_hull(arg0):
+            return 'isl.schedule_node_band("%s")' % s
+    def ast_build_options(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_affine_hull(isl.isl_basic_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def apply(arg0, arg1):
+        res = isl.isl_schedule_node_band_get_ast_build_options(arg0.ptr)
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def get_ast_build_options(arg0):
+        return arg0.ast_build_options()
+    def ast_isolate_option(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_band_get_ast_isolate_option(arg0.ptr)
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def get_ast_isolate_option(arg0):
+        return arg0.ast_isolate_option()
+    def partial_schedule(arg0):
         try:
-            if not arg1.__class__ is basic_map:
-                arg1 = basic_map(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
-            return set(arg0).apply(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_apply(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_map_copy(arg1.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def detect_equalities(arg0):
+        res = isl.isl_schedule_node_band_get_partial_schedule(arg0.ptr)
+        obj = multi_union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_partial_schedule(arg0):
+        return arg0.partial_schedule()
+    def permutable(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_detect_equalities(isl.isl_basic_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def dim_max_val(arg0, arg1):
+        res = isl.isl_schedule_node_band_get_permutable(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def get_permutable(arg0):
+        return arg0.permutable()
+    def member_get_coincident(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_dim_max_val(isl.isl_basic_set_copy(arg0.ptr), arg1)
-        return val(ctx=ctx, ptr=res)
-    def flatten(arg0):
+        res = isl.isl_schedule_node_band_member_get_coincident(arg0.ptr, arg1)
+        if res < 0:
+            raise
+        return bool(res)
+    def member_set_coincident(arg0, arg1, arg2):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_flatten(isl.isl_basic_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def gist(arg0, arg1):
+        res = isl.isl_schedule_node_band_member_set_coincident(isl.isl_schedule_node_copy(arg0.ptr), arg1, arg2)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def mod(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
-            return set(arg0).gist(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_gist(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def intersect(arg0, arg1):
+        res = isl.isl_schedule_node_band_mod(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def n_member(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_band_n_member(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+    def scale(arg0, arg1):
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
-            return set(arg0).intersect(arg1)
+            raise
+        try:
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
+        except:
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_intersect(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def intersect_params(arg0, arg1):
+        res = isl.isl_schedule_node_band_scale(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def scale_down(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
-            return set(arg0).intersect_params(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_intersect_params(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def is_empty(arg0):
+        res = isl.isl_schedule_node_band_scale_down(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def set_ast_build_options(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_is_empty(arg0.ptr)
-        if res < 0:
+        res = isl.isl_schedule_node_band_set_ast_build_options(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def set_permutable(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
             raise
-        return bool(res)
-    def is_equal(arg0, arg1):
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_band_set_permutable(isl.isl_schedule_node_copy(arg0.ptr), arg1)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def shift(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg1.__class__ is multi_union_pw_aff:
+                arg1 = multi_union_pw_aff(arg1)
         except:
-            return set(arg0).is_equal(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_is_equal(arg0.ptr, arg1.ptr)
-        if res < 0:
+        res = isl.isl_schedule_node_band_shift(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_multi_union_pw_aff_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def split(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
             raise
-        return bool(res)
-    def is_subset(arg0, arg1):
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_band_split(isl.isl_schedule_node_copy(arg0.ptr), arg1)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def tile(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg1.__class__ is multi_val:
+                arg1 = multi_val(arg1)
         except:
-            return set(arg0).is_subset(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_is_subset(arg0.ptr, arg1.ptr)
-        if res < 0:
+        res = isl.isl_schedule_node_band_tile(isl.isl_schedule_node_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def member_set_ast_loop_default(arg0, arg1):
+        try:
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
+        except:
             raise
-        return bool(res)
-    def is_wrapping(arg0):
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_band_member_set_ast_loop_type(isl.isl_schedule_node_copy(arg0.ptr), arg1, 0)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def member_set_ast_loop_atomic(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_is_wrapping(arg0.ptr)
-        if res < 0:
-            raise
-        return bool(res)
-    def lexmax(arg0):
+        res = isl.isl_schedule_node_band_member_set_ast_loop_type(isl.isl_schedule_node_copy(arg0.ptr), arg1, 1)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def member_set_ast_loop_unroll(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_lexmax(isl.isl_basic_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def lexmin(arg0):
+        res = isl.isl_schedule_node_band_member_set_ast_loop_type(isl.isl_schedule_node_copy(arg0.ptr), arg1, 2)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+    def member_set_ast_loop_separate(arg0, arg1):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_lexmin(isl.isl_basic_set_copy(arg0.ptr))
-        return set(ctx=ctx, ptr=res)
-    def sample(arg0):
+        res = isl.isl_schedule_node_band_member_set_ast_loop_type(isl.isl_schedule_node_copy(arg0.ptr), arg1, 3)
+        obj = schedule_node(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_schedule_node_band_get_ast_build_options.restype = c_void_p
+isl.isl_schedule_node_band_get_ast_build_options.argtypes = [c_void_p]
+isl.isl_schedule_node_band_get_ast_isolate_option.restype = c_void_p
+isl.isl_schedule_node_band_get_ast_isolate_option.argtypes = [c_void_p]
+isl.isl_schedule_node_band_get_partial_schedule.restype = c_void_p
+isl.isl_schedule_node_band_get_partial_schedule.argtypes = [c_void_p]
+isl.isl_schedule_node_band_get_permutable.argtypes = [c_void_p]
+isl.isl_schedule_node_band_member_get_coincident.argtypes = [c_void_p, c_int]
+isl.isl_schedule_node_band_member_set_coincident.restype = c_void_p
+isl.isl_schedule_node_band_member_set_coincident.argtypes = [c_void_p, c_int, c_int]
+isl.isl_schedule_node_band_mod.restype = c_void_p
+isl.isl_schedule_node_band_mod.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_band_n_member.argtypes = [c_void_p]
+isl.isl_schedule_node_band_scale.restype = c_void_p
+isl.isl_schedule_node_band_scale.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_band_scale_down.restype = c_void_p
+isl.isl_schedule_node_band_scale_down.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_band_set_ast_build_options.restype = c_void_p
+isl.isl_schedule_node_band_set_ast_build_options.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_band_set_permutable.restype = c_void_p
+isl.isl_schedule_node_band_set_permutable.argtypes = [c_void_p, c_int]
+isl.isl_schedule_node_band_shift.restype = c_void_p
+isl.isl_schedule_node_band_shift.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_band_split.restype = c_void_p
+isl.isl_schedule_node_band_split.argtypes = [c_void_p, c_int]
+isl.isl_schedule_node_band_tile.restype = c_void_p
+isl.isl_schedule_node_band_tile.argtypes = [c_void_p, c_void_p]
+isl.isl_schedule_node_band_member_set_ast_loop_type.restype = c_void_p
+isl.isl_schedule_node_band_member_set_ast_loop_type.argtypes = [c_void_p, c_int, c_int]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class schedule_node_context(schedule_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_context, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node_context:
+                arg0 = schedule_node_context(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_basic_set_sample(isl.isl_basic_set_copy(arg0.ptr))
-        return basic_set(ctx=ctx, ptr=res)
-    def sample_point(arg0):
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node_context("""%s""")' % s
+        else:
+            return 'isl.schedule_node_context("%s")' % s
+    def context(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_sample_point(isl.isl_basic_set_copy(arg0.ptr))
-        return point(ctx=ctx, ptr=res)
-    def union(arg0, arg1):
+        res = isl.isl_schedule_node_context_get_context(arg0.ptr)
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def get_context(arg0):
+        return arg0.context()
+
+isl.isl_schedule_node_context_get_context.restype = c_void_p
+isl.isl_schedule_node_context_get_context.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class schedule_node_domain(schedule_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_domain, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is basic_set:
-                arg0 = basic_set(arg0)
+            if not arg0.__class__ is schedule_node_domain:
+                arg0 = schedule_node_domain(arg0)
         except:
             raise
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node_domain("""%s""")' % s
+        else:
+            return 'isl.schedule_node_domain("%s")' % s
+    def domain(arg0):
         try:
-            if not arg1.__class__ is basic_set:
-                arg1 = basic_set(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
-            return set(arg0).union(arg1)
+            raise
         ctx = arg0.ctx
-        res = isl.isl_basic_set_union(isl.isl_basic_set_copy(arg0.ptr), isl.isl_basic_set_copy(arg1.ptr))
-        return set(ctx=ctx, ptr=res)
+        res = isl.isl_schedule_node_domain_get_domain(arg0.ptr)
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def get_domain(arg0):
+        return arg0.domain()
 
-isl.isl_basic_set_read_from_str.restype = c_void_p
-isl.isl_basic_set_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_basic_set_from_point.restype = c_void_p
-isl.isl_basic_set_from_point.argtypes = [c_void_p]
-isl.isl_basic_set_affine_hull.restype = c_void_p
-isl.isl_basic_set_affine_hull.argtypes = [c_void_p]
-isl.isl_basic_set_apply.restype = c_void_p
-isl.isl_basic_set_apply.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_set_detect_equalities.restype = c_void_p
-isl.isl_basic_set_detect_equalities.argtypes = [c_void_p]
-isl.isl_basic_set_dim_max_val.restype = c_void_p
-isl.isl_basic_set_dim_max_val.argtypes = [c_void_p, c_int]
-isl.isl_basic_set_flatten.restype = c_void_p
-isl.isl_basic_set_flatten.argtypes = [c_void_p]
-isl.isl_basic_set_gist.restype = c_void_p
-isl.isl_basic_set_gist.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_set_intersect.restype = c_void_p
-isl.isl_basic_set_intersect.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_set_intersect_params.restype = c_void_p
-isl.isl_basic_set_intersect_params.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_set_is_empty.restype = c_bool
-isl.isl_basic_set_is_empty.argtypes = [c_void_p]
-isl.isl_basic_set_is_equal.restype = c_bool
-isl.isl_basic_set_is_equal.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_set_is_subset.restype = c_bool
-isl.isl_basic_set_is_subset.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_set_is_wrapping.restype = c_bool
-isl.isl_basic_set_is_wrapping.argtypes = [c_void_p]
-isl.isl_basic_set_lexmax.restype = c_void_p
-isl.isl_basic_set_lexmax.argtypes = [c_void_p]
-isl.isl_basic_set_lexmin.restype = c_void_p
-isl.isl_basic_set_lexmin.argtypes = [c_void_p]
-isl.isl_basic_set_sample.restype = c_void_p
-isl.isl_basic_set_sample.argtypes = [c_void_p]
-isl.isl_basic_set_sample_point.restype = c_void_p
-isl.isl_basic_set_sample_point.argtypes = [c_void_p]
-isl.isl_basic_set_union.restype = c_void_p
-isl.isl_basic_set_union.argtypes = [c_void_p, c_void_p]
-isl.isl_basic_set_copy.restype = c_void_p
-isl.isl_basic_set_copy.argtypes = [c_void_p]
-isl.isl_basic_set_free.restype = c_void_p
-isl.isl_basic_set_free.argtypes = [c_void_p]
-isl.isl_basic_set_to_str.restype = POINTER(c_char)
-isl.isl_basic_set_to_str.argtypes = [c_void_p]
+isl.isl_schedule_node_domain_get_domain.restype = c_void_p
+isl.isl_schedule_node_domain_get_domain.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
 
-class multi_val(object):
+class schedule_node_expansion(schedule_node):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
@@ -4281,96 +12168,212 @@ def __init__(self, *args, **keywords):
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_multi_val_free(self.ptr)
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_expansion, cls).__new__(cls)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is multi_val:
-                arg0 = multi_val(arg0)
+            if not arg0.__class__ is schedule_node_expansion:
+                arg0 = schedule_node_expansion(arg0)
         except:
             raise
-        ptr = isl.isl_multi_val_to_str(arg0.ptr)
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.multi_val("""%s""")' % s
+            return 'isl.schedule_node_expansion("""%s""")' % s
         else:
-            return 'isl.multi_val("%s")' % s
-    def add(arg0, arg1):
+            return 'isl.schedule_node_expansion("%s")' % s
+    def contraction(arg0):
         try:
-            if not arg0.__class__ is multi_val:
-                arg0 = multi_val(arg0)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_schedule_node_expansion_get_contraction(arg0.ptr)
+        obj = union_pw_multi_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_contraction(arg0):
+        return arg0.contraction()
+    def expansion(arg0):
         try:
-            if not arg1.__class__ is multi_val:
-                arg1 = multi_val(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_multi_val_add(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
-        return multi_val(ctx=ctx, ptr=res)
-    def flat_range_product(arg0, arg1):
+        res = isl.isl_schedule_node_expansion_get_expansion(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_expansion(arg0):
+        return arg0.expansion()
+
+isl.isl_schedule_node_expansion_get_contraction.restype = c_void_p
+isl.isl_schedule_node_expansion_get_contraction.argtypes = [c_void_p]
+isl.isl_schedule_node_expansion_get_expansion.restype = c_void_p
+isl.isl_schedule_node_expansion_get_expansion.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class schedule_node_extension(schedule_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_extension, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is multi_val:
-                arg0 = multi_val(arg0)
+            if not arg0.__class__ is schedule_node_extension:
+                arg0 = schedule_node_extension(arg0)
         except:
             raise
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node_extension("""%s""")' % s
+        else:
+            return 'isl.schedule_node_extension("%s")' % s
+    def extension(arg0):
         try:
-            if not arg1.__class__ is multi_val:
-                arg1 = multi_val(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_multi_val_flat_range_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
-        return multi_val(ctx=ctx, ptr=res)
-    def product(arg0, arg1):
+        res = isl.isl_schedule_node_extension_get_extension(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_extension(arg0):
+        return arg0.extension()
+
+isl.isl_schedule_node_extension_get_extension.restype = c_void_p
+isl.isl_schedule_node_extension_get_extension.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class schedule_node_filter(schedule_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_filter, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is multi_val:
-                arg0 = multi_val(arg0)
+            if not arg0.__class__ is schedule_node_filter:
+                arg0 = schedule_node_filter(arg0)
         except:
             raise
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node_filter("""%s""")' % s
+        else:
+            return 'isl.schedule_node_filter("%s")' % s
+    def filter(arg0):
         try:
-            if not arg1.__class__ is multi_val:
-                arg1 = multi_val(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_multi_val_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
-        return multi_val(ctx=ctx, ptr=res)
-    def range_product(arg0, arg1):
+        res = isl.isl_schedule_node_filter_get_filter(arg0.ptr)
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def get_filter(arg0):
+        return arg0.filter()
+
+isl.isl_schedule_node_filter_get_filter.restype = c_void_p
+isl.isl_schedule_node_filter_get_filter.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class schedule_node_guard(schedule_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_guard, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is multi_val:
-                arg0 = multi_val(arg0)
+            if not arg0.__class__ is schedule_node_guard:
+                arg0 = schedule_node_guard(arg0)
         except:
             raise
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node_guard("""%s""")' % s
+        else:
+            return 'isl.schedule_node_guard("%s")' % s
+    def guard(arg0):
         try:
-            if not arg1.__class__ is multi_val:
-                arg1 = multi_val(arg1)
+            if not arg0.__class__ is schedule_node:
+                arg0 = schedule_node(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_multi_val_range_product(isl.isl_multi_val_copy(arg0.ptr), isl.isl_multi_val_copy(arg1.ptr))
-        return multi_val(ctx=ctx, ptr=res)
+        res = isl.isl_schedule_node_guard_get_guard(arg0.ptr)
+        obj = set(ctx=ctx, ptr=res)
+        return obj
+    def get_guard(arg0):
+        return arg0.guard()
 
-isl.isl_multi_val_add.restype = c_void_p
-isl.isl_multi_val_add.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_val_flat_range_product.restype = c_void_p
-isl.isl_multi_val_flat_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_val_product.restype = c_void_p
-isl.isl_multi_val_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_val_range_product.restype = c_void_p
-isl.isl_multi_val_range_product.argtypes = [c_void_p, c_void_p]
-isl.isl_multi_val_copy.restype = c_void_p
-isl.isl_multi_val_copy.argtypes = [c_void_p]
-isl.isl_multi_val_free.restype = c_void_p
-isl.isl_multi_val_free.argtypes = [c_void_p]
-isl.isl_multi_val_to_str.restype = POINTER(c_char)
-isl.isl_multi_val_to_str.argtypes = [c_void_p]
+isl.isl_schedule_node_guard_get_guard.restype = c_void_p
+isl.isl_schedule_node_guard_get_guard.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
 
-class point(basic_set):
+class schedule_node_leaf(schedule_node):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
@@ -4379,215 +12382,376 @@ def __init__(self, *args, **keywords):
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_point_free(self.ptr)
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_leaf, cls).__new__(cls)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is point:
-                arg0 = point(arg0)
+            if not arg0.__class__ is schedule_node_leaf:
+                arg0 = schedule_node_leaf(arg0)
         except:
             raise
-        ptr = isl.isl_point_to_str(arg0.ptr)
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.point("""%s""")' % s
+            return 'isl.schedule_node_leaf("""%s""")' % s
         else:
-            return 'isl.point("%s")' % s
+            return 'isl.schedule_node_leaf("%s")' % s
 
-isl.isl_point_copy.restype = c_void_p
-isl.isl_point_copy.argtypes = [c_void_p]
-isl.isl_point_free.restype = c_void_p
-isl.isl_point_free.argtypes = [c_void_p]
-isl.isl_point_to_str.restype = POINTER(c_char)
-isl.isl_point_to_str.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
 
-class schedule(object):
+class schedule_node_mark(schedule_node):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_schedule_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_schedule_free(self.ptr)
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_mark, cls).__new__(cls)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is schedule:
-                arg0 = schedule(arg0)
+            if not arg0.__class__ is schedule_node_mark:
+                arg0 = schedule_node_mark(arg0)
         except:
             raise
-        ptr = isl.isl_schedule_to_str(arg0.ptr)
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.schedule("""%s""")' % s
+            return 'isl.schedule_node_mark("""%s""")' % s
         else:
-            return 'isl.schedule("%s")' % s
-    def get_map(arg0):
+            return 'isl.schedule_node_mark("%s")' % s
+
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class schedule_node_sequence(schedule_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_sequence, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is schedule:
-                arg0 = schedule(arg0)
+            if not arg0.__class__ is schedule_node_sequence:
+                arg0 = schedule_node_sequence(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_schedule_get_map(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_root(arg0):
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node_sequence("""%s""")' % s
+        else:
+            return 'isl.schedule_node_sequence("%s")' % s
+
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+
+class schedule_node_set(schedule_node):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_schedule_node_free(self.ptr)
+    def __new__(cls, *args, **keywords):
+        return super(schedule_node_set, cls).__new__(cls)
+    def __str__(arg0):
         try:
-            if not arg0.__class__ is schedule:
-                arg0 = schedule(arg0)
+            if not arg0.__class__ is schedule_node_set:
+                arg0 = schedule_node_set(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_schedule_get_root(arg0.ptr)
-        return schedule_node(ctx=ctx, ptr=res)
-    def pullback(arg0, arg1):
-        if arg1.__class__ is union_pw_multi_aff:
-            res = isl.isl_schedule_pullback_union_pw_multi_aff(isl.isl_schedule_copy(arg0.ptr), isl.isl_union_pw_multi_aff_copy(arg1.ptr))
-            return schedule(ctx=arg0.ctx, ptr=res)
+        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.schedule_node_set("""%s""")' % s
+        else:
+            return 'isl.schedule_node_set("%s")' % s
 
-isl.isl_schedule_read_from_str.restype = c_void_p
-isl.isl_schedule_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_schedule_get_map.restype = c_void_p
-isl.isl_schedule_get_map.argtypes = [c_void_p]
-isl.isl_schedule_get_root.restype = c_void_p
-isl.isl_schedule_get_root.argtypes = [c_void_p]
-isl.isl_schedule_pullback_union_pw_multi_aff.restype = c_void_p
-isl.isl_schedule_pullback_union_pw_multi_aff.argtypes = [c_void_p, c_void_p]
-isl.isl_schedule_copy.restype = c_void_p
-isl.isl_schedule_copy.argtypes = [c_void_p]
-isl.isl_schedule_free.restype = c_void_p
-isl.isl_schedule_free.argtypes = [c_void_p]
-isl.isl_schedule_to_str.restype = POINTER(c_char)
-isl.isl_schedule_to_str.argtypes = [c_void_p]
+isl.isl_schedule_node_copy.restype = c_void_p
+isl.isl_schedule_node_copy.argtypes = [c_void_p]
+isl.isl_schedule_node_free.restype = c_void_p
+isl.isl_schedule_node_free.argtypes = [c_void_p]
+isl.isl_schedule_node_to_str.restype = POINTER(c_char)
+isl.isl_schedule_node_to_str.argtypes = [c_void_p]
 
-class schedule_constraints(object):
+class space(object):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_schedule_constraints_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_schedule_constraints_free(self.ptr)
+            isl.isl_space_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
-        ptr = isl.isl_schedule_constraints_to_str(arg0.ptr)
+        ptr = isl.isl_space_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.schedule_constraints("""%s""")' % s
+            return 'isl.space("""%s""")' % s
         else:
-            return 'isl.schedule_constraints("%s")' % s
-    def compute_schedule(arg0):
+            return 'isl.space("%s")' % s
+    def add_named_tuple(*args):
+        if len(args) == 3 and (args[1].__class__ is id or type(args[1]) == str) and type(args[2]) == int:
+            args = list(args)
+            try:
+                if not args[1].__class__ is id:
+                    args[1] = id(args[1])
+            except:
+                raise
+            ctx = args[0].ctx
+            res = isl.isl_space_add_named_tuple_id_ui(isl.isl_space_copy(args[0].ptr), isl.isl_id_copy(args[1].ptr), args[2])
+            obj = space(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def add_unnamed_tuple(*args):
+        if len(args) == 2 and type(args[1]) == int:
+            ctx = args[0].ctx
+            res = isl.isl_space_add_unnamed_tuple_ui(isl.isl_space_copy(args[0].ptr), args[1])
+            obj = space(ctx=ctx, ptr=res)
+            return obj
+        raise Error
+    def domain(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_compute_schedule(isl.isl_schedule_constraints_copy(arg0.ptr))
-        return schedule(ctx=ctx, ptr=res)
-    def get_coincidence(arg0):
+        res = isl.isl_space_domain(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def flatten_domain(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_get_coincidence(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_conditional_validity(arg0):
+        res = isl.isl_space_flatten_domain(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def flatten_range(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_get_conditional_validity(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_conditional_validity_condition(arg0):
+        res = isl.isl_space_flatten_range(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def is_equal(arg0, arg1):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is space:
+                arg1 = space(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_get_conditional_validity_condition(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_context(arg0):
+        res = isl.isl_space_is_equal(arg0.ptr, arg1.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def is_wrapping(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_get_context(arg0.ptr)
-        return set(ctx=ctx, ptr=res)
-    def get_domain(arg0):
+        res = isl.isl_space_is_wrapping(arg0.ptr)
+        if res < 0:
+            raise
+        return bool(res)
+    def map_from_set(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_get_domain(arg0.ptr)
-        return union_set(ctx=ctx, ptr=res)
-    def get_proximity(arg0):
+        res = isl.isl_space_map_from_set(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def params(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_get_proximity(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_validity(arg0):
+        res = isl.isl_space_params(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def range(arg0):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_get_validity(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
+        res = isl.isl_space_range(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
     @staticmethod
-    def on_domain(arg0):
+    def unit():
+        ctx = Context.getDefaultInstance()
+        res = isl.isl_space_unit(ctx)
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def unwrap(arg0):
         try:
-            if not arg0.__class__ is union_set:
-                arg0 = union_set(arg0)
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_on_domain(isl.isl_union_set_copy(arg0.ptr))
-        return schedule_constraints(ctx=ctx, ptr=res)
-    def set_coincidence(arg0, arg1):
+        res = isl.isl_space_unwrap(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+    def wrap(arg0):
+        try:
+            if not arg0.__class__ is space:
+                arg0 = space(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_space_wrap(isl.isl_space_copy(arg0.ptr))
+        obj = space(ctx=ctx, ptr=res)
+        return obj
+
+isl.isl_space_add_named_tuple_id_ui.restype = c_void_p
+isl.isl_space_add_named_tuple_id_ui.argtypes = [c_void_p, c_void_p, c_int]
+isl.isl_space_add_unnamed_tuple_ui.restype = c_void_p
+isl.isl_space_add_unnamed_tuple_ui.argtypes = [c_void_p, c_int]
+isl.isl_space_domain.restype = c_void_p
+isl.isl_space_domain.argtypes = [c_void_p]
+isl.isl_space_flatten_domain.restype = c_void_p
+isl.isl_space_flatten_domain.argtypes = [c_void_p]
+isl.isl_space_flatten_range.restype = c_void_p
+isl.isl_space_flatten_range.argtypes = [c_void_p]
+isl.isl_space_is_equal.argtypes = [c_void_p, c_void_p]
+isl.isl_space_is_wrapping.argtypes = [c_void_p]
+isl.isl_space_map_from_set.restype = c_void_p
+isl.isl_space_map_from_set.argtypes = [c_void_p]
+isl.isl_space_params.restype = c_void_p
+isl.isl_space_params.argtypes = [c_void_p]
+isl.isl_space_range.restype = c_void_p
+isl.isl_space_range.argtypes = [c_void_p]
+isl.isl_space_unit.restype = c_void_p
+isl.isl_space_unit.argtypes = [Context]
+isl.isl_space_unwrap.restype = c_void_p
+isl.isl_space_unwrap.argtypes = [c_void_p]
+isl.isl_space_wrap.restype = c_void_p
+isl.isl_space_wrap.argtypes = [c_void_p]
+isl.isl_space_copy.restype = c_void_p
+isl.isl_space_copy.argtypes = [c_void_p]
+isl.isl_space_free.restype = c_void_p
+isl.isl_space_free.argtypes = [c_void_p]
+isl.isl_space_to_str.restype = POINTER(c_char)
+isl.isl_space_to_str.argtypes = [c_void_p]
+
+class union_access_info(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and args[0].__class__ is union_map:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_access_info_from_sink(isl.isl_union_map_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_union_access_info_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        ptr = isl.isl_union_access_info_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.union_access_info("""%s""")' % s
+        else:
+            return 'isl.union_access_info("%s")' % s
+    def compute_flow(arg0):
+        try:
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_union_access_info_compute_flow(isl.isl_union_access_info_copy(arg0.ptr))
+        obj = union_flow(ctx=ctx, ptr=res)
+        return obj
+    def set_kill(arg0, arg1):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
         except:
             raise
         try:
@@ -4596,12 +12760,13 @@ def set_coincidence(arg0, arg1):
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_set_coincidence(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return schedule_constraints(ctx=ctx, ptr=res)
-    def set_conditional_validity(arg0, arg1, arg2):
+        res = isl.isl_union_access_info_set_kill(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_access_info(ctx=ctx, ptr=res)
+        return obj
+    def set_may_source(arg0, arg1):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
         except:
             raise
         try:
@@ -4609,46 +12774,44 @@ def set_conditional_validity(arg0, arg1, arg2):
                 arg1 = union_map(arg1)
         except:
             raise
-        try:
-            if not arg2.__class__ is union_map:
-                arg2 = union_map(arg2)
-        except:
-            raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_set_conditional_validity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr), isl.isl_union_map_copy(arg2.ptr))
-        return schedule_constraints(ctx=ctx, ptr=res)
-    def set_context(arg0, arg1):
+        res = isl.isl_union_access_info_set_may_source(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_access_info(ctx=ctx, ptr=res)
+        return obj
+    def set_must_source(arg0, arg1):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is set:
-                arg1 = set(arg1)
+            if not arg1.__class__ is union_map:
+                arg1 = union_map(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_set_context(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_set_copy(arg1.ptr))
-        return schedule_constraints(ctx=ctx, ptr=res)
-    def set_proximity(arg0, arg1):
+        res = isl.isl_union_access_info_set_must_source(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_access_info(ctx=ctx, ptr=res)
+        return obj
+    def set_schedule(arg0, arg1):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is schedule:
+                arg1 = schedule(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_set_proximity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return schedule_constraints(ctx=ctx, ptr=res)
-    def set_validity(arg0, arg1):
+        res = isl.isl_union_access_info_set_schedule(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_schedule_copy(arg1.ptr))
+        obj = union_access_info(ctx=ctx, ptr=res)
+        return obj
+    def set_schedule_map(arg0, arg1):
         try:
-            if not arg0.__class__ is schedule_constraints:
-                arg0 = schedule_constraints(arg0)
+            if not arg0.__class__ is union_access_info:
+                arg0 = union_access_info(arg0)
         except:
             raise
         try:
@@ -4657,47 +12820,32 @@ def set_validity(arg0, arg1):
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_constraints_set_validity(isl.isl_schedule_constraints_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return schedule_constraints(ctx=ctx, ptr=res)
+        res = isl.isl_union_access_info_set_schedule_map(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
+        obj = union_access_info(ctx=ctx, ptr=res)
+        return obj
 
-isl.isl_schedule_constraints_read_from_str.restype = c_void_p
-isl.isl_schedule_constraints_read_from_str.argtypes = [Context, c_char_p]
-isl.isl_schedule_constraints_compute_schedule.restype = c_void_p
-isl.isl_schedule_constraints_compute_schedule.argtypes = [c_void_p]
-isl.isl_schedule_constraints_get_coincidence.restype = c_void_p
-isl.isl_schedule_constraints_get_coincidence.argtypes = [c_void_p]
-isl.isl_schedule_constraints_get_conditional_validity.restype = c_void_p
-isl.isl_schedule_constraints_get_conditional_validity.argtypes = [c_void_p]
-isl.isl_schedule_constraints_get_conditional_validity_condition.restype = c_void_p
-isl.isl_schedule_constraints_get_conditional_validity_condition.argtypes = [c_void_p]
-isl.isl_schedule_constraints_get_context.restype = c_void_p
-isl.isl_schedule_constraints_get_context.argtypes = [c_void_p]
-isl.isl_schedule_constraints_get_domain.restype = c_void_p
-isl.isl_schedule_constraints_get_domain.argtypes = [c_void_p]
-isl.isl_schedule_constraints_get_proximity.restype = c_void_p
-isl.isl_schedule_constraints_get_proximity.argtypes = [c_void_p]
-isl.isl_schedule_constraints_get_validity.restype = c_void_p
-isl.isl_schedule_constraints_get_validity.argtypes = [c_void_p]
-isl.isl_schedule_constraints_on_domain.restype = c_void_p
-isl.isl_schedule_constraints_on_domain.argtypes = [c_void_p]
-isl.isl_schedule_constraints_set_coincidence.restype = c_void_p
-isl.isl_schedule_constraints_set_coincidence.argtypes = [c_void_p, c_void_p]
-isl.isl_schedule_constraints_set_conditional_validity.restype = c_void_p
-isl.isl_schedule_constraints_set_conditional_validity.argtypes = [c_void_p, c_void_p, c_void_p]
-isl.isl_schedule_constraints_set_context.restype = c_void_p
-isl.isl_schedule_constraints_set_context.argtypes = [c_void_p, c_void_p]
-isl.isl_schedule_constraints_set_proximity.restype = c_void_p
-isl.isl_schedule_constraints_set_proximity.argtypes = [c_void_p, c_void_p]
-isl.isl_schedule_constraints_set_validity.restype = c_void_p
-isl.isl_schedule_constraints_set_validity.argtypes = [c_void_p, c_void_p]
-isl.isl_schedule_constraints_copy.restype = c_void_p
-isl.isl_schedule_constraints_copy.argtypes = [c_void_p]
-isl.isl_schedule_constraints_free.restype = c_void_p
-isl.isl_schedule_constraints_free.argtypes = [c_void_p]
-isl.isl_schedule_constraints_to_str.restype = POINTER(c_char)
-isl.isl_schedule_constraints_to_str.argtypes = [c_void_p]
+isl.isl_union_access_info_from_sink.restype = c_void_p
+isl.isl_union_access_info_from_sink.argtypes = [c_void_p]
+isl.isl_union_access_info_compute_flow.restype = c_void_p
+isl.isl_union_access_info_compute_flow.argtypes = [c_void_p]
+isl.isl_union_access_info_set_kill.restype = c_void_p
+isl.isl_union_access_info_set_kill.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_may_source.restype = c_void_p
+isl.isl_union_access_info_set_may_source.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_must_source.restype = c_void_p
+isl.isl_union_access_info_set_must_source.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_schedule.restype = c_void_p
+isl.isl_union_access_info_set_schedule.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_set_schedule_map.restype = c_void_p
+isl.isl_union_access_info_set_schedule_map.argtypes = [c_void_p, c_void_p]
+isl.isl_union_access_info_copy.restype = c_void_p
+isl.isl_union_access_info_copy.argtypes = [c_void_p]
+isl.isl_union_access_info_free.restype = c_void_p
+isl.isl_union_access_info_free.argtypes = [c_void_p]
+isl.isl_union_access_info_to_str.restype = POINTER(c_char)
+isl.isl_union_access_info_to_str.argtypes = [c_void_p]
 
-class schedule_node(object):
+class union_flow(object):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
@@ -4706,351 +12854,400 @@ def __init__(self, *args, **keywords):
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_schedule_node_free(self.ptr)
+            isl.isl_union_flow_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
         except:
             raise
-        ptr = isl.isl_schedule_node_to_str(arg0.ptr)
+        ptr = isl.isl_union_flow_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.schedule_node("""%s""")' % s
+            return 'isl.union_flow("""%s""")' % s
         else:
-            return 'isl.schedule_node("%s")' % s
-    def band_member_get_coincident(arg0, arg1):
-        try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
-        except:
-            raise
-        ctx = arg0.ctx
-        res = isl.isl_schedule_node_band_member_get_coincident(arg0.ptr, arg1)
-        if res < 0:
-            raise
-        return bool(res)
-    def band_member_set_coincident(arg0, arg1, arg2):
-        try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
-        except:
-            raise
-        ctx = arg0.ctx
-        res = isl.isl_schedule_node_band_member_set_coincident(isl.isl_schedule_node_copy(arg0.ptr), arg1, arg2)
-        return schedule_node(ctx=ctx, ptr=res)
-    def child(arg0, arg1):
+            return 'isl.union_flow("%s")' % s
+    def full_may_dependence(arg0):
         try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_node_child(isl.isl_schedule_node_copy(arg0.ptr), arg1)
-        return schedule_node(ctx=ctx, ptr=res)
-    def get_prefix_schedule_multi_union_pw_aff(arg0):
+        res = isl.isl_union_flow_get_full_may_dependence(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_full_may_dependence(arg0):
+        return arg0.full_may_dependence()
+    def full_must_dependence(arg0):
         try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(arg0.ptr)
-        return multi_union_pw_aff(ctx=ctx, ptr=res)
-    def get_prefix_schedule_union_map(arg0):
+        res = isl.isl_union_flow_get_full_must_dependence(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_full_must_dependence(arg0):
+        return arg0.full_must_dependence()
+    def may_dependence(arg0):
         try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_node_get_prefix_schedule_union_map(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_prefix_schedule_union_pw_multi_aff(arg0):
+        res = isl.isl_union_flow_get_may_dependence(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_may_dependence(arg0):
+        return arg0.may_dependence()
+    def may_no_source(arg0):
         try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(arg0.ptr)
-        return union_pw_multi_aff(ctx=ctx, ptr=res)
-    def get_schedule(arg0):
+        res = isl.isl_union_flow_get_may_no_source(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_may_no_source(arg0):
+        return arg0.may_no_source()
+    def must_dependence(arg0):
         try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_node_get_schedule(arg0.ptr)
-        return schedule(ctx=ctx, ptr=res)
-    def parent(arg0):
+        res = isl.isl_union_flow_get_must_dependence(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_must_dependence(arg0):
+        return arg0.must_dependence()
+    def must_no_source(arg0):
         try:
-            if not arg0.__class__ is schedule_node:
-                arg0 = schedule_node(arg0)
+            if not arg0.__class__ is union_flow:
+                arg0 = union_flow(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_schedule_node_parent(isl.isl_schedule_node_copy(arg0.ptr))
-        return schedule_node(ctx=ctx, ptr=res)
+        res = isl.isl_union_flow_get_must_no_source(arg0.ptr)
+        obj = union_map(ctx=ctx, ptr=res)
+        return obj
+    def get_must_no_source(arg0):
+        return arg0.must_no_source()
 
-isl.isl_schedule_node_band_member_get_coincident.restype = c_bool
-isl.isl_schedule_node_band_member_get_coincident.argtypes = [c_void_p, c_int]
-isl.isl_schedule_node_band_member_set_coincident.restype = c_void_p
-isl.isl_schedule_node_band_member_set_coincident.argtypes = [c_void_p, c_int, c_int]
-isl.isl_schedule_node_child.restype = c_void_p
-isl.isl_schedule_node_child.argtypes = [c_void_p, c_int]
-isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff.restype = c_void_p
-isl.isl_schedule_node_get_prefix_schedule_multi_union_pw_aff.argtypes = [c_void_p]
-isl.isl_schedule_node_get_prefix_schedule_union_map.restype = c_void_p
-isl.isl_schedule_node_get_prefix_schedule_union_map.argtypes = [c_void_p]
-isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff.restype = c_void_p
-isl.isl_schedule_node_get_prefix_schedule_union_pw_multi_aff.argtypes = [c_void_p]
-isl.isl_schedule_node_get_schedule.restype = c_void_p
-isl.isl_schedule_node_get_schedule.argtypes = [c_void_p]
-isl.isl_schedule_node_parent.restype = c_void_p
-isl.isl_schedule_node_parent.argtypes = [c_void_p]
-isl.isl_schedule_node_copy.restype = c_void_p
-isl.isl_schedule_node_copy.argtypes = [c_void_p]
-isl.isl_schedule_node_free.restype = c_void_p
-isl.isl_schedule_node_free.argtypes = [c_void_p]
-isl.isl_schedule_node_to_str.restype = POINTER(c_char)
-isl.isl_schedule_node_to_str.argtypes = [c_void_p]
+isl.isl_union_flow_get_full_may_dependence.restype = c_void_p
+isl.isl_union_flow_get_full_may_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_full_must_dependence.restype = c_void_p
+isl.isl_union_flow_get_full_must_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_may_dependence.restype = c_void_p
+isl.isl_union_flow_get_may_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_may_no_source.restype = c_void_p
+isl.isl_union_flow_get_may_no_source.argtypes = [c_void_p]
+isl.isl_union_flow_get_must_dependence.restype = c_void_p
+isl.isl_union_flow_get_must_dependence.argtypes = [c_void_p]
+isl.isl_union_flow_get_must_no_source.restype = c_void_p
+isl.isl_union_flow_get_must_no_source.argtypes = [c_void_p]
+isl.isl_union_flow_copy.restype = c_void_p
+isl.isl_union_flow_copy.argtypes = [c_void_p]
+isl.isl_union_flow_free.restype = c_void_p
+isl.isl_union_flow_free.argtypes = [c_void_p]
+isl.isl_union_flow_to_str.restype = POINTER(c_char)
+isl.isl_union_flow_to_str.argtypes = [c_void_p]
 
-class union_access_info(object):
+class union_pw_aff_list(object):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and args[0].__class__ is union_map:
+        if len(args) == 1 and type(args[0]) == int:
             self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_union_access_info_from_sink(isl.isl_union_map_copy(args[0].ptr))
+            self.ptr = isl.isl_union_pw_aff_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and args[0].__class__ is union_pw_aff:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_pw_aff_list_from_union_pw_aff(isl.isl_union_pw_aff_copy(args[0].ptr))
             return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_union_access_info_free(self.ptr)
+            isl.isl_union_pw_aff_list_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is union_access_info:
-                arg0 = union_access_info(arg0)
+            if not arg0.__class__ is union_pw_aff_list:
+                arg0 = union_pw_aff_list(arg0)
         except:
             raise
-        ptr = isl.isl_union_access_info_to_str(arg0.ptr)
+        ptr = isl.isl_union_pw_aff_list_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.union_access_info("""%s""")' % s
+            return 'isl.union_pw_aff_list("""%s""")' % s
         else:
-            return 'isl.union_access_info("%s")' % s
-    def compute_flow(arg0):
-        try:
-            if not arg0.__class__ is union_access_info:
-                arg0 = union_access_info(arg0)
-        except:
-            raise
-        ctx = arg0.ctx
-        res = isl.isl_union_access_info_compute_flow(isl.isl_union_access_info_copy(arg0.ptr))
-        return union_flow(ctx=ctx, ptr=res)
-    def set_kill(arg0, arg1):
-        try:
-            if not arg0.__class__ is union_access_info:
-                arg0 = union_access_info(arg0)
-        except:
-            raise
+            return 'isl.union_pw_aff_list("%s")' % s
+    def add(arg0, arg1):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is union_pw_aff_list:
+                arg0 = union_pw_aff_list(arg0)
         except:
             raise
-        ctx = arg0.ctx
-        res = isl.isl_union_access_info_set_kill(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_access_info(ctx=ctx, ptr=res)
-    def set_may_source(arg0, arg1):
         try:
-            if not arg0.__class__ is union_access_info:
-                arg0 = union_access_info(arg0)
+            if not arg1.__class__ is union_pw_aff:
+                arg1 = union_pw_aff(arg1)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_list_add(isl.isl_union_pw_aff_list_copy(arg0.ptr), isl.isl_union_pw_aff_copy(arg1.ptr))
+        obj = union_pw_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is union_pw_aff_list:
+                arg0 = union_pw_aff_list(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_access_info_set_may_source(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_access_info(ctx=ctx, ptr=res)
-    def set_must_source(arg0, arg1):
+        res = isl.isl_union_pw_aff_list_clear(isl.isl_union_pw_aff_list_copy(arg0.ptr))
+        obj = union_pw_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
         try:
-            if not arg0.__class__ is union_access_info:
-                arg0 = union_access_info(arg0)
+            if not arg0.__class__ is union_pw_aff_list:
+                arg0 = union_pw_aff_list(arg0)
         except:
             raise
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg1.__class__ is union_pw_aff_list:
+                arg1 = union_pw_aff_list(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_access_info_set_must_source(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_access_info(ctx=ctx, ptr=res)
-    def set_schedule(arg0, arg1):
-        try:
-            if not arg0.__class__ is union_access_info:
-                arg0 = union_access_info(arg0)
-        except:
-            raise
+        res = isl.isl_union_pw_aff_list_concat(isl.isl_union_pw_aff_list_copy(arg0.ptr), isl.isl_union_pw_aff_list_copy(arg1.ptr))
+        obj = union_pw_aff_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
         try:
-            if not arg1.__class__ is schedule:
-                arg1 = schedule(arg1)
+            if not arg0.__class__ is union_pw_aff_list:
+                arg0 = union_pw_aff_list(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = union_pw_aff(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_union_access_info_set_schedule(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_schedule_copy(arg1.ptr))
-        return union_access_info(ctx=ctx, ptr=res)
-    def set_schedule_map(arg0, arg1):
+        res = isl.isl_union_pw_aff_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is union_access_info:
-                arg0 = union_access_info(arg0)
+            if not arg0.__class__ is union_pw_aff_list:
+                arg0 = union_pw_aff_list(arg0)
         except:
             raise
+        ctx = arg0.ctx
+        res = isl.isl_union_pw_aff_list_get_at(arg0.ptr, arg1)
+        obj = union_pw_aff(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
         try:
-            if not arg1.__class__ is union_map:
-                arg1 = union_map(arg1)
+            if not arg0.__class__ is union_pw_aff_list:
+                arg0 = union_pw_aff_list(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_access_info_set_schedule_map(isl.isl_union_access_info_copy(arg0.ptr), isl.isl_union_map_copy(arg1.ptr))
-        return union_access_info(ctx=ctx, ptr=res)
+        res = isl.isl_union_pw_aff_list_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
 
-isl.isl_union_access_info_from_sink.restype = c_void_p
-isl.isl_union_access_info_from_sink.argtypes = [c_void_p]
-isl.isl_union_access_info_compute_flow.restype = c_void_p
-isl.isl_union_access_info_compute_flow.argtypes = [c_void_p]
-isl.isl_union_access_info_set_kill.restype = c_void_p
-isl.isl_union_access_info_set_kill.argtypes = [c_void_p, c_void_p]
-isl.isl_union_access_info_set_may_source.restype = c_void_p
-isl.isl_union_access_info_set_may_source.argtypes = [c_void_p, c_void_p]
-isl.isl_union_access_info_set_must_source.restype = c_void_p
-isl.isl_union_access_info_set_must_source.argtypes = [c_void_p, c_void_p]
-isl.isl_union_access_info_set_schedule.restype = c_void_p
-isl.isl_union_access_info_set_schedule.argtypes = [c_void_p, c_void_p]
-isl.isl_union_access_info_set_schedule_map.restype = c_void_p
-isl.isl_union_access_info_set_schedule_map.argtypes = [c_void_p, c_void_p]
-isl.isl_union_access_info_copy.restype = c_void_p
-isl.isl_union_access_info_copy.argtypes = [c_void_p]
-isl.isl_union_access_info_free.restype = c_void_p
-isl.isl_union_access_info_free.argtypes = [c_void_p]
-isl.isl_union_access_info_to_str.restype = POINTER(c_char)
-isl.isl_union_access_info_to_str.argtypes = [c_void_p]
+isl.isl_union_pw_aff_list_alloc.restype = c_void_p
+isl.isl_union_pw_aff_list_alloc.argtypes = [Context, c_int]
+isl.isl_union_pw_aff_list_from_union_pw_aff.restype = c_void_p
+isl.isl_union_pw_aff_list_from_union_pw_aff.argtypes = [c_void_p]
+isl.isl_union_pw_aff_list_add.restype = c_void_p
+isl.isl_union_pw_aff_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_list_clear.restype = c_void_p
+isl.isl_union_pw_aff_list_clear.argtypes = [c_void_p]
+isl.isl_union_pw_aff_list_concat.restype = c_void_p
+isl.isl_union_pw_aff_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_union_pw_aff_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_pw_aff_list_get_at.restype = c_void_p
+isl.isl_union_pw_aff_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_union_pw_aff_list_size.argtypes = [c_void_p]
+isl.isl_union_pw_aff_list_copy.restype = c_void_p
+isl.isl_union_pw_aff_list_copy.argtypes = [c_void_p]
+isl.isl_union_pw_aff_list_free.restype = c_void_p
+isl.isl_union_pw_aff_list_free.argtypes = [c_void_p]
+isl.isl_union_pw_aff_list_to_str.restype = POINTER(c_char)
+isl.isl_union_pw_aff_list_to_str.argtypes = [c_void_p]
 
-class union_flow(object):
+class union_set_list(object):
     def __init__(self, *args, **keywords):
         if "ptr" in keywords:
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and args[0].__class__ is union_set:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_union_set_list_from_union_set(isl.isl_union_set_copy(args[0].ptr))
+            return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
-            isl.isl_union_flow_free(self.ptr)
+            isl.isl_union_set_list_free(self.ptr)
     def __str__(arg0):
         try:
-            if not arg0.__class__ is union_flow:
-                arg0 = union_flow(arg0)
+            if not arg0.__class__ is union_set_list:
+                arg0 = union_set_list(arg0)
         except:
             raise
-        ptr = isl.isl_union_flow_to_str(arg0.ptr)
+        ptr = isl.isl_union_set_list_to_str(arg0.ptr)
         res = cast(ptr, c_char_p).value.decode('ascii')
         libc.free(ptr)
         return res
     def __repr__(self):
         s = str(self)
         if '"' in s:
-            return 'isl.union_flow("""%s""")' % s
+            return 'isl.union_set_list("""%s""")' % s
         else:
-            return 'isl.union_flow("%s")' % s
-    def get_full_may_dependence(arg0):
+            return 'isl.union_set_list("%s")' % s
+    def add(arg0, arg1):
         try:
-            if not arg0.__class__ is union_flow:
-                arg0 = union_flow(arg0)
+            if not arg0.__class__ is union_set_list:
+                arg0 = union_set_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set:
+                arg1 = union_set(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_flow_get_full_may_dependence(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_full_must_dependence(arg0):
+        res = isl.isl_union_set_list_add(isl.isl_union_set_list_copy(arg0.ptr), isl.isl_union_set_copy(arg1.ptr))
+        obj = union_set_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
         try:
-            if not arg0.__class__ is union_flow:
-                arg0 = union_flow(arg0)
+            if not arg0.__class__ is union_set_list:
+                arg0 = union_set_list(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_flow_get_full_must_dependence(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_may_dependence(arg0):
+        res = isl.isl_union_set_list_clear(isl.isl_union_set_list_copy(arg0.ptr))
+        obj = union_set_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
         try:
-            if not arg0.__class__ is union_flow:
-                arg0 = union_flow(arg0)
+            if not arg0.__class__ is union_set_list:
+                arg0 = union_set_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is union_set_list:
+                arg1 = union_set_list(arg1)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_flow_get_may_dependence(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_may_no_source(arg0):
+        res = isl.isl_union_set_list_concat(isl.isl_union_set_list_copy(arg0.ptr), isl.isl_union_set_list_copy(arg1.ptr))
+        obj = union_set_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
         try:
-            if not arg0.__class__ is union_flow:
-                arg0 = union_flow(arg0)
+            if not arg0.__class__ is union_set_list:
+                arg0 = union_set_list(arg0)
         except:
             raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = union_set(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
         ctx = arg0.ctx
-        res = isl.isl_union_flow_get_may_no_source(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_must_dependence(arg0):
+        res = isl.isl_union_set_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def at(arg0, arg1):
         try:
-            if not arg0.__class__ is union_flow:
-                arg0 = union_flow(arg0)
+            if not arg0.__class__ is union_set_list:
+                arg0 = union_set_list(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_flow_get_must_dependence(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
-    def get_must_no_source(arg0):
+        res = isl.isl_union_set_list_get_at(arg0.ptr, arg1)
+        obj = union_set(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
         try:
-            if not arg0.__class__ is union_flow:
-                arg0 = union_flow(arg0)
+            if not arg0.__class__ is union_set_list:
+                arg0 = union_set_list(arg0)
         except:
             raise
         ctx = arg0.ctx
-        res = isl.isl_union_flow_get_must_no_source(arg0.ptr)
-        return union_map(ctx=ctx, ptr=res)
+        res = isl.isl_union_set_list_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
 
-isl.isl_union_flow_get_full_may_dependence.restype = c_void_p
-isl.isl_union_flow_get_full_may_dependence.argtypes = [c_void_p]
-isl.isl_union_flow_get_full_must_dependence.restype = c_void_p
-isl.isl_union_flow_get_full_must_dependence.argtypes = [c_void_p]
-isl.isl_union_flow_get_may_dependence.restype = c_void_p
-isl.isl_union_flow_get_may_dependence.argtypes = [c_void_p]
-isl.isl_union_flow_get_may_no_source.restype = c_void_p
-isl.isl_union_flow_get_may_no_source.argtypes = [c_void_p]
-isl.isl_union_flow_get_must_dependence.restype = c_void_p
-isl.isl_union_flow_get_must_dependence.argtypes = [c_void_p]
-isl.isl_union_flow_get_must_no_source.restype = c_void_p
-isl.isl_union_flow_get_must_no_source.argtypes = [c_void_p]
-isl.isl_union_flow_copy.restype = c_void_p
-isl.isl_union_flow_copy.argtypes = [c_void_p]
-isl.isl_union_flow_free.restype = c_void_p
-isl.isl_union_flow_free.argtypes = [c_void_p]
-isl.isl_union_flow_to_str.restype = POINTER(c_char)
-isl.isl_union_flow_to_str.argtypes = [c_void_p]
+isl.isl_union_set_list_alloc.restype = c_void_p
+isl.isl_union_set_list_alloc.argtypes = [Context, c_int]
+isl.isl_union_set_list_from_union_set.restype = c_void_p
+isl.isl_union_set_list_from_union_set.argtypes = [c_void_p]
+isl.isl_union_set_list_add.restype = c_void_p
+isl.isl_union_set_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_list_clear.restype = c_void_p
+isl.isl_union_set_list_clear.argtypes = [c_void_p]
+isl.isl_union_set_list_concat.restype = c_void_p
+isl.isl_union_set_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_union_set_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_union_set_list_get_at.restype = c_void_p
+isl.isl_union_set_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_union_set_list_size.argtypes = [c_void_p]
+isl.isl_union_set_list_copy.restype = c_void_p
+isl.isl_union_set_list_copy.argtypes = [c_void_p]
+isl.isl_union_set_list_free.restype = c_void_p
+isl.isl_union_set_list_free.argtypes = [c_void_p]
+isl.isl_union_set_list_to_str.restype = POINTER(c_char)
+isl.isl_union_set_list_to_str.argtypes = [c_void_p]
 
 class val(object):
     def __init__(self, *args, **keywords):
@@ -5058,14 +13255,14 @@ def __init__(self, *args, **keywords):
             self.ctx = keywords["ctx"]
             self.ptr = keywords["ptr"]
             return
-        if len(args) == 1 and type(args[0]) == str:
-            self.ctx = Context.getDefaultInstance()
-            self.ptr = isl.isl_val_read_from_str(self.ctx, args[0].encode('ascii'))
-            return
         if len(args) == 1 and type(args[0]) == int:
             self.ctx = Context.getDefaultInstance()
             self.ptr = isl.isl_val_int_from_si(self.ctx, args[0])
             return
+        if len(args) == 1 and type(args[0]) == str:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_val_read_from_str(self.ctx, args[0].encode('ascii'))
+            return
         raise Error
     def __del__(self):
         if hasattr(self, 'ptr'):
@@ -5094,7 +13291,8 @@ def abs(arg0):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_abs(isl.isl_val_copy(arg0.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def abs_eq(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5124,7 +13322,8 @@ def add(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_add(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def ceil(arg0):
         try:
             if not arg0.__class__ is val:
@@ -5133,7 +13332,8 @@ def ceil(arg0):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_ceil(isl.isl_val_copy(arg0.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def cmp_si(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5156,7 +13356,8 @@ def div(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_div(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def eq(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5181,7 +13382,8 @@ def floor(arg0):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_floor(isl.isl_val_copy(arg0.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def gcd(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5195,7 +13397,8 @@ def gcd(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_gcd(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def ge(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5212,6 +13415,28 @@ def ge(arg0, arg1):
         if res < 0:
             raise
         return bool(res)
+    def den_si(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_get_den_si(arg0.ptr)
+        return res
+    def get_den_si(arg0):
+        return arg0.den_si()
+    def num_si(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_get_num_si(arg0.ptr)
+        return res
+    def get_num_si(arg0):
+        return arg0.num_si()
     def gt(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5232,7 +13457,8 @@ def gt(arg0, arg1):
     def infty():
         ctx = Context.getDefaultInstance()
         res = isl.isl_val_infty(ctx)
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def inv(arg0):
         try:
             if not arg0.__class__ is val:
@@ -5241,7 +13467,8 @@ def inv(arg0):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_inv(isl.isl_val_copy(arg0.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def is_divisible_by(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5435,7 +13662,8 @@ def max(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_max(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def min(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5449,7 +13677,8 @@ def min(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_min(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def mod(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5463,7 +13692,8 @@ def mod(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_mod(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def mul(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5477,12 +13707,14 @@ def mul(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_mul(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     @staticmethod
     def nan():
         ctx = Context.getDefaultInstance()
         res = isl.isl_val_nan(ctx)
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def ne(arg0, arg1):
         try:
             if not arg0.__class__ is val:
@@ -5507,22 +13739,26 @@ def neg(arg0):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_neg(isl.isl_val_copy(arg0.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     @staticmethod
     def neginfty():
         ctx = Context.getDefaultInstance()
         res = isl.isl_val_neginfty(ctx)
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     @staticmethod
     def negone():
         ctx = Context.getDefaultInstance()
         res = isl.isl_val_negone(ctx)
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     @staticmethod
     def one():
         ctx = Context.getDefaultInstance()
         res = isl.isl_val_one(ctx)
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def pow2(arg0):
         try:
             if not arg0.__class__ is val:
@@ -5531,7 +13767,8 @@ def pow2(arg0):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_pow2(isl.isl_val_copy(arg0.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def sgn(arg0):
         try:
             if not arg0.__class__ is val:
@@ -5554,7 +13791,8 @@ def sub(arg0, arg1):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_sub(isl.isl_val_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     def trunc(arg0):
         try:
             if not arg0.__class__ is val:
@@ -5563,20 +13801,21 @@ def trunc(arg0):
             raise
         ctx = arg0.ctx
         res = isl.isl_val_trunc(isl.isl_val_copy(arg0.ptr))
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
     @staticmethod
     def zero():
         ctx = Context.getDefaultInstance()
         res = isl.isl_val_zero(ctx)
-        return val(ctx=ctx, ptr=res)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
 
-isl.isl_val_read_from_str.restype = c_void_p
-isl.isl_val_read_from_str.argtypes = [Context, c_char_p]
 isl.isl_val_int_from_si.restype = c_void_p
 isl.isl_val_int_from_si.argtypes = [Context, c_long]
+isl.isl_val_read_from_str.restype = c_void_p
+isl.isl_val_read_from_str.argtypes = [Context, c_char_p]
 isl.isl_val_abs.restype = c_void_p
 isl.isl_val_abs.argtypes = [c_void_p]
-isl.isl_val_abs_eq.restype = c_bool
 isl.isl_val_abs_eq.argtypes = [c_void_p, c_void_p]
 isl.isl_val_add.restype = c_void_p
 isl.isl_val_add.argtypes = [c_void_p, c_void_p]
@@ -5585,49 +13824,33 @@ def zero():
 isl.isl_val_cmp_si.argtypes = [c_void_p, c_long]
 isl.isl_val_div.restype = c_void_p
 isl.isl_val_div.argtypes = [c_void_p, c_void_p]
-isl.isl_val_eq.restype = c_bool
 isl.isl_val_eq.argtypes = [c_void_p, c_void_p]
 isl.isl_val_floor.restype = c_void_p
 isl.isl_val_floor.argtypes = [c_void_p]
 isl.isl_val_gcd.restype = c_void_p
 isl.isl_val_gcd.argtypes = [c_void_p, c_void_p]
-isl.isl_val_ge.restype = c_bool
 isl.isl_val_ge.argtypes = [c_void_p, c_void_p]
-isl.isl_val_gt.restype = c_bool
+isl.isl_val_get_den_si.argtypes = [c_void_p]
+isl.isl_val_get_num_si.argtypes = [c_void_p]
 isl.isl_val_gt.argtypes = [c_void_p, c_void_p]
 isl.isl_val_infty.restype = c_void_p
 isl.isl_val_infty.argtypes = [Context]
 isl.isl_val_inv.restype = c_void_p
 isl.isl_val_inv.argtypes = [c_void_p]
-isl.isl_val_is_divisible_by.restype = c_bool
 isl.isl_val_is_divisible_by.argtypes = [c_void_p, c_void_p]
-isl.isl_val_is_infty.restype = c_bool
 isl.isl_val_is_infty.argtypes = [c_void_p]
-isl.isl_val_is_int.restype = c_bool
 isl.isl_val_is_int.argtypes = [c_void_p]
-isl.isl_val_is_nan.restype = c_bool
 isl.isl_val_is_nan.argtypes = [c_void_p]
-isl.isl_val_is_neg.restype = c_bool
 isl.isl_val_is_neg.argtypes = [c_void_p]
-isl.isl_val_is_neginfty.restype = c_bool
 isl.isl_val_is_neginfty.argtypes = [c_void_p]
-isl.isl_val_is_negone.restype = c_bool
 isl.isl_val_is_negone.argtypes = [c_void_p]
-isl.isl_val_is_nonneg.restype = c_bool
 isl.isl_val_is_nonneg.argtypes = [c_void_p]
-isl.isl_val_is_nonpos.restype = c_bool
 isl.isl_val_is_nonpos.argtypes = [c_void_p]
-isl.isl_val_is_one.restype = c_bool
 isl.isl_val_is_one.argtypes = [c_void_p]
-isl.isl_val_is_pos.restype = c_bool
 isl.isl_val_is_pos.argtypes = [c_void_p]
-isl.isl_val_is_rat.restype = c_bool
 isl.isl_val_is_rat.argtypes = [c_void_p]
-isl.isl_val_is_zero.restype = c_bool
 isl.isl_val_is_zero.argtypes = [c_void_p]
-isl.isl_val_le.restype = c_bool
 isl.isl_val_le.argtypes = [c_void_p, c_void_p]
-isl.isl_val_lt.restype = c_bool
 isl.isl_val_lt.argtypes = [c_void_p, c_void_p]
 isl.isl_val_max.restype = c_void_p
 isl.isl_val_max.argtypes = [c_void_p, c_void_p]
@@ -5639,7 +13862,6 @@ def zero():
 isl.isl_val_mul.argtypes = [c_void_p, c_void_p]
 isl.isl_val_nan.restype = c_void_p
 isl.isl_val_nan.argtypes = [Context]
-isl.isl_val_ne.restype = c_bool
 isl.isl_val_ne.argtypes = [c_void_p, c_void_p]
 isl.isl_val_neg.restype = c_void_p
 isl.isl_val_neg.argtypes = [c_void_p]
@@ -5664,3 +13886,152 @@ def zero():
 isl.isl_val_free.argtypes = [c_void_p]
 isl.isl_val_to_str.restype = POINTER(c_char)
 isl.isl_val_to_str.argtypes = [c_void_p]
+
+class val_list(object):
+    def __init__(self, *args, **keywords):
+        if "ptr" in keywords:
+            self.ctx = keywords["ctx"]
+            self.ptr = keywords["ptr"]
+            return
+        if len(args) == 1 and type(args[0]) == int:
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_val_list_alloc(self.ctx, args[0])
+            return
+        if len(args) == 1 and (args[0].__class__ is val or type(args[0]) == int):
+            args = list(args)
+            try:
+                if not args[0].__class__ is val:
+                    args[0] = val(args[0])
+            except:
+                raise
+            self.ctx = Context.getDefaultInstance()
+            self.ptr = isl.isl_val_list_from_val(isl.isl_val_copy(args[0].ptr))
+            return
+        raise Error
+    def __del__(self):
+        if hasattr(self, 'ptr'):
+            isl.isl_val_list_free(self.ptr)
+    def __str__(arg0):
+        try:
+            if not arg0.__class__ is val_list:
+                arg0 = val_list(arg0)
+        except:
+            raise
+        ptr = isl.isl_val_list_to_str(arg0.ptr)
+        res = cast(ptr, c_char_p).value.decode('ascii')
+        libc.free(ptr)
+        return res
+    def __repr__(self):
+        s = str(self)
+        if '"' in s:
+            return 'isl.val_list("""%s""")' % s
+        else:
+            return 'isl.val_list("%s")' % s
+    def add(arg0, arg1):
+        try:
+            if not arg0.__class__ is val_list:
+                arg0 = val_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val:
+                arg1 = val(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_list_add(isl.isl_val_list_copy(arg0.ptr), isl.isl_val_copy(arg1.ptr))
+        obj = val_list(ctx=ctx, ptr=res)
+        return obj
+    def clear(arg0):
+        try:
+            if not arg0.__class__ is val_list:
+                arg0 = val_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_list_clear(isl.isl_val_list_copy(arg0.ptr))
+        obj = val_list(ctx=ctx, ptr=res)
+        return obj
+    def concat(arg0, arg1):
+        try:
+            if not arg0.__class__ is val_list:
+                arg0 = val_list(arg0)
+        except:
+            raise
+        try:
+            if not arg1.__class__ is val_list:
+                arg1 = val_list(arg1)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_list_concat(isl.isl_val_list_copy(arg0.ptr), isl.isl_val_list_copy(arg1.ptr))
+        obj = val_list(ctx=ctx, ptr=res)
+        return obj
+    def foreach(arg0, arg1):
+        try:
+            if not arg0.__class__ is val_list:
+                arg0 = val_list(arg0)
+        except:
+            raise
+        exc_info = [None]
+        fn = CFUNCTYPE(c_int, c_void_p, c_void_p)
+        def cb_func(cb_arg0, cb_arg1):
+            cb_arg0 = val(ctx=arg0.ctx, ptr=(cb_arg0))
+            try:
+                arg1(cb_arg0)
+            except:
+                import sys
+                exc_info[0] = sys.exc_info()
+                return -1
+            return 0
+        cb = fn(cb_func)
+        ctx = arg0.ctx
+        res = isl.isl_val_list_foreach(arg0.ptr, cb, None)
+        if exc_info[0] != None:
+            raise (exc_info[0][0], exc_info[0][1], exc_info[0][2])
+        if res < 0:
+            raise
+    def at(arg0, arg1):
+        try:
+            if not arg0.__class__ is val_list:
+                arg0 = val_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_list_get_at(arg0.ptr, arg1)
+        obj = val(ctx=ctx, ptr=res)
+        return obj
+    def get_at(arg0, arg1):
+        return arg0.at(arg1)
+    def size(arg0):
+        try:
+            if not arg0.__class__ is val_list:
+                arg0 = val_list(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_list_size(arg0.ptr)
+        if res < 0:
+            raise
+        return int(res)
+
+isl.isl_val_list_alloc.restype = c_void_p
+isl.isl_val_list_alloc.argtypes = [Context, c_int]
+isl.isl_val_list_from_val.restype = c_void_p
+isl.isl_val_list_from_val.argtypes = [c_void_p]
+isl.isl_val_list_add.restype = c_void_p
+isl.isl_val_list_add.argtypes = [c_void_p, c_void_p]
+isl.isl_val_list_clear.restype = c_void_p
+isl.isl_val_list_clear.argtypes = [c_void_p]
+isl.isl_val_list_concat.restype = c_void_p
+isl.isl_val_list_concat.argtypes = [c_void_p, c_void_p]
+isl.isl_val_list_foreach.argtypes = [c_void_p, c_void_p, c_void_p]
+isl.isl_val_list_get_at.restype = c_void_p
+isl.isl_val_list_get_at.argtypes = [c_void_p, c_int]
+isl.isl_val_list_size.argtypes = [c_void_p]
+isl.isl_val_list_copy.restype = c_void_p
+isl.isl_val_list_copy.argtypes = [c_void_p]
+isl.isl_val_list_free.restype = c_void_p
+isl.isl_val_list_free.argtypes = [c_void_p]
+isl.isl_val_list_to_str.restype = POINTER(c_char)
+isl.isl_val_list_to_str.argtypes = [c_void_p]

diff  --git a/polly/lib/External/isl/interface/python.cc b/polly/lib/External/isl/interface/python.cc
index 7e6fd182d28b..4212a327f017 100644
--- a/polly/lib/External/isl/interface/python.cc
+++ b/polly/lib/External/isl/interface/python.cc
@@ -33,7 +33,10 @@
 
 #include "isl_config.h"
 
+#include <stdarg.h>
 #include <stdio.h>
+
+#include <algorithm>
 #include <iostream>
 #include <map>
 #include <vector>
@@ -41,6 +44,13 @@
 #include "python.h"
 #include "generator.h"
 
+/* Argument format for Python methods with a fixed number of arguments.
+ */
+static const char *fixed_arg_fmt = "arg%d";
+/* Argument format for Python methods with a variable number of arguments.
+ */
+static const char *var_arg_fmt = "args[%d]";
+
 /* Drop the "isl_" initial part of the type name "name".
  */
 static string type2python(string name)
@@ -48,14 +58,25 @@ static string type2python(string name)
 	return name.substr(4);
 }
 
-/* Print the header of the method "name" with "n_arg" arguments.
+/* Print the arguments of a method with "n_arg" arguments, starting at "first".
+ */
+void python_generator::print_method_arguments(int first, int n_arg)
+{
+	for (int i = first; i < n_arg; ++i) {
+		if (i > first)
+			printf(", ");
+		printf("arg%d", i);
+	}
+}
+
+/* Print the start of a definition for method "name"
+ * (without specifying the arguments).
  * If "is_static" is set, then mark the python method as static.
  *
  * If the method is called "from", then rename it to "convert_from"
  * because "from" is a python keyword.
  */
-void python_generator::print_method_header(bool is_static, const string &name,
-	int n_arg)
+static void print_method_def(bool is_static, const string &name)
 {
 	const char *s;
 
@@ -66,16 +87,35 @@ void python_generator::print_method_header(bool is_static, const string &name,
 	if (name == "from")
 		s = "convert_from";
 
-	printf("    def %s(", s);
-	for (int i = 0; i < n_arg; ++i) {
-		if (i)
-			printf(", ");
-		printf("arg%d", i);
-	}
+	printf("    def %s", s);
+}
+
+/* Print the header of the method "name" with "n_arg" arguments.
+ * If "is_static" is set, then mark the python method as static.
+ */
+void python_generator::print_method_header(bool is_static, const string &name,
+	int n_arg)
+{
+	print_method_def(is_static, name);
+	printf("(");
+	print_method_arguments(0, n_arg);
 	printf("):\n");
 }
 
-/* Print a check that the argument in position "pos" is of type "type".
+/* Print formatted output with the given indentation.
+ */
+static void print_indent(int indent, const char *format, ...)
+{
+	va_list args;
+
+	printf("%*s", indent, " ");
+	va_start(args, format);
+	vprintf(format, args);
+	va_end(args);
+}
+
+/* Print a check that the argument in position "pos" is of type "type"
+ * with the given indentation.
  * If this fails and if "upcast" is set, then convert the first
  * argument to "super" and call the method "name" on it, passing
  * the remaining of the "n" arguments.
@@ -83,27 +123,66 @@ void python_generator::print_method_header(bool is_static, const string &name,
  * an exception.
  * If "upcast" is not set, then the "super", "name" and "n" arguments
  * to this function are ignored.
+ * "fmt" is the format for printing Python method arguments.
  */
-void python_generator::print_type_check(const string &type, int pos,
-	bool upcast, const string &super, const string &name, int n)
+void python_generator::print_type_check(int indent, const string &type,
+	const char *fmt, int pos, bool upcast, const string &super,
+	const string &name, int n)
 {
-	printf("        try:\n");
-	printf("            if not arg%d.__class__ is %s:\n",
-		pos, type.c_str());
-	printf("                arg%d = %s(arg%d)\n",
-		pos, type.c_str(), pos);
-	printf("        except:\n");
+	print_indent(indent, "try:\n");
+	print_indent(indent, "    if not ");
+	printf(fmt, pos);
+	printf(".__class__ is %s:\n", type.c_str());
+	print_indent(indent, "        ");
+	printf(fmt, pos);
+	printf(" = %s(", type.c_str());
+	printf(fmt, pos);
+	printf(")\n");
+	print_indent(indent, "except:\n");
 	if (upcast) {
-		printf("            return %s(arg0).%s(",
-			type2python(super).c_str(), name.c_str());
+		print_indent(indent, "    return %s(",
+			type2python(super).c_str());
+		printf(fmt, 0);
+		printf(").%s(", name.c_str());
 		for (int i = 1; i < n; ++i) {
 			if (i != 1)
 				printf(", ");
-			printf("arg%d", i);
+			printf(fmt, i);
 		}
 		printf(")\n");
 	} else
-		printf("            raise\n");
+		print_indent(indent, "    raise\n");
+}
+
+/* For each of the "n" initial arguments of the function "method"
+ * that refer to an isl structure,
+ * including the object on which the method is called,
+ * check if the corresponding actual argument is of the right type.
+ * If not, try and convert it to the right type.
+ * If that doesn't work and if "super" contains at least one element,
+ * try and convert self to the type of the first superclass in "super" and
+ * call the corresponding method.
+ * If "first_is_ctx" is set, then the first argument is skipped.
+ */
+void python_generator::print_type_checks(const string &cname,
+	FunctionDecl *method, bool first_is_ctx, int n,
+	const vector<string> &super)
+{
+	for (int i = first_is_ctx; i < n; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		string type;
+
+		if (!is_isl_type(param->getOriginalType()))
+			continue;
+		type = type2python(extract_type(param->getOriginalType()));
+		if (!first_is_ctx && i > 0 && super.size() > 0)
+			print_type_check(8, type, fixed_arg_fmt,
+					i - first_is_ctx, true,
+					super[0], cname, n);
+		else
+			print_type_check(8, type, fixed_arg_fmt,
+					i - first_is_ctx, false, "", cname, -1);
+	}
 }
 
 /* Print a call to the *_copy function corresponding to "type".
@@ -122,16 +201,29 @@ void python_generator::print_copy(QualType type)
  * The wrapper converts the arguments of the callback to python types,
  * taking a copy if the C callback does not take its arguments.
  * If any exception is thrown, the wrapper keeps track of it in exc_info[0]
- * and returns -1.  Otherwise the wrapper returns 0.
+ * and returns a value indicating an error.  Otherwise the wrapper
+ * returns a value indicating success.
+ * In case the C callback is expected to return an isl_stat,
+ * the error value is -1 and the success value is 0.
+ * In case the C callback is expected to return an isl_bool,
+ * the error value is -1 and the success value is 1 or 0 depending
+ * on the result of the Python callback.
+ * Otherwise, None is returned to indicate an error and
+ * a copy of the object in case of success.
  */
 void python_generator::print_callback(ParmVarDecl *param, int arg)
 {
 	QualType type = param->getOriginalType();
 	const FunctionProtoType *fn = extract_prototype(type);
+	QualType return_type = fn->getReturnType();
 	unsigned n_arg = fn->getNumArgs();
 
 	printf("        exc_info = [None]\n");
-	printf("        fn = CFUNCTYPE(c_int");
+	printf("        fn = CFUNCTYPE(");
+	if (is_isl_stat(return_type) || is_isl_bool(return_type))
+		printf("c_int");
+	else
+		printf("c_void_p");
 	for (unsigned i = 0; i < n_arg - 1; ++i) {
 		if (!is_isl_type(fn->getArgType(i)))
 			die("Argument has non-isl type");
@@ -155,7 +247,10 @@ void python_generator::print_callback(ParmVarDecl *param, int arg)
 		printf("(cb_arg%d))\n", i);
 	}
 	printf("            try:\n");
-	printf("                arg%d(", arg);
+	if (is_isl_stat(return_type))
+		printf("                arg%d(", arg);
+	else
+		printf("                res = arg%d(", arg);
 	for (unsigned i = 0; i < n_arg - 1; ++i) {
 		if (i)
 			printf(", ");
@@ -165,41 +260,120 @@ void python_generator::print_callback(ParmVarDecl *param, int arg)
 	printf("            except:\n");
 	printf("                import sys\n");
 	printf("                exc_info[0] = sys.exc_info()\n");
-	printf("                return -1\n");
-	printf("            return 0\n");
+	if (is_isl_stat(return_type) || is_isl_bool(return_type))
+		printf("                return -1\n");
+	else
+		printf("                return None\n");
+	if (is_isl_stat(return_type)) {
+		printf("            return 0\n");
+	} else if (is_isl_bool(return_type)) {
+		printf("            return 1 if res else 0\n");
+	} else {
+		printf("            return ");
+		print_copy(return_type);
+		printf("(res.ptr)\n");
+	}
 	printf("        cb = fn(cb_func)\n");
 }
 
 /* Print the argument at position "arg" in call to "fd".
+ * "fmt" is the format for printing Python method arguments.
  * "skip" is the number of initial arguments of "fd" that are
  * skipped in the Python method.
  *
- * If the argument is a callback, then print a reference to
+ * If the (first) argument is an isl_ctx, then print "ctx",
+ * assuming that the caller has made the context available
+ * in a "ctx" variable.
+ * Otherwise, if the argument is a callback, then print a reference to
  * the callback wrapper "cb".
  * Otherwise, if the argument is marked as consuming a reference,
  * then pass a copy of the pointer stored in the corresponding
  * argument passed to the Python method.
+ * Otherwise, if the argument is a string, then the python string is first
+ * encoded as a byte sequence, using 'ascii' as encoding.  This assumes
+ * that all strings passed to isl can be converted to 'ascii'.
  * Otherwise, if the argument is a pointer, then pass this pointer itself.
  * Otherwise, pass the argument directly.
  */
-void python_generator::print_arg_in_call(FunctionDecl *fd, int arg, int skip)
+void python_generator::print_arg_in_call(FunctionDecl *fd, const char *fmt,
+	int arg, int skip)
 {
 	ParmVarDecl *param = fd->getParamDecl(arg);
 	QualType type = param->getOriginalType();
-	if (is_callback(type)) {
+	if (is_isl_ctx(type)) {
+		printf("ctx");
+	} else if (is_callback(type)) {
 		printf("cb");
 	} else if (takes(param)) {
 		print_copy(type);
-		printf("(arg%d.ptr)", arg - skip);
+		printf("(");
+		printf(fmt, arg - skip);
+		printf(".ptr)");
+	} else if (is_string(type)) {
+		printf(fmt, arg - skip);
+		printf(".encode('ascii')");
 	} else if (type->isPointerType()) {
-		printf("arg%d.ptr", arg - skip);
+		printf(fmt, arg - skip);
+		printf(".ptr");
 	} else {
-		printf("arg%d", arg - skip);
+		printf(fmt, arg - skip);
+	}
+}
+
+/* Generate code that raises the exception captured in "exc_info", if any,
+ * with the given indentation.
+ */
+static void print_rethrow(int indent, const char *exc_info)
+{
+	print_indent(indent, "if %s != None:\n", exc_info);
+	print_indent(indent, "    raise (%s[0], %s[1], %s[2])\n",
+		exc_info, exc_info, exc_info);
+}
+
+/* Print code with the given indentation that checks
+ * whether any of the persistent callbacks of "clazz"
+ * is set and if it failed with an exception.  If so, the 'exc_info'
+ * field contains the exception and is raised again.
+ * The field is cleared because the callback and its data may get reused.
+ * "fmt" is the format for printing Python method arguments.
+ */
+static void print_persistent_callback_failure_check(int indent,
+	const isl_class &clazz, const char *fmt)
+{
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
+	set<FunctionDecl *>::const_iterator in;
+
+	for (in = callbacks.begin(); in != callbacks.end(); ++in) {
+		string callback_name = clazz.persistent_callback_name(*in);
+
+		print_indent(indent, "if hasattr(");
+		printf(fmt, 0);
+		printf(", '%s') and ", callback_name.c_str());
+		printf(fmt, 0);
+		printf(".%s['exc_info'] != None:\n", callback_name.c_str());
+		print_indent(indent, "    exc_info = ");
+		printf(fmt, 0);
+		printf(".%s['exc_info'][0]\n", callback_name.c_str());
+		print_indent(indent, "    ");
+		printf(fmt, 0);
+		printf(".%s['exc_info'][0] = None\n", callback_name.c_str());
+		print_rethrow(indent + 4, "exc_info");
 	}
 }
 
 /* Print the return statement of the python method corresponding
- * to the C function "method".
+ * to the C function "method" with the given indentation.
+ * If the object on which the method was called
+ * may have a persistent callback, then first check if any of those failed.
+ * "fmt" is the format for printing Python method arguments.
+ *
+ * If the method returns a new instance of the same object type and
+ * if the class has any persistent callbacks, then the data
+ * for these callbacks are copied from the original to the new object.
+ * If the method it itself setting a persistent callback,
+ * then keep track of the constructed C callback (such that it doesn't
+ * get destroyed) and the data structure that holds the captured exception
+ * (such that it can be raised again).
  *
  * If the return type is a (const) char *, then convert the result
  * to a Python string, raising an error on NULL and freeing
@@ -207,37 +381,121 @@ void python_generator::print_arg_in_call(FunctionDecl *fd, int arg, int skip)
  * by isl is explicitly decoded as an 'ascii' string.  This is correct
  * as all strings returned by isl are expected to be 'ascii'.
  *
- * If the return type is isl_bool, then convert the result to
- * a Python boolean, raising an error on isl_bool_error.
+ * If the return type is isl_stat, isl_bool or isl_size, then
+ * raise an error on isl_stat_error, isl_bool_error or isl_size_error.
+ * In case of isl_bool, the result is converted to
+ * a Python boolean.
+ * In case of isl_size, the result is converted to a Python int.
  */
-void python_generator::print_method_return(FunctionDecl *method)
+void python_generator::print_method_return(int indent, const isl_class &clazz,
+	FunctionDecl *method, const char *fmt)
 {
 	QualType return_type = method->getReturnType();
 
+	if (!is_static(clazz, method))
+		print_persistent_callback_failure_check(indent, clazz, fmt);
+
 	if (is_isl_type(return_type)) {
 		string type;
 
 		type = type2python(extract_type(return_type));
-		printf("        return %s(ctx=ctx, ptr=res)\n", type.c_str());
+		print_indent(indent,
+			"obj = %s(ctx=ctx, ptr=res)\n", type.c_str());
+		if (is_mutator(clazz, method) &&
+		    clazz.has_persistent_callbacks())
+			print_indent(indent, "obj.copy_callbacks(arg0)\n");
+		if (clazz.persistent_callbacks.count(method)) {
+			string callback_name;
+
+			callback_name = clazz.persistent_callback_name(method);
+			print_indent(indent, "obj.%s = { 'func': cb, "
+				"'exc_info': exc_info }\n",
+				callback_name.c_str());
+		}
+		print_indent(indent, "return obj\n");
 	} else if (is_string(return_type)) {
-		printf("        if res == 0:\n");
-		printf("            raise\n");
-		printf("        string = "
+		print_indent(indent, "if res == 0:\n");
+		print_indent(indent, "    raise\n");
+		print_indent(indent, "string = "
 		       "cast(res, c_char_p).value.decode('ascii')\n");
 
 		if (gives(method))
-			printf("        libc.free(res)\n");
+			print_indent(indent, "libc.free(res)\n");
 
-		printf("        return string\n");
-	} else if (is_isl_bool(return_type)) {
-		printf("        if res < 0:\n");
-		printf("            raise\n");
-		printf("        return bool(res)\n");
+		print_indent(indent, "return string\n");
+	} else if (is_isl_neg_error(return_type)) {
+		print_indent(indent, "if res < 0:\n");
+		print_indent(indent, "    raise\n");
+		if (is_isl_bool(return_type))
+			print_indent(indent, "return bool(res)\n");
+		else if (is_isl_size(return_type))
+			print_indent(indent, "return int(res)\n");
 	} else {
-		printf("        return res\n");
+		print_indent(indent, "return res\n");
 	}
 }
 
+/* Print a python "get" method corresponding to the C function "fd"
+ * in class "clazz" using a name that includes the "get_" prefix.
+ *
+ * This method simply calls the variant without the "get_" prefix and
+ * returns its result.
+ * Note that static methods are not considered to be "get" methods.
+ */
+void python_generator::print_get_method(const isl_class &clazz,
+	FunctionDecl *fd)
+{
+	string get_name = clazz.base_method_name(fd);
+	string name = clazz.method_name(fd);
+	int num_params = fd->getNumParams();
+
+	print_method_header(false, get_name, num_params);
+	printf("        return arg0.%s(", name.c_str());
+	print_method_arguments(1, num_params);
+	printf(")\n");
+}
+
+/* Print a call to "method", along with the corresponding
+ * return statement, with the given indentation.
+ * "drop_ctx" is set if the first argument is an isl_ctx.
+ * "drop_user" is set if the last argument is a "user" argument
+ * corresponding to a callback argument.
+ *
+ * A "ctx" variable is first initialized as it may be needed
+ * in the first call to print_arg_in_call and in print_method_return.
+ *
+ * If the method has a callback function, then any exception
+ * thrown in the callback also need to be rethrown.
+ */
+void python_generator::print_method_call(int indent, const isl_class &clazz,
+	FunctionDecl *method, const char *fmt, int drop_ctx, int drop_user)
+{
+	string fullname = method->getName();
+	int num_params = method->getNumParams();
+
+	if (drop_ctx) {
+		print_indent(indent, "ctx = Context.getDefaultInstance()\n");
+	} else {
+		print_indent(indent, "ctx = ");
+		printf(fmt, 0);
+		printf(".ctx\n");
+	}
+	print_indent(indent, "res = isl.%s(", fullname.c_str());
+	for (int i = 0; i < num_params - drop_user; ++i) {
+		if (i > 0)
+			printf(", ");
+		print_arg_in_call(method, fmt, i, drop_ctx);
+	}
+	if (drop_user)
+		printf(", None");
+	printf(")\n");
+
+	if (drop_user)
+		print_rethrow(indent, "exc_info[0]");
+
+	print_method_return(indent, clazz, method, fmt);
+}
+
 /* Print a python method corresponding to the C function "method".
  * "super" contains the superclasses of the class to which the method belongs,
  * with the first element corresponding to the annotation that appears
@@ -255,21 +513,16 @@ void python_generator::print_method_return(FunctionDecl *method)
  * 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.
- * If that doesn't work and if "super" contains at least one element, we try
- * to convert self to the type of the first superclass in "super" and
- * call the corresponding method.
- *
  * If the function consumes a reference, then we pass it a copy of
  * the actual argument.
+ *
+ * For methods that are identified as "get" methods, also
+ * print a variant of the method using a name that includes
+ * the "get_" prefix.
  */
 void python_generator::print_method(const isl_class &clazz,
 	FunctionDecl *method, vector<string> super)
 {
-	string fullname = method->getName();
 	string cname = clazz.method_name(method);
 	int num_params = method->getNumParams();
 	int drop_user = 0;
@@ -285,19 +538,8 @@ void python_generator::print_method(const isl_class &clazz,
 	print_method_header(is_static(clazz, method), cname,
 			    num_params - drop_ctx - drop_user);
 
-	for (int i = drop_ctx; i < num_params; ++i) {
-		ParmVarDecl *param = method->getParamDecl(i);
-		string type;
-		if (!is_isl_type(param->getOriginalType()))
-			continue;
-		type = type2python(extract_type(param->getOriginalType()));
-		if (!drop_ctx && i > 0 && super.size() > 0)
-			print_type_check(type, i - drop_ctx, true, super[0],
-					cname, num_params - drop_user);
-		else
-			print_type_check(type, i - drop_ctx, false, "",
-					cname, -1);
-	}
+	print_type_checks(cname, method, drop_ctx,
+			    num_params - drop_user, super);
 	for (int i = 1; i < num_params; ++i) {
 		ParmVarDecl *param = method->getParamDecl(i);
 		QualType type = param->getOriginalType();
@@ -305,34 +547,89 @@ void python_generator::print_method(const isl_class &clazz,
 			continue;
 		print_callback(param, i - drop_ctx);
 	}
-	if (drop_ctx)
-		printf("        ctx = Context.getDefaultInstance()\n");
-	else
-		printf("        ctx = arg0.ctx\n");
-	printf("        res = isl.%s(", fullname.c_str());
-	if (drop_ctx)
-		printf("ctx");
-	else
-		print_arg_in_call(method, 0, 0);
-	for (int i = 1; i < num_params - drop_user; ++i) {
-		printf(", ");
-		print_arg_in_call(method, i, drop_ctx);
+	print_method_call(8, clazz, method, fixed_arg_fmt, drop_ctx, drop_user);
+
+	if (clazz.is_get_method(method))
+		print_get_method(clazz, method);
+}
+
+/* Print a condition that checks whether Python method argument "i"
+ * corresponds to the C function argument type "type".
+ */
+static void print_argument_check(QualType type, int i)
+{
+	if (generator::is_isl_type(type)) {
+		string type_str;
+		type_str = generator::extract_type(type);
+		type_str = type2python(type_str);
+		printf("args[%d].__class__ is %s", i, type_str.c_str());
+	} else if (type->isPointerType()) {
+		printf("type(args[%d]) == str", i);
+	} else {
+		printf("type(args[%d]) == int", i);
 	}
-	if (drop_user)
-		printf(", None");
-	printf(")\n");
+}
+
+/* Print a test that checks whether the arguments passed
+ * to the Python method correspond to the arguments
+ * expected by "fd".
+ * "drop_ctx" is set if the first argument of "fd" is an isl_ctx,
+ * which does not appear as an argument to the Python method.
+ *
+ * If an automatic conversion function is available for any
+ * of the argument types, then also allow the argument
+ * to be of the type as prescribed by the second input argument
+ * of the conversion function.
+ * The corresponding arguments are then converted to the expected types
+ * if needed.  The argument tuple first needs to be converted to a list
+ * in order to be able to modify the entries.
+ */
+void python_generator::print_argument_checks(const isl_class &clazz,
+	FunctionDecl *fd, int drop_ctx)
+{
+	int num_params = fd->getNumParams();
+	int first = generator::is_static(clazz, fd) ? drop_ctx : 1;
+	std::vector<bool> convert(num_params);
 
-	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("        if len(args) == %d", num_params - drop_ctx);
+	for (int i = first; i < num_params; ++i) {
+		ParmVarDecl *param = fd->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		const Type *ptr = type.getTypePtr();
+
+		printf(" and ");
+		if (conversions.count(ptr) == 0) {
+			print_argument_check(type, i - drop_ctx);
+		} else {
+			QualType type2 = conversions.at(ptr)->getOriginalType();
+			convert[i] = true;
+			printf("(");
+			print_argument_check(type, i - drop_ctx);
+			printf(" or ");
+			print_argument_check(type2, i - drop_ctx);
+			printf(")");
+		}
 	}
+	printf(":\n");
 
-	print_method_return(method);
+	if (std::find(convert.begin(), convert.end(), true) == convert.end())
+		return;
+	print_indent(12, "args = list(args)\n");
+	for (int i = first; i < num_params; ++i) {
+		ParmVarDecl *param = fd->getParamDecl(i);
+		string type;
+
+		if (!convert[i])
+			continue;
+		type = type2python(extract_type(param->getOriginalType()));
+		print_type_check(12, type, var_arg_fmt,
+				i - drop_ctx, false, "", "", -1);
+	}
 }
 
 /* Print part of an overloaded python method corresponding to the C function
  * "method".
+ * "drop_ctx" is set if the first argument of "method" is an isl_ctx.
  *
  * In particular, print code to test whether the arguments passed to
  * the python method correspond to the arguments expected by "method"
@@ -341,36 +638,10 @@ void python_generator::print_method(const isl_class &clazz,
 void python_generator::print_method_overload(const isl_class &clazz,
 	FunctionDecl *method)
 {
-	string fullname = method->getName();
-	int num_params = method->getNumParams();
-	int first;
-	string type;
-
-	first = is_static(clazz, method) ? 0 : 1;
+	int drop_ctx = first_arg_is_isl_ctx(method);
 
-	printf("        if ");
-	for (int i = first; i < num_params; ++i) {
-		if (i > first)
-			printf(" and ");
-		ParmVarDecl *param = method->getParamDecl(i);
-		if (is_isl_type(param->getOriginalType())) {
-			string type;
-			type = extract_type(param->getOriginalType());
-			type = type2python(type);
-			printf("arg%d.__class__ is %s", i, type.c_str());
-		} else
-			printf("type(arg%d) == str", i);
-	}
-	printf(":\n");
-	printf("            res = isl.%s(", fullname.c_str());
-	print_arg_in_call(method, 0, 0);
-	for (int i = 1; i < num_params; ++i) {
-		printf(", ");
-		print_arg_in_call(method, i, 0);
-	}
-	printf(")\n");
-	type = type2python(extract_type(method->getReturnType()));
-	printf("            return %s(ctx=arg0.ctx, ptr=res)\n", type.c_str());
+	print_argument_checks(clazz, method, drop_ctx);
+	print_method_call(12, clazz, method, var_arg_fmt, drop_ctx, 0);
 }
 
 /* Print a python method with a name derived from "fullname"
@@ -383,12 +654,11 @@ void python_generator::print_method_overload(const isl_class &clazz,
  * to each function in "methods".
  */
 void python_generator::print_method(const isl_class &clazz,
-	const string &fullname, const set<FunctionDecl *> &methods,
+	const string &fullname, const function_set &methods,
 	vector<string> super)
 {
 	string cname;
-	set<FunctionDecl *>::const_iterator it;
-	int num_params;
+	function_set::const_iterator it;
 	FunctionDecl *any_method;
 
 	any_method = *methods.begin();
@@ -398,12 +668,65 @@ void python_generator::print_method(const isl_class &clazz,
 	}
 
 	cname = clazz.method_name(any_method);
-	num_params = any_method->getNumParams();
 
-	print_method_header(is_static(clazz, any_method), cname, num_params);
+	print_method_def(is_static(clazz, any_method), cname);
+	printf("(*args):\n");
 
 	for (it = methods.begin(); it != methods.end(); ++it)
 		print_method_overload(clazz, *it);
+	printf("        raise Error\n");
+}
+
+/* Print a python method "name" corresponding to "fd" setting
+ * the enum value "value".
+ * "super" contains the superclasses of the class to which the method belongs,
+ * with the first element corresponding to the annotation that appears
+ * closest to the annotated type.
+ *
+ * The last argument of the C function does not appear in the method call,
+ * but is fixed to "value" instead.
+ * Other than that, the method printed here is similar to one
+ * printed by python_generator::print_method, except that
+ * some of the special cases do not occur.
+ */
+void python_generator::print_set_enum(const isl_class &clazz,
+	FunctionDecl *fd, int value, const string &name,
+	const vector<string> &super)
+{
+	string fullname = fd->getName();
+	int num_params = fd->getNumParams();
+
+	print_method_header(is_static(clazz, fd), name, num_params - 1);
+
+	print_type_checks(name, fd, false, num_params - 1, super);
+	printf("        ctx = arg0.ctx\n");
+	printf("        res = isl.%s(", fullname.c_str());
+	for (int i = 0; i < num_params - 1; ++i) {
+		if (i)
+			printf(", ");
+		print_arg_in_call(fd, fixed_arg_fmt, i, 0);
+	}
+	printf(", %d", value);
+	printf(")\n");
+	print_method_return(8, clazz, fd, fixed_arg_fmt);
+}
+
+/* Print python methods corresponding to "fd", which sets an enum.
+ * "super" contains the superclasses of the class to which the method belongs,
+ * with the first element corresponding to the annotation that appears
+ * closest to the annotated type.
+ *
+ * A method is generated for each value in the enum, setting
+ * the enum to that value.
+ */
+void python_generator::print_set_enum(const isl_class &clazz,
+	FunctionDecl *fd, const vector<string> &super)
+{
+	vector<set_enum>::const_iterator it;
+	const vector<set_enum> &set_enums = clazz.set_enums.at(fd);
+
+	for (it = set_enums.begin(); it != set_enums.end(); ++it)
+		print_set_enum(clazz, fd, it->value, it->method_name, super);
 }
 
 /* Print part of the constructor for this isl_class.
@@ -411,13 +734,6 @@ void python_generator::print_method(const isl_class &clazz,
  * 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.
- *
- * If the function takes a string argument, the python string is first
- * encoded as a byte sequence, using 'ascii' as encoding.  This assumes
- * that all strings passed to isl can be converted to 'ascii'.
  */
 void python_generator::print_constructor(const isl_class &clazz,
 	FunctionDecl *cons)
@@ -427,48 +743,48 @@ void python_generator::print_constructor(const isl_class &clazz,
 	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);
-		QualType type = param->getOriginalType();
-		if (is_isl_type(type)) {
-			string s;
-			s = type2python(extract_type(type));
-			printf(" and args[%d].__class__ is %s",
-				i - drop_ctx, s.c_str());
-		} else if (type->isPointerType()) {
-			printf(" and type(args[%d]) == str", i - drop_ctx);
-		} else {
-			printf(" and type(args[%d]) == int", i - drop_ctx);
-		}
-	}
-	printf(":\n");
+	print_argument_checks(clazz, cons, drop_ctx);
 	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);
-		QualType type = param->getOriginalType();
 		if (i)
 			printf(", ");
-		if (is_isl_type(type)) {
-			if (takes(param))
-				print_copy(param->getOriginalType());
-			printf("(args[%d].ptr)", i - drop_ctx);
-		} else if (is_string(type)) {
-			printf("args[%d].encode('ascii')", i - drop_ctx);
-		} else {
-			printf("args[%d]", i - drop_ctx);
-		}
+		print_arg_in_call(cons, var_arg_fmt, i, drop_ctx);
 	}
 	printf(")\n");
 	printf("            return\n");
 }
 
+/* If "clazz" has a type function describing subclasses,
+ * then add constructors that allow each of these subclasses
+ * to be treated as an object to the superclass.
+ */
+void python_generator::print_upcast_constructors(const isl_class &clazz)
+{
+	map<int, string>::const_iterator i;
+
+	if (!clazz.fn_type)
+		return;
+
+	for (i = clazz.type_subclasses.begin();
+	     i != clazz.type_subclasses.end(); ++i) {
+		printf("        if len(args) == 1 and "
+						"isinstance(args[0], %s):\n",
+			 type2python(i->second).c_str());
+		printf("            self.ctx = args[0].ctx\n");
+		printf("            self.ptr = isl.%s_copy(args[0].ptr)\n",
+			clazz.name.c_str());
+		printf("            return\n");
+	}
+}
+
 /* Print the header of the class "name" with superclasses "super".
  * The order of the superclasses is the opposite of the order
  * in which the corresponding annotations appear in the source code.
+ * If "clazz" is a subclass derived from a type function,
+ * then the immediate superclass is recorded in "clazz" itself.
  */
 void python_generator::print_class_header(const isl_class &clazz,
 	const string &name, const vector<string> &super)
@@ -482,6 +798,8 @@ void python_generator::print_class_header(const isl_class &clazz,
 			printf("%s", type2python(super[i]).c_str());
 		}
 		printf(")");
+	} else if (clazz.is_type_subclass()) {
+		printf("(%s)", type2python(clazz.superclass_name).c_str());
 	} else {
 		printf("(object)");
 	}
@@ -491,9 +809,11 @@ void python_generator::print_class_header(const isl_class &clazz,
 /* Tell ctypes about the return type of "fd".
  * In particular, if "fd" returns a pointer to an isl object,
  * then tell ctypes it returns a "c_void_p".
- * Similarly, if "fd" returns an isl_bool,
- * then tell ctypes it returns a "c_bool".
  * If "fd" returns a char *, then simply tell ctypes.
+ *
+ * Nothing needs to be done for functions returning
+ * isl_bool, isl_stat or isl_size since they are represented by an int and
+ * ctypes assumes that a function returns int by default.
  */
 void python_generator::print_restype(FunctionDecl *fd)
 {
@@ -501,8 +821,6 @@ void python_generator::print_restype(FunctionDecl *fd)
 	QualType type = fd->getReturnType();
 	if (is_isl_type(type))
 		printf("isl.%s.restype = c_void_p\n", fullname.c_str());
-	else if (is_isl_bool(type))
-		printf("isl.%s.restype = c_bool\n", fullname.c_str());
 	else if (is_string(type))
 		printf("isl.%s.restype = POINTER(c_char)\n", fullname.c_str());
 }
@@ -547,6 +865,41 @@ void python_generator::print_method_type(FunctionDecl *fd)
 	print_argtypes(fd);
 }
 
+/* If "clazz" has a type function describing subclasses or
+ * if it is one of those type subclasses, then print a __new__ method.
+ *
+ * In the superclass, the __new__ method constructs an object
+ * of the subclass type specified by the type function.
+ * In the subclass, the __new__ method reverts to the original behavior.
+ */
+void python_generator::print_new(const isl_class &clazz,
+	const string &python_name)
+{
+	if (!clazz.fn_type && !clazz.is_type_subclass())
+		return;
+
+	printf("    def __new__(cls, *args, **keywords):\n");
+
+	if (clazz.fn_type) {
+		map<int, string>::const_iterator i;
+
+		printf("        if \"ptr\" in keywords:\n");
+		printf("            type = isl.%s(keywords[\"ptr\"])\n",
+			clazz.fn_type->getNameAsString().c_str());
+
+		for (i = clazz.type_subclasses.begin();
+		     i != clazz.type_subclasses.end(); ++i) {
+			printf("            if type == %d:\n", i->first);
+			printf("                return %s(**keywords)\n",
+				type2python(i->second).c_str());
+		}
+		printf("            raise\n");
+	}
+
+	printf("        return super(%s, cls).__new__(cls)\n",
+		python_name.c_str());
+}
+
 /* Print declarations for methods printing the class representation,
  * provided there is a corresponding *_to_str function.
  *
@@ -569,7 +922,7 @@ void python_generator::print_representation(const isl_class &clazz,
 		return;
 
 	printf("    def __str__(arg0):\n");
-	print_type_check(python_name, 0, false, "", "", -1);
+	print_type_check(8, python_name, fixed_arg_fmt, 0, false, "", "", -1);
 	printf("        ptr = isl.%s(arg0.ptr)\n",
 		string(clazz.fn_to_str->getName()).c_str());
 	printf("        res = cast(ptr, c_char_p).value.decode('ascii')\n");
@@ -585,31 +938,64 @@ void python_generator::print_representation(const isl_class &clazz,
 		python_name.c_str());
 }
 
+/* If "clazz" has any persistent callbacks, then print the definition
+ * of a "copy_callbacks" function that copies the persistent callbacks
+ * from one object to another.
+ */
+void python_generator::print_copy_callbacks(const isl_class &clazz)
+{
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
+	set<FunctionDecl *>::const_iterator in;
+
+	if (!clazz.has_persistent_callbacks())
+		return;
+
+	printf("    def copy_callbacks(self, obj):\n");
+	for (in = callbacks.begin(); in != callbacks.end(); ++in) {
+		string callback_name = clazz.persistent_callback_name(*in);
+
+		printf("        if hasattr(obj, '%s'):\n",
+			callback_name.c_str());
+		printf("            self.%s = obj.%s\n",
+			callback_name.c_str(), callback_name.c_str());
+	}
+}
+
 /* Print code to set method type signatures.
  *
  * To be able to call C functions it is necessary to explicitly set their
  * argument and result types.  Do this for all exported constructors and
- * methods, as well as for the *_to_str method, if it exists.
+ * methods (including those that set a persistent callback and
+ * those that set an enum value),
+ * as well as for the *_to_str and the type function, if they exist.
  * Assuming each exported class has a *_copy and a *_free method,
  * also unconditionally set the type of such methods.
  */
 void python_generator::print_method_types(const isl_class &clazz)
 {
-	set<FunctionDecl *>::const_iterator in;
-	map<string, set<FunctionDecl *> >::const_iterator it;
+	function_set::const_iterator in;
+	map<string, function_set>::const_iterator it;
+	map<FunctionDecl *, vector<set_enum> >::const_iterator ie;
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
 
 	for (in = clazz.constructors.begin(); in != clazz.constructors.end();
 		++in)
 		print_method_type(*in);
 
+	for (in = callbacks.begin(); in != callbacks.end(); ++in)
+		print_method_type(*in);
 	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
 		for (in = it->second.begin(); in != it->second.end(); ++in)
 			print_method_type(*in);
+	for (ie = clazz.set_enums.begin(); ie != clazz.set_enums.end(); ++ie)
+		print_method_type(ie->first);
 
 	print_method_type(clazz.fn_copy);
 	print_method_type(clazz.fn_free);
 	if (clazz.fn_to_str)
 		print_method_type(clazz.fn_to_str);
+	if (clazz.fn_type)
+		print_method_type(clazz.fn_type);
 }
 
 /* Print out the definition of this isl_class.
@@ -618,11 +1004,12 @@ void python_generator::print_method_types(const isl_class &clazz)
  * If it is, we make sure those superclasses are 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.
+ * a Python object from a return value, one for each function that
+ * was marked as a constructor and for each type based subclass.
  *
  * Next, we print out some common methods and the methods corresponding
- * to functions that are not marked as constructors.
+ * to functions that are not marked as constructors, including those
+ * that set a persistent callback and those that set an enum value.
  *
  * Finally, we tell ctypes about the types of the arguments of the
  * constructor functions and the return types of those function returning
@@ -630,15 +1017,19 @@ void python_generator::print_method_types(const isl_class &clazz)
  */
 void python_generator::print(const isl_class &clazz)
 {
-	string p_name = type2python(clazz.name);
-	set<FunctionDecl *>::const_iterator in;
-	map<string, set<FunctionDecl *> >::const_iterator it;
+	string p_name = type2python(clazz.subclass_name);
+	function_set::const_iterator in;
+	map<string, function_set>::const_iterator it;
+	map<FunctionDecl *, vector<set_enum> >::const_iterator ie;
 	vector<string> super = find_superclasses(clazz.type);
+	const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
 
 	for (unsigned i = 0; i < super.size(); ++i)
 		if (done.find(super[i]) == done.end())
 			print(classes[super[i]]);
-	done.insert(clazz.name);
+	if (clazz.is_type_subclass() && done.find(clazz.name) == done.end())
+		print(classes[clazz.name]);
+	done.insert(clazz.subclass_name);
 
 	printf("\n");
 	print_class_header(clazz, p_name, super);
@@ -652,15 +1043,22 @@ void python_generator::print(const isl_class &clazz)
 	for (in = clazz.constructors.begin(); in != clazz.constructors.end();
 		++in)
 		print_constructor(clazz, *in);
+	print_upcast_constructors(clazz);
 	printf("        raise Error\n");
 	printf("    def __del__(self):\n");
 	printf("        if hasattr(self, 'ptr'):\n");
 	printf("            isl.%s_free(self.ptr)\n", clazz.name.c_str());
 
+	print_new(clazz, p_name);
 	print_representation(clazz, p_name);
+	print_copy_callbacks(clazz);
 
+	for (in = callbacks.begin(); in != callbacks.end(); ++in)
+		print_method(clazz, *in, super);
 	for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
 		print_method(clazz, it->first, it->second, super);
+	for (ie = clazz.set_enums.begin(); ie != clazz.set_enums.end(); ++ie)
+		print_set_enum(clazz, ie->first, super);
 
 	printf("\n");
 

diff  --git a/polly/lib/External/isl/interface/python.h b/polly/lib/External/isl/interface/python.h
index 27d8889b32e7..e56c23d9c590 100644
--- a/polly/lib/External/isl/interface/python.h
+++ b/polly/lib/External/isl/interface/python.h
@@ -19,28 +19,48 @@ class python_generator : public generator {
 
 private:
 	void print(const isl_class &clazz);
+	void print_method_arguments(int first, int n_arg);
 	void print_method_header(bool is_static, const string &name, int n_arg);
 	void print_class_header(const isl_class &clazz, const string &name,
 		const vector<string> &super);
-	void print_type_check(const string &type, int pos, bool upcast,
-		const string &super, const string &name, int n);
+	void print_type_check(int indent, const string &type, const char *fmt,
+		int pos, bool upcast, const string &super,
+		const string &name, int n);
+	void print_type_checks(const string &cname, FunctionDecl *method,
+		bool first_is_ctx, int n, const vector<string> &super);
 	void print_copy(QualType type);
 	void print_callback(ParmVarDecl *param, int arg);
-	void print_arg_in_call(FunctionDecl *fd, int arg, int skip);
+	void print_arg_in_call(FunctionDecl *fd, const char *fmt, int arg,
+		int skip);
 	void print_argtypes(FunctionDecl *fd);
-	void print_method_return(FunctionDecl *method);
+	void print_method_return(int indent, const isl_class &clazz,
+		FunctionDecl *method, const char *fmt);
 	void print_restype(FunctionDecl *fd);
 	void print(map<string, isl_class> &classes, set<string> &done);
 	void print_constructor(const isl_class &clazz, FunctionDecl *method);
+	void print_upcast_constructors(const isl_class &clazz);
+	void print_new(const isl_class &clazz,
+		const string &python_name);
 	void print_representation(const isl_class &clazz,
 		const string &python_name);
+	void print_copy_callbacks(const isl_class &clazz);
 	void print_method_type(FunctionDecl *fd);
 	void print_method_types(const isl_class &clazz);
+	void print_get_method(const isl_class &clazz, FunctionDecl *fd);
 	void print_method(const isl_class &clazz, FunctionDecl *method,
 		vector<string> super);
+	void print_method_call(int indent, const isl_class &clazz,
+		FunctionDecl *method, const char *fmt,
+		int drop_ctx, int drop_user);
+	void print_argument_checks(const isl_class &clazz, FunctionDecl *fd,
+		int drop_ctx);
 	void print_method_overload(const isl_class &clazz,
 		FunctionDecl *method);
 	void print_method(const isl_class &clazz, const string &fullname,
-		const set<FunctionDecl *> &methods, vector<string> super);
+		const function_set &methods, vector<string> super);
+	void print_set_enum(const isl_class &clazz, FunctionDecl *fd,
+		int value, const string &name, const vector<string> &super);
+	void print_set_enum(const isl_class &clazz, FunctionDecl *fd,
+		const vector<string> &super);
 
 };

diff  --git a/polly/lib/External/isl/isl_aff.c b/polly/lib/External/isl/isl_aff.c
index c967277e4383..ae02be12b56d 100644
--- a/polly/lib/External/isl/isl_aff.c
+++ b/polly/lib/External/isl/isl_aff.c
@@ -3,6 +3,8 @@
  * Copyright 2011      Sven Verdoolaege
  * Copyright 2012-2014 Ecole Normale Superieure
  * Copyright 2014      INRIA Rocquencourt
+ * Copyright 2016      Sven Verdoolaege
+ * Copyright 2018      Cerebras Systems
  *
  * Use of this software is governed by the MIT license
  *
@@ -12,6 +14,7 @@
  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
  * B.P. 105 - 78153 Le Chesnay, France
+ * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
  */
 
 #include <isl_ctx_private.h>
@@ -22,7 +25,7 @@
 #include <isl_local_space_private.h>
 #include <isl_vec_private.h>
 #include <isl_mat_private.h>
-#include <isl/id.h>
+#include <isl_id_private.h>
 #include <isl/constraint.h>
 #include <isl_seq.h>
 #include <isl/set.h>
@@ -30,28 +33,28 @@
 #include <isl_point_private.h>
 #include <isl_config.h>
 
-#undef BASE
-#define BASE aff
+#undef EL_BASE
+#define EL_BASE aff
 
 #include <isl_list_templ.c>
 
-#undef BASE
-#define BASE pw_aff
+#undef EL_BASE
+#define EL_BASE pw_aff
 
 #include <isl_list_templ.c>
 
-#undef BASE
-#define BASE pw_multi_aff
+#undef EL_BASE
+#define EL_BASE pw_multi_aff
 
 #include <isl_list_templ.c>
 
-#undef BASE
-#define BASE union_pw_aff
+#undef EL_BASE
+#define EL_BASE union_pw_aff
 
 #include <isl_list_templ.c>
 
-#undef BASE
-#define BASE union_pw_multi_aff
+#undef EL_BASE
+#define EL_BASE union_pw_multi_aff
 
 #include <isl_list_templ.c>
 
@@ -82,7 +85,7 @@ __isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
 {
 	isl_ctx *ctx;
 	isl_vec *v;
-	unsigned total;
+	isl_size total;
 
 	if (!ls)
 		return NULL;
@@ -97,6 +100,8 @@ __isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
 			goto error);
 
 	total = isl_local_space_dim(ls, isl_dim_all);
+	if (total < 0)
+		goto error;
 	v = isl_vec_alloc(ctx, 1 + 1 + total);
 	return isl_aff_alloc_vec(ls, v);
 error:
@@ -181,6 +186,14 @@ __isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls,
 	return NULL;
 }
 
+/* Return an affine expression that is equal to "val" on domain space "space".
+ */
+__isl_give isl_aff *isl_aff_val_on_domain_space(__isl_take isl_space *space,
+	__isl_take isl_val *val)
+{
+	return isl_aff_val_on_domain(isl_local_space_from_space(space), val);
+}
+
 /* Return an affine expression that is equal to the specified dimension
  * in "ls".
  */
@@ -199,9 +212,8 @@ __isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls,
 	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);
+	if (isl_local_space_check_range(ls, type, pos, 1) < 0)
+		goto error;
 
 	isl_space_free(space);
 	aff = isl_aff_alloc(ls);
@@ -322,18 +334,47 @@ uint32_t isl_aff_get_hash(__isl_keep isl_aff *aff)
 	return hash;
 }
 
+/* Return the domain local space of "aff".
+ */
+static __isl_keep isl_local_space *isl_aff_peek_domain_local_space(
+	__isl_keep isl_aff *aff)
+{
+	return aff ? aff->ls : NULL;
+}
+
+/* Return the number of variables of the given type in the domain of "aff".
+ */
+isl_size isl_aff_domain_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
+{
+	isl_local_space *ls;
+
+	ls = isl_aff_peek_domain_local_space(aff);
+	return isl_local_space_dim(ls, type);
+}
+
 /* 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)
+isl_size isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
 {
 	if (!aff)
-		return 0;
+		return isl_size_error;
 	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 isl_aff_domain_dim(aff, type);
+}
+
+/* Return the offset of the first coefficient of type "type" in
+ * the domain of "aff".
+ */
+isl_size isl_aff_domain_offset(__isl_keep isl_aff *aff, enum isl_dim_type type)
+{
+	isl_local_space *ls;
+
+	ls = isl_aff_peek_domain_local_space(aff);
+	return isl_local_space_offset(ls, type);
 }
 
 /* Return the position of the dimension of the given type and name
@@ -375,10 +416,12 @@ __isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff)
 	return space;
 }
 
+/* Return a copy of the domain space of "aff".
+ */
 __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;
+	return isl_local_space_copy(isl_aff_peek_domain_local_space(aff));
 }
 
 __isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
@@ -499,14 +542,17 @@ static __isl_give isl_vec *vec_reorder(__isl_take isl_vec *vec,
 {
 	isl_space *space;
 	isl_vec *res;
+	isl_size dim;
 	int i;
 
 	if (!vec || !r)
 		goto error;
 
 	space = isl_reordering_peek_space(r);
-	res = isl_vec_alloc(vec->ctx,
-			    2 + isl_space_dim(space, isl_dim_all) + n_div);
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0)
+		goto error;
+	res = isl_vec_alloc(vec->ctx, 2 + dim + n_div);
 	if (!res)
 		goto error;
 	isl_seq_cpy(res->el, vec->el, 2);
@@ -576,18 +622,48 @@ __isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
 	return NULL;
 }
 
+/* Given an affine function "aff" defined over a parameter domain,
+ * convert it to a function defined over a domain corresponding
+ * to "domain".
+ * Any parameters with identifiers in "domain" are reinterpreted
+ * as the corresponding domain dimensions.
+ */
+__isl_give isl_aff *isl_aff_unbind_params_insert_domain(
+	__isl_take isl_aff *aff, __isl_take isl_multi_id *domain)
+{
+	isl_bool is_params;
+	isl_space *space;
+	isl_reordering *r;
+
+	space = isl_aff_peek_domain_space(aff);
+	is_params = isl_space_is_params(space);
+	if (is_params < 0)
+		domain = isl_multi_id_free(domain);
+	else if (!is_params)
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"expecting function with parameter domain",
+			domain = isl_multi_id_free(domain));
+	r = isl_reordering_unbind_params_insert_domain(space, domain);
+	isl_multi_id_free(domain);
+
+	return isl_aff_realign_domain(aff, r);
+}
+
 /* Is "aff" obviously equal to zero?
  *
  * If the denominator is zero, then "aff" is not equal to zero.
  */
 isl_bool isl_aff_plain_is_zero(__isl_keep isl_aff *aff)
 {
+	int pos;
+
 	if (!aff)
 		return isl_bool_error;
 
 	if (isl_int_is_zero(aff->v->el[0]))
 		return isl_bool_false;
-	return isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1) < 0;
+	pos = isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1);
+	return isl_bool_ok(pos < 0);
 }
 
 /* Does "aff" represent NaN?
@@ -597,7 +673,7 @@ isl_bool isl_aff_is_nan(__isl_keep isl_aff *aff)
 	if (!aff)
 		return isl_bool_error;
 
-	return isl_seq_first_non_zero(aff->v->el, 2) < 0;
+	return isl_bool_ok(isl_seq_first_non_zero(aff->v->el, 2) < 0);
 }
 
 /* Are "aff1" and "aff2" obviously equal?
@@ -689,9 +765,8 @@ __isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
 	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_local_space_check_range(aff->ls, type, pos, 1) < 0)
+		return NULL;
 
 	if (isl_aff_is_nan(aff))
 		return isl_val_nan(ctx);
@@ -719,9 +794,8 @@ int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type,
 	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);
+	if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
+		return 0;
 
 	pos += isl_local_space_offset(aff->ls, type);
 	return isl_int_sgn(aff->v->el[1 + pos]);
@@ -980,9 +1054,8 @@ __isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *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_local_space_check_range(aff->ls, type, pos, 1) < 0)
+		return isl_aff_free(aff);
 
 	if (isl_aff_is_nan(aff))
 		return aff;
@@ -1018,9 +1091,8 @@ __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *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_local_space_check_range(aff->ls, type, pos, 1) < 0)
+		return isl_aff_free(aff);
 
 	if (isl_aff_is_nan(aff))
 		return aff;
@@ -1059,9 +1131,8 @@ __isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *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", goto error);
+	if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
+		return isl_aff_free(aff);
 
 	if (isl_aff_is_nan(aff)) {
 		isl_val_free(v);
@@ -1125,9 +1196,8 @@ __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *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_local_space_check_range(aff->ls, type, pos, 1) < 0)
+		return isl_aff_free(aff);
 
 	if (isl_aff_is_nan(aff))
 		return aff;
@@ -1168,9 +1238,8 @@ __isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *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", goto error);
+	if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
+		goto error;
 
 	if (isl_aff_is_nan(aff)) {
 		isl_val_free(v);
@@ -1267,14 +1336,13 @@ __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
 __isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff)
 {
 	int pos;
-	int off;
-	int n;
+	isl_size off;
+	isl_size 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);
+	n = isl_aff_domain_dim(aff, isl_dim_div);
+	off = isl_aff_domain_offset(aff, isl_dim_div);
+	if (n < 0 || off < 0)
+		return isl_aff_free(aff);
 
 	pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1;
 	if (pos == n)
@@ -1298,17 +1366,18 @@ __isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff)
  */
 static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	int len;
 	isl_int v;
 	isl_vec *vec;
 	isl_local_space *ls;
-	unsigned pos;
-
-	if (!aff)
-		return NULL;
+	isl_size off;
 
-	n = isl_local_space_dim(aff->ls, isl_dim_div);
+	n = isl_aff_domain_dim(aff, isl_dim_div);
+	off = isl_aff_domain_offset(aff, isl_dim_div);
+	if (n < 0 || off < 0)
+		return isl_aff_free(aff);
 	len = aff->v->size;
 	for (i = 0; i < n; ++i) {
 		if (!isl_int_is_one(aff->ls->div->row[i][0]))
@@ -1323,8 +1392,7 @@ static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
 
 		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],
+		isl_seq_substitute(vec->el, off + i, aff->ls->div->row[i],
 					len, len, v);
 
 		isl_int_clear(v);
@@ -1363,14 +1431,14 @@ static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
  */
 static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff)
 {
-	int i, j, n;
-	int off;
-
-	if (!aff)
-		return NULL;
+	int i, j;
+	isl_size n;
+	isl_size off;
 
-	n = isl_local_space_dim(aff->ls, isl_dim_div);
-	off = isl_local_space_offset(aff->ls, isl_dim_div);
+	n = isl_aff_domain_dim(aff, isl_dim_div);
+	off = isl_aff_domain_offset(aff, isl_dim_div);
+	if (n < 0 || off < 0)
+		return isl_aff_free(aff);
 	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]))
@@ -1393,10 +1461,13 @@ static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff)
  */
 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_size off = isl_aff_domain_offset(aff, isl_dim_div);
 	isl_local_space *ls;
 	isl_vec *v;
 
+	if (off < 0)
+		return isl_aff_free(aff);
+
 	ls = isl_local_space_copy(aff->ls);
 	ls = isl_local_space_swap_div(ls, a, b);
 	v = isl_vec_copy(aff->v);
@@ -1424,7 +1495,10 @@ static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b)
  */
 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);
+	isl_size off = isl_aff_domain_offset(aff, isl_dim_div);
+
+	if (off < 0)
+		return isl_aff_free(aff);
 
 	if (isl_int_is_zero(aff->v->el[1 + off + b]))
 		return aff;
@@ -1451,12 +1525,12 @@ static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b)
  */
 static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff)
 {
-	int i, j, n;
-
-	if (!aff)
-		return NULL;
+	isl_size n;
+	int i, j;
 
 	n = isl_aff_dim(aff, isl_dim_div);
+	if (n < 0)
+		return isl_aff_free(aff);
 	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);
@@ -1680,19 +1754,19 @@ __isl_give isl_aff *isl_aff_ceil(__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)
 {
-	int old_n_div;
-	int new_n_div;
-	int offset;
+	isl_size old_n_div;
+	isl_size new_n_div;
+	isl_size offset;
 
 	aff = isl_aff_cow(aff);
-	if (!aff || !div)
-		goto error;
 
-	old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
+	offset = isl_aff_domain_offset(aff, isl_dim_div);
+	old_n_div = isl_aff_domain_dim(aff, isl_dim_div);
 	new_n_div = isl_mat_rows(div);
-	offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
+	if (offset < 0 || old_n_div < 0 || new_n_div < 0)
+		goto error;
 
-	aff->v = isl_vec_expand(aff->v, offset, old_n_div, exp, new_n_div);
+	aff->v = isl_vec_expand(aff->v, 1 + offset, old_n_div, exp, new_n_div);
 	aff->ls = isl_local_space_replace_divs(aff->ls, div);
 	if (!aff->v || !aff->ls)
 		return isl_aff_free(aff);
@@ -1731,6 +1805,7 @@ static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1,
 	isl_int_clear(gcd);
 
 	isl_aff_free(aff2);
+	aff1 = isl_aff_normalize(aff1);
 	return aff1;
 error:
 	isl_aff_free(aff1);
@@ -1749,7 +1824,7 @@ __isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
 	int *exp1 = NULL;
 	int *exp2 = NULL;
 	isl_mat *div;
-	int n_div1, n_div2;
+	isl_size n_div1, n_div2;
 
 	if (!aff1 || !aff2)
 		goto error;
@@ -1770,6 +1845,8 @@ __isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
 
 	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)
+		goto error;
 	if (n_div1 == 0 && n_div2 == 0)
 		return add_expanded(aff1, aff2);
 
@@ -2024,7 +2101,7 @@ 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 o_div;
 	unsigned n_div;
 
 	if (!eq)
@@ -2044,14 +2121,14 @@ static __isl_give isl_aff *isl_aff_substitute_equalities_lifted(
 	if (!aff->ls || !aff->v)
 		goto error;
 
-	total = 1 + isl_space_dim(eq->dim, isl_dim_all);
+	o_div = isl_basic_set_offset(eq, isl_dim_div);
 	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)
+		j = isl_seq_last_non_zero(eq->eq[i], o_div + n_div);
+		if (j < 0 || j == 0 || j >= o_div)
 			continue;
 
-		isl_seq_elim(aff->v->el + 1, eq->eq[i], j, total,
+		isl_seq_elim(aff->v->el + 1, eq->eq[i], j, o_div,
 				&aff->v->el[0]);
 	}
 
@@ -2070,11 +2147,11 @@ static __isl_give isl_aff *isl_aff_substitute_equalities_lifted(
 __isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff,
 	__isl_take isl_basic_set *eq)
 {
-	int n_div;
+	isl_size n_div;
 
-	if (!aff || !eq)
+	n_div = isl_aff_domain_dim(aff, isl_dim_div);
+	if (n_div < 0)
 		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);
@@ -2092,30 +2169,14 @@ __isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff,
 __isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
 	__isl_take isl_set *context)
 {
+	isl_local_space *ls;
 	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));
-	}
+	ls = isl_aff_get_domain_local_space(aff);
+	context = isl_local_space_lift_set(ls, context);
 
 	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,
@@ -2132,7 +2193,7 @@ __isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
  * If "aff" is NaN, then it is not positive.
  */
 static __isl_give isl_basic_set *aff_pos_basic_set(__isl_take isl_aff *aff,
-	int rational)
+	int rational, void *user)
 {
 	isl_constraint *ineq;
 	isl_basic_set *bset;
@@ -2169,7 +2230,7 @@ static __isl_give isl_basic_set *aff_pos_basic_set(__isl_take isl_aff *aff,
  * 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_take isl_aff *aff, int rational, void *user)
 {
 	isl_constraint *ineq;
 	isl_basic_set *bset;
@@ -2196,7 +2257,7 @@ static __isl_give isl_basic_set *aff_nonneg_basic_set(
  */
 __isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff)
 {
-	return aff_nonneg_basic_set(aff, 0);
+	return aff_nonneg_basic_set(aff, 0, NULL);
 }
 
 /* Return a basic set containing those elements in the domain space
@@ -2224,7 +2285,7 @@ __isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff)
  * 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)
+	int rational, void *user)
 {
 	isl_constraint *ineq;
 	isl_basic_set *bset;
@@ -2251,7 +2312,7 @@ static __isl_give isl_basic_set *aff_zero_basic_set(__isl_take isl_aff *aff,
  */
 __isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff)
 {
-	return aff_zero_basic_set(aff, 0);
+	return aff_zero_basic_set(aff, 0, NULL);
 }
 
 /* Return a basic set containing those elements in the shared space
@@ -2378,14 +2439,19 @@ __isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_set *dom,
 	return aff1;
 }
 
-int isl_aff_is_empty(__isl_keep isl_aff *aff)
+isl_bool isl_aff_is_empty(__isl_keep isl_aff *aff)
 {
 	if (!aff)
-		return -1;
+		return isl_bool_error;
 
-	return 0;
+	return isl_bool_false;
 }
 
+#undef TYPE
+#define TYPE	isl_aff
+static
+#include "check_type_range_templ.c"
+
 /* 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
@@ -2395,7 +2461,6 @@ isl_bool 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;
 	isl_bool involves = isl_bool_false;
 
@@ -2403,11 +2468,8 @@ isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff,
 		return isl_bool_error;
 	if (n == 0)
 		return isl_bool_false;
-
-	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 isl_bool_error);
+	if (isl_aff_check_range(aff, type, first, n) < 0)
+		return isl_bool_error;
 
 	active = isl_local_space_get_active(aff->ls, aff->v->el + 2);
 	if (!active)
@@ -2428,6 +2490,18 @@ isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff,
 	return isl_bool_error;
 }
 
+/* Does "aff" involve any local variables, i.e., integer divisions?
+ */
+isl_bool isl_aff_involves_locals(__isl_keep isl_aff *aff)
+{
+	isl_size n;
+
+	n = isl_aff_dim(aff, isl_dim_div);
+	if (n < 0)
+		return isl_bool_error;
+	return isl_aff_involves_dims(aff, isl_dim_div, 0, n);
+}
+
 __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
@@ -2445,9 +2519,8 @@ __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
 		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));
+	if (isl_local_space_check_range(aff->ls, type, first, n) < 0)
+		return isl_aff_free(aff);
 
 	aff = isl_aff_cow(aff);
 	if (!aff)
@@ -2465,70 +2538,31 @@ __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
 	return aff;
 }
 
-/* Drop the "n" domain dimensions starting at "first" from "aff",
- * after checking that they do not appear in the affine expression.
+/* Is the domain of "aff" a product?
  */
-static __isl_give isl_aff *drop_domain(__isl_take isl_aff *aff, unsigned first,
-	unsigned n)
+static isl_bool isl_aff_domain_is_product(__isl_keep isl_aff *aff)
 {
-	isl_bool involves;
-
-	involves = isl_aff_involves_dims(aff, isl_dim_in, first, 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));
-	return isl_aff_drop_dims(aff, isl_dim_in, first, n);
+	return isl_space_is_product(isl_aff_peek_domain_space(aff));
 }
 
+#undef TYPE
+#define TYPE	isl_aff
+#include <isl_domain_factor_templ.c>
+
 /* 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;
+	isl_size n;
 
 	n = isl_aff_dim(aff, isl_dim_in);
-	aff = drop_domain(aff, 0, n);
-	space = isl_aff_get_domain_space(aff);
-	space = isl_space_params(space);
-	aff = isl_aff_reset_domain_space(aff, space);
-	return aff;
-}
-
-/* Check that the domain of "aff" is a product.
- */
-static isl_stat check_domain_product(__isl_keep isl_aff *aff)
-{
-	isl_bool is_product;
-
-	is_product = isl_space_is_product(isl_aff_peek_domain_space(aff));
-	if (is_product < 0)
-		return isl_stat_error;
-	if (!is_product)
-		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
-			"domain is not a product", return isl_stat_error);
-	return isl_stat_ok;
-}
-
-/* Given an affine function with a domain of the form [A -> B] that
- * does not depend on B, return the same function on domain A.
- */
-__isl_give isl_aff *isl_aff_domain_factor_domain(__isl_take isl_aff *aff)
-{
-	isl_space *space;
-	int n, n_in;
-
-	if (check_domain_product(aff) < 0)
+	if (n < 0)
 		return isl_aff_free(aff);
+	aff = isl_aff_drop_domain(aff, 0, n);
 	space = isl_aff_get_domain_space(aff);
-	n = isl_space_dim(space, isl_dim_set);
-	space = isl_space_factor_domain(space);
-	n_in = isl_space_dim(space, isl_dim_set);
-	aff = drop_domain(aff, n_in, n - n_in);
+	space = isl_space_params(space);
 	aff = isl_aff_reset_domain_space(aff, space);
 	return aff;
 }
@@ -2564,9 +2598,8 @@ __isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
 		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));
+	if (isl_local_space_check_range(aff->ls, type, first, 0) < 0)
+		return isl_aff_free(aff);
 
 	aff = isl_aff_cow(aff);
 	if (!aff)
@@ -2587,9 +2620,11 @@ __isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
 __isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
 	enum isl_dim_type type, unsigned n)
 {
-	unsigned pos;
+	isl_size pos;
 
 	pos = isl_aff_dim(aff, type);
+	if (pos < 0)
+		return isl_aff_free(aff);
 
 	return isl_aff_insert_dims(aff, type, pos, n);
 }
@@ -2597,9 +2632,11 @@ __isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
 __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;
+	isl_size pos;
 
 	pos = isl_pw_aff_dim(pwaff, type);
+	if (pos < 0)
+		return isl_pw_aff_free(pwaff);
 
 	return isl_pw_aff_insert_dims(pwaff, type, pos, n);
 }
@@ -2615,6 +2652,7 @@ __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
 {
 	unsigned g_dst_pos;
 	unsigned g_src_pos;
+	isl_size src_off, dst_off;
 
 	if (!aff)
 		return NULL;
@@ -2635,20 +2673,21 @@ __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
 	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", return isl_aff_free(aff));
+	if (isl_local_space_check_range(aff->ls, src_type, src_pos, n) < 0)
+		return 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",
 			return isl_aff_free(aff));
 
 	aff = isl_aff_cow(aff);
-	if (!aff)
-		return NULL;
+	src_off = isl_aff_domain_offset(aff, src_type);
+	dst_off = isl_aff_domain_offset(aff, dst_type);
+	if (src_off < 0 || dst_off < 0)
+		return isl_aff_free(aff);
 
-	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;
+	g_src_pos = 1 + src_off + src_pos;
+	g_dst_pos = 1 + dst_off + dst_pos;
 	if (dst_type > src_type)
 		g_dst_pos -= n;
 
@@ -2663,18 +2702,25 @@ __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
 	return aff;
 }
 
-__isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
+/* Return a zero isl_aff in the given space.
+ *
+ * This is a helper function for isl_pw_*_as_* that ensures a uniform
+ * interface over all piecewise types.
+ */
+static __isl_give isl_aff *isl_aff_zero_in_space(__isl_take isl_space *space)
 {
-	isl_set *dom = isl_set_universe(isl_aff_get_domain_space(aff));
-	return isl_pw_aff_alloc(dom, aff);
+	isl_local_space *ls;
+
+	ls = isl_local_space_from_space(isl_space_domain(space));
+	return isl_aff_zero_on_domain(ls);
 }
 
 #define isl_aff_involves_nan isl_aff_is_nan
 
 #undef PW
 #define PW isl_pw_aff
-#undef EL
-#define EL isl_aff
+#undef BASE
+#define BASE aff
 #undef EL_IS_ZERO
 #define EL_IS_ZERO is_empty
 #undef ZERO
@@ -2686,13 +2732,16 @@ __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
 #undef DEFAULT_IS_ZERO
 #define DEFAULT_IS_ZERO 0
 
-#define NO_OPT
-#define NO_LIFT
-#define NO_MORPH
-
 #include <isl_pw_templ.c>
+#include <isl_pw_add_constant_val_templ.c>
+#include <isl_pw_bind_domain_templ.c>
 #include <isl_pw_eval.c>
 #include <isl_pw_hash.c>
+#include <isl_pw_insert_dims_templ.c>
+#include <isl_pw_move_dims_templ.c>
+#include <isl_pw_neg_templ.c>
+#include <isl_pw_pullback_templ.c>
+#include <isl_pw_sub_templ.c>
 #include <isl_pw_union_opt.c>
 
 #undef BASE
@@ -2701,78 +2750,17 @@ __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
 #include <isl_union_single.c>
 #include <isl_union_neg.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))
-{
-	isl_bool equal_params;
-
-	if (!pwaff1 || !pwaff2)
-		goto error;
-	equal_params = isl_space_has_equal_params(pwaff1->dim, pwaff2->dim);
-	if (equal_params < 0)
-		goto error;
-	if (equal_params)
-		return fn(pwaff1, pwaff2);
-	if (isl_pw_aff_check_named_params(pwaff1) < 0 ||
-	    isl_pw_aff_check_named_params(pwaff2) < 0)
-		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;
-}
-
-/* Align the parameters of the to isl_pw_aff arguments and
- * then apply a function "fn" on them that returns an isl_map.
- */
-static __isl_give isl_map *align_params_pw_pw_map_and(
-	__isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
-	__isl_give isl_map *(*fn)(__isl_take isl_pw_aff *pa1,
-				    __isl_take isl_pw_aff *pa2))
-{
-	isl_bool equal_params;
-
-	if (!pa1 || !pa2)
-		goto error;
-	equal_params = isl_space_has_equal_params(pa1->dim, pa2->dim);
-	if (equal_params < 0)
-		goto error;
-	if (equal_params)
-		return fn(pa1, pa2);
-	if (isl_pw_aff_check_named_params(pa1) < 0 ||
-	    isl_pw_aff_check_named_params(pa2) < 0)
-		goto error;
-	pa1 = isl_pw_aff_align_params(pa1, isl_pw_aff_get_space(pa2));
-	pa2 = isl_pw_aff_align_params(pa2, isl_pw_aff_get_space(pa1));
-	return fn(pa1, pa2);
-error:
-	isl_pw_aff_free(pa1);
-	isl_pw_aff_free(pa2);
-	return NULL;
-}
-
 /* Compute a piecewise quasi-affine expression with a domain that
  * is the union of those of pwaff1 and pwaff2 and such that on each
  * cell, the quasi-affine expression is the 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 isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_ge_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);
+	isl_pw_aff_align_params_bin(&pwaff1, &pwaff2);
+	return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_ge_set);
 }
 
 /* Compute a piecewise quasi-affine expression with a domain that
@@ -2781,17 +2769,11 @@ __isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *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 isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_le_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_pw_aff_align_params_bin(&pwaff1, &pwaff2);
+	return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_le_set);
 }
 
 __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
@@ -2803,6 +2785,17 @@ __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
 		return isl_pw_aff_union_min(pwaff1, pwaff2);
 }
 
+/* Is the domain of "pa" a product?
+ */
+static isl_bool isl_pw_aff_domain_is_product(__isl_keep isl_pw_aff *pa)
+{
+	return isl_space_domain_is_wrapping(isl_pw_aff_peek_space(pa));
+}
+
+#undef TYPE
+#define TYPE	isl_pw_aff
+#include <isl_domain_factor_templ.c>
+
 /* Return a set containing those elements in the domain
  * of "pwaff" where it satisfies "fn" (if complement is 0) or
  * does not satisfy "fn" (if complement is 1).
@@ -2811,8 +2804,9 @@ __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
  * NaN does not satisfy any property.
  */
 static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff,
-	__isl_give isl_basic_set *(*fn)(__isl_take isl_aff *aff, int rational),
-	int complement)
+	__isl_give isl_basic_set *(*fn)(__isl_take isl_aff *aff, int rational,
+		void *user),
+	int complement, void *user)
 {
 	int i;
 	isl_set *set;
@@ -2831,7 +2825,7 @@ static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff,
 			continue;
 
 		rational = isl_set_has_rational(pwaff->p[i].set);
-		bset = fn(isl_aff_copy(pwaff->p[i].aff), rational);
+		bset = fn(isl_aff_copy(pwaff->p[i].aff), rational, user);
 		locus = isl_set_from_basic_set(bset);
 		set_i = isl_set_copy(pwaff->p[i].set);
 		if (complement)
@@ -2851,7 +2845,7 @@ static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff,
  */
 __isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa)
 {
-	return pw_aff_locus(pa, &aff_pos_basic_set, 0);
+	return pw_aff_locus(pa, &aff_pos_basic_set, 0, NULL);
 }
 
 /* Return a set containing those elements in the domain
@@ -2859,7 +2853,7 @@ __isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa)
  */
 __isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff)
 {
-	return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0);
+	return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0, NULL);
 }
 
 /* Return a set containing those elements in the domain
@@ -2867,7 +2861,7 @@ __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)
 {
-	return pw_aff_locus(pwaff, &aff_zero_basic_set, 0);
+	return pw_aff_locus(pwaff, &aff_zero_basic_set, 0, NULL);
 }
 
 /* Return a set containing those elements in the domain
@@ -2875,7 +2869,60 @@ __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)
 {
-	return pw_aff_locus(pwaff, &aff_zero_basic_set, 1);
+	return pw_aff_locus(pwaff, &aff_zero_basic_set, 1, NULL);
+}
+
+/* Bind the affine function "aff" to the parameter "id",
+ * returning the elements in the domain where the affine expression
+ * is equal to the parameter.
+ */
+__isl_give isl_basic_set *isl_aff_bind_id(__isl_take isl_aff *aff,
+	__isl_take isl_id *id)
+{
+	isl_space *space;
+	isl_aff *aff_id;
+
+	space = isl_aff_get_domain_space(aff);
+	space = isl_space_add_param_id(space, isl_id_copy(id));
+
+	aff = isl_aff_align_params(aff, isl_space_copy(space));
+	aff_id = isl_aff_param_on_domain_space_id(space, id);
+
+	return isl_aff_eq_basic_set(aff, aff_id);
+}
+
+/* Wrapper around isl_aff_bind_id for use as pw_aff_locus callback.
+ * "rational" should not be set.
+ */
+static __isl_give isl_basic_set *aff_bind_id(__isl_take isl_aff *aff,
+	int rational, void *user)
+{
+	isl_id *id = user;
+
+	if (!aff)
+		return NULL;
+	if (rational)
+		isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
+			"rational binding not supported", goto error);
+	return isl_aff_bind_id(aff, isl_id_copy(id));
+error:
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* Bind the piecewise affine function "pa" to the parameter "id",
+ * returning the elements in the domain where the expression
+ * is equal to the parameter.
+ */
+__isl_give isl_set *isl_pw_aff_bind_id(__isl_take isl_pw_aff *pa,
+	__isl_take isl_id *id)
+{
+	isl_set *bound;
+
+	bound = pw_aff_locus(pa, &aff_bind_id, 0, id);
+	isl_id_free(id);
+
+	return bound;
 }
 
 /* Return a set containing those elements in the shared domain
@@ -2900,9 +2947,9 @@ static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1,
 	pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2));
 
 	if (strict) {
-		isl_space *dim = isl_set_get_space(set1);
+		isl_space *space = isl_set_get_space(set1);
 		isl_aff *aff;
-		aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
+		aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
 		aff = isl_aff_add_constant_si(aff, -1);
 		pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff));
 	} else
@@ -2916,46 +2963,31 @@ static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *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);
+	isl_pw_aff_align_params_bin(&pwaff1, &pwaff2);
+	return pw_aff_gte_set(pwaff1, pwaff2, 0, 1);
 }
 
 /* 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);
+	isl_pw_aff_align_params_bin(&pwaff1, &pwaff2);
+	return pw_aff_gte_set(pwaff1, pwaff2, 0, 0);
 }
 
 /* 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_pw_aff_align_params_bin(&pwaff1, &pwaff2);
+	return pw_aff_gte_set(pwaff1, pwaff2, 1, 0);
 }
 
 __isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
@@ -2973,7 +3005,6 @@ __isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
  * where the function values are ordered in the same way as "order",
  * which returns a set in the shared domain of its two arguments.
- * The parameters of "pa1" and "pa2" are assumed to have been aligned.
  *
  * Let "pa1" and "pa2" be defined on domains A and B respectively.
  * We first pull back the two functions such that they are defined on
@@ -2981,7 +3012,7 @@ __isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
  * in the space [A -> B].  Finally, we unwrap this set to obtain
  * a map in the space A -> B.
  */
-static __isl_give isl_map *isl_pw_aff_order_map_aligned(
+static __isl_give isl_map *isl_pw_aff_order_map(
 	__isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
 	__isl_give isl_set *(*order)(__isl_take isl_pw_aff *pa1,
 		__isl_take isl_pw_aff *pa2))
@@ -2990,6 +3021,7 @@ static __isl_give isl_map *isl_pw_aff_order_map_aligned(
 	isl_multi_aff *ma;
 	isl_set *set;
 
+	isl_pw_aff_align_params_bin(&pa1, &pa2);
 	space1 = isl_space_domain(isl_pw_aff_get_space(pa1));
 	space2 = isl_space_domain(isl_pw_aff_get_space(pa2));
 	space1 = isl_space_map_from_domain_and_range(space1, space2);
@@ -3002,33 +3034,23 @@ static __isl_give isl_map *isl_pw_aff_order_map_aligned(
 	return isl_set_unwrap(set);
 }
 
-/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
- * where the function values are equal.
- * The parameters of "pa1" and "pa2" are assumed to have been aligned.
- */
-static __isl_give isl_map *isl_pw_aff_eq_map_aligned(__isl_take isl_pw_aff *pa1,
-	__isl_take isl_pw_aff *pa2)
-{
-	return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_eq_set);
-}
-
 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
  * where the function values are equal.
  */
 __isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2)
 {
-	return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_eq_map_aligned);
+	return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_eq_set);
 }
 
 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
- * where the function value of "pa1" is less than the function value of "pa2".
- * The parameters of "pa1" and "pa2" are assumed to have been aligned.
+ * where the function value of "pa1" is less than or equal to
+ * the function value of "pa2".
  */
-static __isl_give isl_map *isl_pw_aff_lt_map_aligned(__isl_take isl_pw_aff *pa1,
+__isl_give isl_map *isl_pw_aff_le_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2)
 {
-	return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_lt_set);
+	return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_le_set);
 }
 
 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
@@ -3037,18 +3059,17 @@ static __isl_give isl_map *isl_pw_aff_lt_map_aligned(__isl_take isl_pw_aff *pa1,
 __isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2)
 {
-	return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_lt_map_aligned);
+	return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_lt_set);
 }
 
 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
- * where the function value of "pa1" is greater than the function value
- * of "pa2".
- * The parameters of "pa1" and "pa2" are assumed to have been aligned.
+ * where the function value of "pa1" is greater than or equal to
+ * the function value of "pa2".
  */
-static __isl_give isl_map *isl_pw_aff_gt_map_aligned(__isl_take isl_pw_aff *pa1,
+__isl_give isl_map *isl_pw_aff_ge_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2)
 {
-	return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_gt_set);
+	return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_ge_set);
 }
 
 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
@@ -3058,7 +3079,7 @@ static __isl_give isl_map *isl_pw_aff_gt_map_aligned(__isl_take isl_pw_aff *pa1,
 __isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
 	__isl_take isl_pw_aff *pa2)
 {
-	return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_gt_map_aligned);
+	return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_gt_set);
 }
 
 /* Return a set containing those elements in the shared domain
@@ -3149,23 +3170,18 @@ __isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
 /* 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_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
 	__isl_take isl_pw_aff *pwaff2)
 {
 	isl_set *set_lt, *set_gt;
 
+	isl_pw_aff_align_params_bin(&pwaff1, &pwaff2);
 	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)
 {
@@ -3301,10 +3317,13 @@ __isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond,
 
 isl_bool isl_aff_is_cst(__isl_keep isl_aff *aff)
 {
+	int pos;
+
 	if (!aff)
 		return isl_bool_error;
 
-	return isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2) == -1;
+	pos = isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2);
+	return isl_bool_ok(pos == -1);
 }
 
 /* Check whether pwaff is a piecewise constant.
@@ -3325,24 +3344,6 @@ isl_bool isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff)
 	return isl_bool_true;
 }
 
-/* Are all elements of "mpa" piecewise constants?
- */
-isl_bool isl_multi_pw_aff_is_cst(__isl_keep isl_multi_pw_aff *mpa)
-{
-	int i;
-
-	if (!mpa)
-		return isl_bool_error;
-
-	for (i = 0; i < mpa->n; ++i) {
-		isl_bool is_cst = isl_pw_aff_is_cst(mpa->u.p[i]);
-		if (is_cst < 0 || !is_cst)
-			return is_cst;
-	}
-
-	return isl_bool_true;
-}
-
 /* Return the product of "aff1" and "aff2".
  *
  * If either of the two is NaN, then the result is NaN.
@@ -3441,16 +3442,11 @@ __isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
 	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_pw_aff_align_params_bin(&pwaff1, &pwaff2);
+	return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add);
 }
 
 __isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
@@ -3459,22 +3455,11 @@ __isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
 	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);
+	isl_pw_aff_align_params_bin(&pwaff1, &pwaff2);
+	return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul);
 }
 
 /* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
@@ -3491,7 +3476,8 @@ __isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
 		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);
+	isl_pw_aff_align_params_bin(&pa1, &pa2);
+	return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div);
 error:
 	isl_pw_aff_free(pa1);
 	isl_pw_aff_free(pa2);
@@ -3644,10 +3630,11 @@ static __isl_give isl_pw_aff *pw_aff_min_max(__isl_take isl_pw_aff *pa1,
 	else if (has_nan)
 		return replace_by_nan(pa1, pa2);
 
+	isl_pw_aff_align_params_bin(&pa1, &pa2);
 	if (max)
-		return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_max);
+		return pw_aff_max(pa1, pa2);
 	else
-		return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_min);
+		return pw_aff_min(pa1, pa2);
 }
 
 /* Return an expression for the minimum of "pwaff1" and "pwaff2".
@@ -3809,21 +3796,53 @@ isl_stat isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
 	return isl_stat_error;
 }
 
+/* Return the shared (universe) domain of the elements of "ma".
+ *
+ * Since an isl_multi_aff (and an isl_aff) is always total,
+ * the domain is always the universe set in its domain space.
+ * This is a helper function for use in the generic isl_multi_*_bind.
+ */
+static __isl_give isl_basic_set *isl_multi_aff_domain(
+	__isl_take isl_multi_aff *ma)
+{
+	isl_space *space;
+
+	space = isl_multi_aff_get_space(ma);
+	isl_multi_aff_free(ma);
+
+	return isl_basic_set_universe(isl_space_domain(space));
+}
+
 #undef BASE
 #define BASE aff
-#undef DOMBASE
-#define DOMBASE set
-#define NO_DOMAIN
 
 #include <isl_multi_no_explicit_domain.c>
 #include <isl_multi_templ.c>
+#include <isl_multi_add_constant_templ.c>
 #include <isl_multi_apply_set.c>
+#include <isl_multi_arith_templ.c>
+#include <isl_multi_bind_domain_templ.c>
 #include <isl_multi_cmp.c>
+#include <isl_multi_dim_id_templ.c>
 #include <isl_multi_dims.c>
 #include <isl_multi_floor.c>
+#include <isl_multi_from_base_templ.c>
+#include <isl_multi_identity_templ.c>
+#include <isl_multi_locals_templ.c>
+#include <isl_multi_move_dims_templ.c>
+#include <isl_multi_nan_templ.c>
+#include <isl_multi_product_templ.c>
+#include <isl_multi_splice_templ.c>
+#include <isl_multi_tuple_id_templ.c>
+#include <isl_multi_zero_templ.c>
+
+#undef DOMBASE
+#define DOMBASE set
 #include <isl_multi_gist.c>
 
-#undef NO_DOMAIN
+#undef DOMBASE
+#define DOMBASE basic_set
+#include <isl_multi_bind_templ.c>
 
 /* Construct an isl_multi_aff living in "space" that corresponds
  * to the affine transformation matrix "mat".
@@ -3834,7 +3853,7 @@ __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat(
 	isl_ctx *ctx;
 	isl_local_space *ls = NULL;
 	isl_multi_aff *ma = NULL;
-	int n_row, n_col, n_out, total;
+	isl_size n_row, n_col, n_out, total;
 	int i;
 
 	if (!space || !mat)
@@ -3844,14 +3863,16 @@ __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat(
 
 	n_row = isl_mat_rows(mat);
 	n_col = isl_mat_cols(mat);
+	n_out = isl_space_dim(space, isl_dim_out);
+	total = isl_space_dim(space, isl_dim_all);
+	if (n_row < 0 || n_col < 0 || n_out < 0 || total < 0)
+		goto error;
 	if (n_row < 1)
 		isl_die(ctx, isl_error_invalid,
 			"insufficient number of rows", goto error);
 	if (n_col < 1)
 		isl_die(ctx, isl_error_invalid,
 			"insufficient number of columns", goto error);
-	n_out = isl_space_dim(space, isl_dim_out);
-	total = isl_space_dim(space, isl_dim_all);
 	if (1 + n_out != n_row || 2 + total != n_row + n_col)
 		isl_die(ctx, isl_error_invalid,
 			"dimension mismatch", goto error);
@@ -3883,6 +3904,36 @@ __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat(
 	return NULL;
 }
 
+/* Return the constant terms of the affine expressions of "ma".
+ */
+__isl_give isl_multi_val *isl_multi_aff_get_constant_multi_val(
+	__isl_keep isl_multi_aff *ma)
+{
+	int i;
+	isl_size n;
+	isl_space *space;
+	isl_multi_val *mv;
+
+	n = isl_multi_aff_size(ma);
+	if (n < 0)
+		return NULL;
+	space = isl_space_range(isl_multi_aff_get_space(ma));
+	space = isl_space_drop_all_params(space);
+	mv = isl_multi_val_zero(space);
+
+	for (i = 0; i < n; ++i) {
+		isl_aff *aff;
+		isl_val *val;
+
+		aff = isl_multi_aff_get_at(ma, i);
+		val = isl_aff_get_constant_val(aff);
+		isl_aff_free(aff);
+		mv = isl_multi_val_set_at(mv, i, val);
+	}
+
+	return mv;
+}
+
 /* 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.
@@ -3910,7 +3961,8 @@ __isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
  */
 __isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space)
 {
-	int i, n_in;
+	int i;
+	isl_size n_in;
 	isl_local_space *ls;
 	isl_multi_aff *ma;
 
@@ -3921,6 +3973,8 @@ __isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space)
 			"not a map space", goto error);
 
 	n_in = isl_space_dim(space, isl_dim_in);
+	if (n_in < 0)
+		goto error;
 	space = isl_space_domain_map(space);
 
 	ma = isl_multi_aff_alloc(isl_space_copy(space));
@@ -3950,7 +4004,8 @@ __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)
 {
-	int i, n_in, n_out;
+	int i;
+	isl_size n_in, n_out;
 	isl_local_space *ls;
 	isl_multi_aff *ma;
 
@@ -3962,6 +4017,8 @@ __isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space)
 
 	n_in = isl_space_dim(space, isl_dim_in);
 	n_out = isl_space_dim(space, isl_dim_out);
+	if (n_in < 0 || n_out < 0)
+		goto error;
 	space = isl_space_range_map(space);
 
 	ma = isl_multi_aff_alloc(isl_space_copy(space));
@@ -4002,7 +4059,8 @@ __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;
+	int i;
+	isl_size dim;
 	isl_local_space *ls;
 	isl_multi_aff *ma;
 
@@ -4014,11 +4072,12 @@ __isl_give isl_multi_aff *isl_multi_aff_project_out_map(
 	if (type != isl_dim_set)
 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
 			"only set dimensions can be projected out", goto error);
+	if (isl_space_check_range(space, type, first, n) < 0)
+		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);
+	if (dim < 0)
+		goto error;
 
 	space = isl_space_from_domain(space);
 	space = isl_space_add_dims(space, isl_dim_out, dim - n);
@@ -4066,16 +4125,6 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map(
 	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.
  */
@@ -4137,12 +4186,12 @@ __isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_set *dom,
 	return maff1;
 }
 
-int isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff)
+isl_bool isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff)
 {
 	if (!maff)
-		return -1;
+		return isl_bool_error;
 
-	return 0;
+	return isl_bool_false;
 }
 
 /* Return the set of domain elements where "ma1" is lexicographically
@@ -4203,10 +4252,12 @@ __isl_give isl_set *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1,
 	return isl_multi_aff_order_set(ma1, ma2, &isl_map_lex_gt);
 }
 
+#define isl_multi_aff_zero_in_space	isl_multi_aff_zero
+
 #undef PW
 #define PW isl_pw_multi_aff
-#undef EL
-#define EL isl_multi_aff
+#undef BASE
+#define BASE multi_aff
 #undef EL_IS_ZERO
 #define EL_IS_ZERO is_empty
 #undef ZERO
@@ -4218,29 +4269,97 @@ __isl_give isl_set *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1,
 #undef DEFAULT_IS_ZERO
 #define DEFAULT_IS_ZERO 0
 
-#define NO_SUB
-#define NO_OPT
-#define NO_INSERT_DIMS
-#define NO_LIFT
-#define NO_MORPH
-
 #include <isl_pw_templ.c>
+#include <isl_pw_add_constant_multi_val_templ.c>
+#include <isl_pw_add_constant_val_templ.c>
+#include <isl_pw_bind_domain_templ.c>
+#include <isl_pw_move_dims_templ.c>
+#include <isl_pw_neg_templ.c>
+#include <isl_pw_pullback_templ.c>
 #include <isl_pw_union_opt.c>
 
-#undef NO_SUB
-
 #undef BASE
 #define BASE pw_multi_aff
 
 #include <isl_union_multi.c>
 #include <isl_union_neg.c>
 
-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)
+/* Generic function for extracting a factor from a product "pma".
+ * "check_space" checks that the space is that of the right kind of product.
+ * "space_factor" extracts the factor from the space.
+ * "multi_aff_factor" extracts the factor from the constituent functions.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_factor(
+	__isl_take isl_pw_multi_aff *pma,
+	isl_stat (*check_space)(__isl_keep isl_pw_multi_aff *pma),
+	__isl_give isl_space *(*space_factor)(__isl_take isl_space *space),
+	__isl_give isl_multi_aff *(*multi_aff_factor)(
+		__isl_take isl_multi_aff *ma))
 {
-	return isl_pw_multi_aff_union_opt_cmp(pma1, pma2,
-					    &isl_multi_aff_lex_ge_set);
+	int i;
+	isl_space *space;
+
+	if (check_space(pma) < 0)
+		return isl_pw_multi_aff_free(pma);
+
+	space = isl_pw_multi_aff_take_space(pma);
+	space = space_factor(space);
+
+	for (i = 0; pma && i < pma->n; ++i) {
+		isl_multi_aff *ma;
+
+		ma = isl_pw_multi_aff_take_base_at(pma, i);
+		ma = multi_aff_factor(ma);
+		pma = isl_pw_multi_aff_restore_base_at(pma, i, ma);
+	}
+
+	pma = isl_pw_multi_aff_restore_space(pma, space);
+
+	return pma;
+}
+
+/* Is the range of "pma" a wrapped relation?
+ */
+static isl_bool isl_pw_multi_aff_range_is_wrapping(
+	__isl_keep isl_pw_multi_aff *pma)
+{
+	return isl_space_range_is_wrapping(isl_pw_multi_aff_peek_space(pma));
+}
+
+/* Check that the range of "pma" is a product.
+ */
+static isl_stat pw_multi_aff_check_range_product(
+	__isl_keep isl_pw_multi_aff *pma)
+{
+	isl_bool wraps;
+
+	wraps = isl_pw_multi_aff_range_is_wrapping(pma);
+	if (wraps < 0)
+		return isl_stat_error;
+	if (!wraps)
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+			"range is not a product", return isl_stat_error);
+	return isl_stat_ok;
+}
+
+/* Given a function A -> [B -> C], extract the function A -> B.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_domain(
+	__isl_take isl_pw_multi_aff *pma)
+{
+	return pw_multi_aff_factor(pma, &pw_multi_aff_check_range_product,
+				&isl_space_range_factor_domain,
+				&isl_multi_aff_range_factor_domain);
+}
+
+/* Given a function A -> [B -> C], extract the function A -> C.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_range(
+	__isl_take isl_pw_multi_aff *pma)
+{
+	return pw_multi_aff_factor(pma, &pw_multi_aff_check_range_product,
+				&isl_space_range_factor_range,
+				&isl_multi_aff_range_factor_range);
 }
 
 /* Given two piecewise multi affine expressions, return a piecewise
@@ -4253,16 +4372,9 @@ __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)
-{
+	isl_pw_multi_aff_align_params_bin(&pma1, &pma2);
 	return isl_pw_multi_aff_union_opt_cmp(pma1, pma2,
-					    &isl_multi_aff_lex_le_set);
+					    &isl_multi_aff_lex_ge_set);
 }
 
 /* Given two piecewise multi affine expressions, return a piecewise
@@ -4275,29 +4387,17 @@ __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);
+	isl_pw_multi_aff_align_params_bin(&pma1, &pma2);
+	return isl_pw_multi_aff_union_opt_cmp(pma1, pma2,
+					    &isl_multi_aff_lex_le_set);
 }
 
-static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
+__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_pw_multi_aff_align_params_bin(&pma1, &pma2);
 	return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
-						&isl_multi_aff_sub);
+						&isl_multi_aff_add);
 }
 
 /* Subtract "pma2" from "pma1" and return the result.
@@ -4305,8 +4405,9 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
 __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_pw_multi_aff_align_params_bin(&pma1, &pma2);
+	return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
+						&isl_multi_aff_sub);
 }
 
 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
@@ -4339,14 +4440,14 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_union_add(
 /* 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_give isl_pw_multi_aff *isl_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)
+	if (isl_pw_multi_aff_align_params_bin(&pma1, &pma2) < 0)
 		goto error;
 
 	n = pma1->n * pma2->n;
@@ -4377,13 +4478,6 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_product(
 	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);
-}
-
 /* Subtract the initial "n" elements in "ma" with coefficients in "c" and
  * denominator "denom".
  * "denom" is allowed to be negative, in which case the actual denominator
@@ -4493,7 +4587,7 @@ static __isl_give isl_aff *extract_aff_from_equality(
 	__isl_keep isl_multi_aff *ma)
 {
 	unsigned o_out;
-	unsigned n_div, n_out;
+	isl_size n_div, n_out;
 	isl_ctx *ctx;
 	isl_local_space *ls;
 	isl_aff *aff, *shift;
@@ -4508,6 +4602,8 @@ static __isl_give isl_aff *extract_aff_from_equality(
 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_out < 0 || n_div < 0)
+		goto error;
 	if (isl_int_is_neg(bmap->eq[eq][o_out + pos])) {
 		isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], o_out);
 		isl_seq_cpy(aff->v->el + 1 + o_out,
@@ -4587,7 +4683,7 @@ 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_size n_out;
 	isl_multi_aff *ma;
 
 	if (!bmap)
@@ -4595,6 +4691,8 @@ static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map(
 
 	ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap));
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (n_out < 0)
+		ma = isl_multi_aff_free(ma);
 
 	for (i = 0; i < n_out; ++i) {
 		isl_aff *aff;
@@ -4720,15 +4818,15 @@ 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_space *space = NULL;
 	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_size n;
+	isl_size n_in;
 	isl_pw_multi_aff *pma;
 	isl_bool is_set;
 
@@ -4741,6 +4839,8 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div(
 	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);
+	if (n_in < 0 || n < 0)
+		goto error;
 
 	v = isl_vec_alloc(ctx, 1 + 1 + n);
 	if (v) {
@@ -4769,6 +4869,7 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div(
 
 	return pma;
 error:
+	isl_space_free(space);
 	isl_map_free(map);
 	isl_basic_map_free(hull);
 	return NULL;
@@ -4839,29 +4940,31 @@ static int is_potential_div_constraint(isl_int *c, int offset, int d, int total)
 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div(
 	__isl_take isl_map *map)
 {
-	int d, dim;
+	int d;
+	isl_size dim;
 	int i, j, n;
-	int offset, total;
+	int offset;
+	isl_size total;
 	isl_int sum;
 	isl_basic_map *hull;
 
 	hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
-	if (!hull)
+	dim = isl_map_dim(map, isl_dim_out);
+	total = isl_basic_map_dim(hull, isl_dim_all);
+	if (dim < 0 || total < 0)
 		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))
+							offset, d, 1 + total))
 				continue;
 			for (j = i + 1; j < n; ++j) {
 				if (!isl_seq_is_neg(hull->ineq[i] + 1,
-						hull->ineq[j] + 1, total - 1))
+						hull->ineq[j] + 1, total))
 					continue;
 				isl_int_add(sum, hull->ineq[i][0],
 						hull->ineq[j][0]);
@@ -5004,9 +5107,9 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
 	isl_aff *aff;
 	isl_multi_aff *ma;
 	isl_pw_multi_aff *pma, *id;
-	unsigned n_in;
+	isl_size n_in;
 	unsigned o_out;
-	unsigned n_out;
+	isl_size n_out;
 	isl_bool is_set;
 
 	is_set = isl_map_is_set(map);
@@ -5015,6 +5118,8 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
 
 	n_in = isl_basic_map_dim(hull, isl_dim_in);
 	n_out = isl_basic_map_dim(hull, isl_dim_out);
+	if (n_in < 0 || n_out < 0)
+		goto error;
 	o_out = isl_basic_map_offset(hull, isl_dim_out);
 
 	if (is_set)
@@ -5082,14 +5187,16 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides(
 	__isl_take isl_map *map, __isl_take isl_basic_map *hull)
 {
 	int i, j;
-	unsigned n_out;
+	isl_size n_out;
 	unsigned o_out;
-	unsigned n_div;
+	isl_size n_div;
 	unsigned o_div;
 	isl_int gcd;
 
 	n_div = isl_basic_map_dim(hull, isl_dim_div);
-	o_div = isl_basic_map_offset(hull, isl_dim_div);
+	n_out = isl_basic_map_dim(hull, isl_dim_out);
+	if (n_div < 0 || n_out < 0)
+		goto error;
 
 	if (n_div == 0) {
 		isl_basic_map_free(hull);
@@ -5098,7 +5205,7 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides(
 
 	isl_int_init(gcd);
 
-	n_out = isl_basic_map_dim(hull, isl_dim_out);
+	o_div = isl_basic_map_offset(hull, isl_dim_div);
 	o_out = isl_basic_map_offset(hull, isl_dim_out);
 
 	for (i = 0; i < n_out; ++i) {
@@ -5130,6 +5237,10 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides(
 	isl_int_clear(gcd);
 	isl_basic_map_free(hull);
 	return pw_multi_aff_from_map_check_div(map);
+error:
+	isl_map_free(map);
+	isl_basic_map_free(hull);
+	return NULL;
 }
 
 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
@@ -5145,12 +5256,14 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides(
 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
 {
 	isl_bool sv;
+	isl_size n;
 	isl_basic_map *hull;
 
-	if (!map)
-		return NULL;
+	n = isl_map_n_basic_map(map);
+	if (n < 0)
+		goto error;
 
-	if (isl_map_n_basic_map(map) == 1) {
+	if (n == 1) {
 		hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
 		hull = isl_basic_map_plain_affine_hull(hull);
 		sv = isl_basic_map_plain_is_single_valued(hull);
@@ -5167,6 +5280,7 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
 	if (sv >= 0)
 		return pw_multi_aff_from_map_check_strides(map, hull);
 	isl_basic_map_free(hull);
+error:
 	isl_map_free(map);
 	return NULL;
 }
@@ -5275,6 +5389,7 @@ __isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff,
 {
 	isl_ctx *ctx;
 	isl_int v;
+	isl_size n_div;
 
 	aff = isl_aff_cow(aff);
 	if (!aff || !subs)
@@ -5284,7 +5399,10 @@ __isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *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)
+	n_div = isl_aff_domain_dim(subs, isl_dim_div);
+	if (n_div < 0)
+		return isl_aff_free(aff);
+	if (n_div != 0)
 		isl_die(ctx, isl_error_unsupported,
 			"cannot handle divs yet", return isl_aff_free(aff));
 
@@ -5434,18 +5552,20 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
  * 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_stat 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;
+	isl_size 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);
+	if (n_param < 0 || n_in < 0 || n_out < 0)
+		return isl_stat_error;
 
 	isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before);
 	o_dst = o_src = has_denom + 1 + n_param + n_before;
@@ -5495,6 +5615,8 @@ void isl_seq_preimage(isl_int *dst, isl_int *src,
 		if (has_denom)
 			isl_int_mul(dst[0], dst[0], c1);
 	}
+
+	return isl_stat_ok;
 }
 
 /* Compute the pullback of "aff" by the function represented by "ma".
@@ -5521,7 +5643,7 @@ __isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
 {
 	isl_aff *res = NULL;
 	isl_local_space *ls;
-	int n_div_aff, n_div_ma;
+	isl_size n_div_aff, n_div_ma;
 	isl_int f, c1, c2, g;
 
 	ma = isl_multi_aff_align_divs(ma);
@@ -5530,6 +5652,8 @@ __isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
 
 	n_div_aff = isl_aff_dim(aff, isl_dim_div);
 	n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
+	if (n_div_aff < 0 || n_div_ma < 0)
+		goto error;
 
 	ls = isl_aff_get_domain_local_space(aff);
 	ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma));
@@ -5542,8 +5666,9 @@ __isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
 	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);
+	if (isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0,
+			    n_div_ma, n_div_aff, f, c1, c2, g, 1) < 0)
+		res = isl_aff_free(res);
 
 	isl_int_clear(f);
 	isl_int_clear(c1);
@@ -5579,15 +5704,14 @@ __isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
 
 /* 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_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
 	__isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
 {
 	int i;
 	isl_space *space = NULL;
 
+	isl_multi_aff_align_params_bin(&ma1, &ma2);
 	ma2 = isl_multi_aff_align_divs(ma2);
 	ma1 = isl_multi_aff_cow(ma1);
 	if (!ma1 || !ma2)
@@ -5613,16 +5737,6 @@ static __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff_aligned(
 	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".
  *
@@ -5633,7 +5747,7 @@ __isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst,
 	__isl_keep isl_aff *src)
 {
 	isl_ctx *ctx;
-	int src_n_div, dst_n_div;
+	isl_size src_n_div, dst_n_div;
 	int *exp1 = NULL;
 	int *exp2 = NULL;
 	isl_bool equal;
@@ -5650,16 +5764,16 @@ __isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst,
 		isl_die(ctx, isl_error_invalid,
 			"spaces don't match", goto error);
 
-	src_n_div = isl_local_space_dim(src->ls, isl_dim_div);
+	src_n_div = isl_aff_domain_dim(src, isl_dim_div);
+	dst_n_div = isl_aff_domain_dim(dst, isl_dim_div);
 	if (src_n_div == 0)
 		return dst;
 	equal = isl_local_space_is_equal(src->ls, dst->ls);
-	if (equal < 0)
+	if (equal < 0 || src_n_div < 0 || dst_n_div < 0)
 		return isl_aff_free(dst);
 	if (equal)
 		return dst;
 
-	dst_n_div = isl_local_space_dim(dst->ls, isl_dim_div);
 	exp1 = isl_alloc_array(ctx, int, src_n_div);
 	exp2 = isl_alloc_array(ctx, int, dst_n_div);
 	if (!exp1 || (dst_n_div && !exp2))
@@ -5727,7 +5841,7 @@ __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
 {
 	int i;
 	isl_space *space;
-	unsigned n_div;
+	isl_size n_div;
 
 	if (ls)
 		*ls = NULL;
@@ -5751,6 +5865,8 @@ __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
 		return NULL;
 
 	n_div = isl_aff_dim(maff->u.p[0], isl_dim_div);
+	if (n_div < 0)
+		return isl_multi_aff_free(maff);
 	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,
@@ -5779,6 +5895,10 @@ __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
 	return isl_multi_aff_free(maff);
 }
 
+#undef TYPE
+#define TYPE	isl_pw_multi_aff
+static
+#include "check_type_range_templ.c"
 
 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma".
  */
@@ -5786,17 +5906,16 @@ __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_size n_out;
 	isl_space *space;
 	isl_pw_aff *pa;
 
-	if (!pma)
+	if (isl_pw_multi_aff_check_range(pma, isl_dim_out, pos, 1) < 0)
 		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);
+	if (n_out < 0)
+		return NULL;
 
 	space = isl_pw_multi_aff_get_space(pma);
 	space = isl_space_drop_dims(space, isl_dim_out,
@@ -5935,35 +6054,27 @@ static __isl_give isl_union_pw_multi_aff *bin_op(
 /* 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_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_space *space;
 
+	isl_pw_multi_aff_align_params_bin(&pma1, &pma2);
 	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_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_space *space;
 
+	isl_pw_multi_aff_align_params_bin(&pma1, &pma2);
 	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);
@@ -5971,16 +6082,6 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_flat_range_product(
 					    &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 "pma2" have the same domain space, then compute
  * their flat range product and the result to data->res.
  */
@@ -6033,9 +6134,8 @@ static __isl_give isl_pw_multi_aff *pw_multi_aff_set_pw_aff(
 					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);
+	if (isl_pw_multi_aff_check_range(pma, isl_dim_out, pos, 1) < 0)
+		goto error;
 
 	n = pma->n * pa->n;
 	res = isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma), n);
@@ -6162,13 +6262,35 @@ isl_stat isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
 #include <isl_multi_explicit_domain.c>
 #include <isl_multi_pw_aff_explicit_domain.c>
 #include <isl_multi_templ.c>
+#include <isl_multi_add_constant_templ.c>
 #include <isl_multi_apply_set.c>
+#include <isl_multi_arith_templ.c>
+#include <isl_multi_bind_templ.c>
+#include <isl_multi_bind_domain_templ.c>
 #include <isl_multi_coalesce.c>
+#include <isl_multi_domain_templ.c>
+#include <isl_multi_dim_id_templ.c>
 #include <isl_multi_dims.c>
+#include <isl_multi_from_base_templ.c>
 #include <isl_multi_gist.c>
 #include <isl_multi_hash.c>
+#include <isl_multi_identity_templ.c>
 #include <isl_multi_align_set.c>
 #include <isl_multi_intersect.c>
+#include <isl_multi_move_dims_templ.c>
+#include <isl_multi_nan_templ.c>
+#include <isl_multi_param_templ.c>
+#include <isl_multi_product_templ.c>
+#include <isl_multi_splice_templ.c>
+#include <isl_multi_tuple_id_templ.c>
+#include <isl_multi_zero_templ.c>
+
+/* Are all elements of "mpa" piecewise constants?
+ */
+isl_bool isl_multi_pw_aff_is_cst(__isl_keep isl_multi_pw_aff *mpa)
+{
+	return isl_multi_pw_aff_every(mpa, &isl_pw_aff_is_cst);
+}
 
 /* Does "mpa" have a non-trivial explicit domain?
  *
@@ -6255,6 +6377,11 @@ static __isl_give isl_pw_multi_aff *union_pw_multi_aff_scale_multi_val_entry(
 __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_transform_control control = {
+		.fn = &union_pw_multi_aff_scale_multi_val_entry,
+		.fn_user = mv,
+	};
+
 	upma = isl_union_pw_multi_aff_align_params(upma,
 						isl_multi_val_get_space(mv));
 	mv = isl_multi_val_align_params(mv,
@@ -6262,8 +6389,7 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
 	if (!upma || !mv)
 		goto error;
 
-	return isl_union_pw_multi_aff_transform(upma,
-		       &union_pw_multi_aff_scale_multi_val_entry, mv);
+	return isl_union_pw_multi_aff_transform(upma, &control);
 
 	isl_multi_val_free(mv);
 	return upma;
@@ -6376,13 +6502,16 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
 	__isl_take isl_multi_aff *ma)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_multi_pw_aff *mpa;
 
+	n = isl_multi_aff_dim(ma, isl_dim_out);
+	if (n < 0)
+		ma = isl_multi_aff_free(ma);
 	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) {
@@ -6406,14 +6535,14 @@ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
 	__isl_take isl_pw_multi_aff *pma)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_multi_pw_aff *mpa;
 
-	if (!pma)
-		return NULL;
-
 	n = isl_pw_multi_aff_dim(pma, isl_dim_out);
+	if (n < 0)
+		pma = isl_pw_multi_aff_free(pma);
 	space = isl_pw_multi_aff_get_space(pma);
 	mpa = isl_multi_pw_aff_alloc(space);
 
@@ -6712,7 +6841,8 @@ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_pw_multi_aff(
 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_in, n_div;
+	int i;
+	isl_size n_in, n_div, n_mpa_in;
 	isl_space *space;
 	isl_val *v;
 	isl_pw_aff *pa;
@@ -6720,13 +6850,15 @@ static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned(
 
 	n_in = isl_aff_dim(aff, isl_dim_in);
 	n_div = isl_aff_dim(aff, isl_dim_div);
+	n_mpa_in = isl_multi_pw_aff_dim(mpa, isl_dim_in);
+	if (n_in < 0 || n_div < 0 || n_mpa_in < 0)
+		goto error;
 
 	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_add_dims(tmp, isl_dim_in, n_mpa_in);
 	tmp = isl_aff_reset_domain_space(tmp, space);
 	pa = isl_pw_aff_from_aff(tmp);
 
@@ -6760,6 +6892,10 @@ static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned(
 	isl_aff_free(aff);
 
 	return pa;
+error:
+	isl_multi_pw_aff_free(mpa);
+	isl_aff_free(aff);
+	return NULL;
 }
 
 /* Apply "aff" to "mpa".  The range of "mpa" needs to be compatible
@@ -6895,13 +7031,13 @@ __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
  * If "mpa1" has an explicit domain, then it is this domain
  * that needs to undergo a pullback instead, i.e., a preimage.
  */
-static __isl_give isl_multi_pw_aff *
-isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
+__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)
 {
 	int i;
 	isl_space *space = NULL;
 
+	isl_multi_pw_aff_align_params_bin(&mpa1, &mpa2);
 	mpa1 = isl_multi_pw_aff_cow(mpa1);
 	if (!mpa1 || !mpa2)
 		goto error;
@@ -6933,16 +7069,6 @@ isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
 	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);
-}
-
 /* Align the parameters of "mpa1" and "mpa2", check that the ranges
  * of "mpa1" and "mpa2" live in the same space, construct map space
  * between the domain spaces of "mpa1" and "mpa2" and call "order"
@@ -6995,12 +7121,15 @@ static __isl_give isl_map *isl_multi_pw_aff_eq_map_on_space(
 	__isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
 	__isl_take isl_space *space)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_map *res;
 
+	n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
+	if (n < 0)
+		space = isl_space_free(space);
 	res = isl_map_universe(space);
 
-	n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
 	for (i = 0; i < n; ++i) {
 		isl_pw_aff *pa1, *pa2;
 		isl_map *map;
@@ -7025,7 +7154,7 @@ __isl_give isl_map *isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff *mpa1,
 }
 
 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
- * where the function values of "mpa1" is lexicographically satisfies "base"
+ * where the function values of "mpa1" lexicographically satisfies "base"
  * compared to that of "mpa2".  "space" is the space of the result.
  * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
  *
@@ -7040,13 +7169,16 @@ static __isl_give isl_map *isl_multi_pw_aff_lex_map_on_space(
 		__isl_take isl_pw_aff *pa2),
 	__isl_take isl_space *space)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_map *res, *rest;
 
+	n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
+	if (n < 0)
+		space = isl_space_free(space);
 	res = isl_map_empty(isl_space_copy(space));
 	rest = isl_map_universe(space);
 
-	n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
 	for (i = 0; i < n; ++i) {
 		isl_pw_aff *pa1, *pa2;
 		isl_map *map;
@@ -7216,21 +7348,39 @@ __isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
 	return isl_pw_aff_alloc(domain, aff);
 }
 
+/* Return a piecewise affine expression that is equal to the parameter
+ * with identifier "id" on "domain".
+ */
+__isl_give isl_pw_aff *isl_pw_aff_param_on_domain_id(
+	__isl_take isl_set *domain, __isl_take isl_id *id)
+{
+	isl_space *space;
+	isl_aff *aff;
+
+	space = isl_set_get_space(domain);
+	space = isl_space_add_param_id(space, isl_id_copy(id));
+	domain = isl_set_align_params(domain, isl_space_copy(space));
+	aff = isl_aff_param_on_domain_space_id(space, id);
+
+	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;
+	int i;
+	isl_size n;
 	isl_space *space2;
 	isl_local_space *ls;
 	isl_multi_aff *ma;
 
-	if (!space || !mv)
+	n = isl_multi_val_dim(mv, isl_dim_set);
+	if (!space || n < 0)
 		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));
@@ -7528,13 +7678,12 @@ struct isl_union_pw_multi_aff_get_union_pw_aff_data {
 static isl_stat get_union_pw_aff(__isl_take isl_pw_multi_aff *pma, void *user)
 {
 	struct isl_union_pw_multi_aff_get_union_pw_aff_data *data = user;
-	int n_out;
+	isl_size n_out;
 	isl_pw_aff *pa;
 
-	if (!pma)
-		return isl_stat_error;
-
 	n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
+	if (n_out < 0)
+		return isl_stat_error;
 	if (data->pos >= n_out) {
 		isl_pw_multi_aff_free(pma);
 		return isl_stat_ok;
@@ -7621,10 +7770,12 @@ static isl_stat pw_aff_on_domain(__isl_take isl_set *domain, void *user)
 {
 	struct isl_union_pw_aff_pw_aff_on_domain_data *data = user;
 	isl_pw_aff *pa;
-	int dim;
+	isl_size dim;
 
 	pa = isl_pw_aff_copy(data->pa);
 	dim = isl_set_dim(domain, isl_dim_set);
+	if (dim < 0)
+		pa = isl_pw_aff_free(pa);
 	pa = isl_pw_aff_from_range(pa);
 	pa = isl_pw_aff_add_dims(pa, isl_dim_in, dim);
 	pa = isl_pw_aff_reset_domain_space(pa, isl_set_get_space(domain));
@@ -7815,6 +7966,48 @@ __isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
 	return zero;
 }
 
+/* Internal data structure for isl_union_pw_aff_bind_id,
+ * storing the parameter that needs to be bound and
+ * the accumulated results.
+ */
+struct isl_bind_id_data {
+	isl_id *id;
+	isl_union_set *bound;
+};
+
+/* Bind the piecewise affine function "pa" to the parameter data->id,
+ * adding the resulting elements in the domain where the expression
+ * is equal to the parameter to data->bound.
+ */
+static isl_stat bind_id(__isl_take isl_pw_aff *pa, void *user)
+{
+	struct isl_bind_id_data *data = user;
+	isl_set *bound;
+
+	bound = isl_pw_aff_bind_id(pa, isl_id_copy(data->id));
+	data->bound = isl_union_set_add_set(data->bound, bound);
+
+	return data->bound ? isl_stat_ok : isl_stat_error;
+}
+
+/* Bind the union piecewise affine function "upa" to the parameter "id",
+ * returning the elements in the domain where the expression
+ * is equal to the parameter.
+ */
+__isl_give isl_union_set *isl_union_pw_aff_bind_id(
+	__isl_take isl_union_pw_aff *upa, __isl_take isl_id *id)
+{
+	struct isl_bind_id_data data = { id };
+
+	data.bound = isl_union_set_empty(isl_union_pw_aff_get_space(upa));
+	if (isl_union_pw_aff_foreach_pw_aff(upa, &bind_id, &data) < 0)
+		data.bound = isl_union_set_free(data.bound);
+
+	isl_union_pw_aff_free(upa);
+	isl_id_free(id);
+	return data.bound;
+}
+
 /* Internal data structure for isl_union_pw_aff_pullback_union_pw_multi_aff.
  * upma is the function that is plugged in.
  * pa is the current part of the function in which upma is plugged in.
@@ -7908,24 +8101,23 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
 #undef DOMBASE
 #define DOMBASE union_set
 
-#define NO_MOVE_DIMS
-#define NO_DOMAIN
-#define NO_PRODUCT
-#define NO_SPLICE
-#define NO_ZERO
-#define NO_IDENTITY
-
 #include <isl_multi_explicit_domain.c>
 #include <isl_multi_union_pw_aff_explicit_domain.c>
 #include <isl_multi_templ.c>
 #include <isl_multi_apply_set.c>
 #include <isl_multi_apply_union_set.c>
+#include <isl_multi_arith_templ.c>
+#include <isl_multi_bind_templ.c>
 #include <isl_multi_coalesce.c>
+#include <isl_multi_dim_id_templ.c>
 #include <isl_multi_floor.c>
+#include <isl_multi_from_base_templ.c>
 #include <isl_multi_gist.c>
 #include <isl_multi_align_set.c>
 #include <isl_multi_align_union_set.c>
 #include <isl_multi_intersect.c>
+#include <isl_multi_nan_templ.c>
+#include <isl_multi_tuple_id_templ.c>
 
 /* Does "mupa" have a non-trivial explicit domain?
  *
@@ -7962,6 +8154,7 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero(
 	__isl_take isl_space *space)
 {
 	isl_bool params;
+	isl_size dim;
 
 	if (!space)
 		return NULL;
@@ -7975,7 +8168,10 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero(
 	if (!isl_space_is_set(space))
 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
 			"expecting set space", goto error);
-	if (isl_space_dim(space , isl_dim_out) != 0)
+	dim = isl_space_dim(space, isl_dim_out);
+	if (dim < 0)
+		goto error;
+	if (dim != 0)
 		isl_die(isl_space_get_ctx(space), isl_error_invalid,
 			"expecting 0D space", goto error);
 
@@ -8001,13 +8197,13 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero(
  * on its explicit domain, then this is allowed as well and the result
  * is the expression with no constraints on its explicit domain.
  */
-static __isl_give isl_multi_union_pw_aff *
-isl_multi_union_pw_aff_union_add_aligned(
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
 	__isl_take isl_multi_union_pw_aff *mupa1,
 	__isl_take isl_multi_union_pw_aff *mupa2)
 {
 	isl_bool has_domain, is_params1, is_params2;
 
+	isl_multi_union_pw_aff_align_params_bin(&mupa1, &mupa2);
 	if (isl_multi_union_pw_aff_check_equal_space(mupa1, mupa2) < 0)
 		goto error;
 	if (mupa1->n > 0)
@@ -8056,18 +8252,6 @@ isl_multi_union_pw_aff_union_add_aligned(
 	return NULL;
 }
 
-/* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
- * with the actual sum on the shared domain and
- * the defined expression on the symmetric 
diff erence of the domains.
- */
-__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
-	__isl_take isl_multi_union_pw_aff *mupa1,
-	__isl_take isl_multi_union_pw_aff *mupa2)
-{
-	return isl_multi_union_pw_aff_align_params_multi_multi_and(mupa1, mupa2,
-				    &isl_multi_union_pw_aff_union_add_aligned);
-}
-
 /* Construct and return a multi union piecewise affine expression
  * that is equal to the given multi affine expression.
  */
@@ -8086,10 +8270,14 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
 	__isl_take isl_multi_pw_aff *mpa)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_multi_union_pw_aff *mupa;
 
+	n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
+	if (n < 0)
+		mpa = isl_multi_pw_aff_free(mpa);
 	if (!mpa)
 		return NULL;
 
@@ -8097,7 +8285,6 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
 	space = isl_space_range(space);
 	mupa = isl_multi_union_pw_aff_alloc(space);
 
-	n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
 	for (i = 0; i < n; ++i) {
 		isl_pw_aff *pa;
 		isl_union_pw_aff *upa;
@@ -8159,11 +8346,13 @@ isl_multi_union_pw_aff_from_union_pw_multi_aff(
 {
 	isl_space *space = NULL;
 	isl_multi_union_pw_aff *mupa;
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!upma)
-		return NULL;
-	if (isl_union_pw_multi_aff_n_pw_multi_aff(upma) == 0)
+	n = isl_union_pw_multi_aff_n_pw_multi_aff(upma);
+	if (n < 0)
+		goto error;
+	if (n == 0)
 		isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
 			"cannot extract range space from empty input",
 			goto error);
@@ -8175,6 +8364,8 @@ isl_multi_union_pw_aff_from_union_pw_multi_aff(
 		goto error;
 
 	n = isl_space_dim(space, isl_dim_set);
+	if (n < 0)
+		space = isl_space_free(space);
 	mupa = isl_multi_union_pw_aff_alloc(space);
 
 	for (i = 0; i < n; ++i) {
@@ -8227,14 +8418,15 @@ static __isl_give isl_multi_union_pw_aff *
 isl_multi_union_pw_aff_multi_val_on_domain_aligned(
 	__isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_multi_union_pw_aff *mupa;
 
-	if (!domain || !mv)
+	n = isl_multi_val_dim(mv, isl_dim_set);
+	if (!domain || n < 0)
 		goto error;
 
-	n = isl_multi_val_dim(mv, isl_dim_set);
 	space = isl_multi_val_get_space(mv);
 	mupa = isl_multi_union_pw_aff_alloc(space);
 	for (i = 0; i < n; ++i) {
@@ -8309,14 +8501,14 @@ static __isl_give isl_multi_union_pw_aff *
 isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(
 	__isl_take isl_union_set *domain, __isl_take isl_pw_multi_aff *pma)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_multi_union_pw_aff *mupa;
 
-	if (!domain || !pma)
-		goto error;
-
 	n = isl_pw_multi_aff_dim(pma, isl_dim_set);
+	if (!domain || n < 0)
+		goto error;
 	space = isl_pw_multi_aff_get_space(pma);
 	mupa = isl_multi_union_pw_aff_alloc(space);
 	for (i = 0; i < n; ++i) {
@@ -8378,14 +8570,17 @@ isl_multi_union_pw_aff_pw_multi_aff_on_domain(__isl_take isl_union_set *domain,
 __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
 	__isl_take isl_multi_union_pw_aff *mupa)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_union_pw_aff *upa;
 	isl_union_set *zero;
 
+	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	if (n < 0)
+		mupa = isl_multi_union_pw_aff_free(mupa);
 	if (!mupa)
 		return NULL;
 
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	if (n == 0)
 		return isl_multi_union_pw_aff_domain(mupa);
 
@@ -8447,15 +8642,18 @@ static __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff_0D(
 __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
 	__isl_take isl_multi_union_pw_aff *mupa)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_union_map *umap;
 	isl_union_pw_aff *upa;
 
+	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	if (n < 0)
+		mupa = isl_multi_union_pw_aff_free(mupa);
 	if (!mupa)
 		return NULL;
 
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	if (n == 0)
 		return isl_union_map_from_multi_union_pw_aff_0D(mupa);
 
@@ -8565,15 +8763,18 @@ __isl_give isl_union_pw_multi_aff *
 isl_union_pw_multi_aff_from_multi_union_pw_aff(
 	__isl_take isl_multi_union_pw_aff *mupa)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_union_pw_multi_aff *upma;
 	isl_union_pw_aff *upa;
 
+	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	if (n < 0)
+		mupa = isl_multi_union_pw_aff_free(mupa);
 	if (!mupa)
 		return NULL;
 
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	if (n == 0)
 		return isl_union_pw_multi_aff_from_multi_union_pw_aff_0D(mupa);
 
@@ -8619,10 +8820,11 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
 	isl_union_pw_multi_aff *upma;
 	isl_union_set *domain;
 	isl_space *space;
-	int n;
+	isl_size n;
 	int match;
 
-	if (!mupa || !range)
+	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	if (n < 0 || !range)
 		goto error;
 
 	space = isl_set_get_space(range);
@@ -8634,7 +8836,6 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
 	if (!match)
 		isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
 			"space don't match", goto error);
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	if (n == 0)
 		return mupa_intersect_range_0D(mupa, range);
 
@@ -8677,14 +8878,17 @@ __isl_give isl_union_set *isl_multi_union_pw_aff_domain_0D(
 __isl_give isl_union_set *isl_multi_union_pw_aff_domain(
 	__isl_take isl_multi_union_pw_aff *mupa)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_union_pw_aff *upa;
 	isl_union_set *dom;
 
+	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	if (n < 0)
+		mupa = isl_multi_union_pw_aff_free(mupa);
 	if (!mupa)
 		return NULL;
 
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	if (n == 0)
 		return isl_multi_union_pw_aff_domain_0D(mupa);
 
@@ -8717,7 +8921,8 @@ __isl_give isl_union_set *isl_multi_union_pw_aff_domain(
 static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
 	__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
 {
-	int i, n_in, n_div;
+	int i;
+	isl_size n_in, n_div;
 	isl_union_pw_aff *upa;
 	isl_union_set *uset;
 	isl_val *v;
@@ -8725,6 +8930,8 @@ static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
 
 	n_in = isl_aff_dim(aff, isl_dim_in);
 	n_div = isl_aff_dim(aff, isl_dim_div);
+	if (n_in < 0 || n_div < 0)
+		goto error;
 
 	uset = isl_multi_union_pw_aff_domain(isl_multi_union_pw_aff_copy(mupa));
 	cst = isl_aff_copy(aff);
@@ -8763,6 +8970,10 @@ static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
 	isl_aff_free(aff);
 
 	return upa;
+error:
+	isl_multi_union_pw_aff_free(mupa);
+	isl_aff_free(aff);
+	return NULL;
 }
 
 /* Apply "aff" to "mupa".  The space of "mupa" needs to be compatible
@@ -8776,8 +8987,9 @@ static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
 	__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
 {
+	isl_size dim;
 	isl_space *space1, *space2;
-	int equal;
+	isl_bool equal;
 
 	mupa = isl_multi_union_pw_aff_align_params(mupa,
 						isl_aff_get_space(aff));
@@ -8795,7 +9007,10 @@ __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
 	if (!equal)
 		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
 			"spaces don't match", goto error);
-	if (isl_aff_dim(aff, isl_dim_in) == 0)
+	dim = isl_aff_dim(aff, isl_dim_in);
+	if (dim < 0)
+		goto error;
+	if (dim == 0)
 		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
 			"cannot determine domains", goto error);
 
@@ -8832,14 +9047,17 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
 {
 	isl_space *space1, *space2;
 	isl_multi_union_pw_aff *res;
-	int equal;
-	int i, n_out;
+	isl_bool equal;
+	int i;
+	isl_size n_in, n_out;
 
 	mupa = isl_multi_union_pw_aff_align_params(mupa,
 						isl_multi_aff_get_space(ma));
 	ma = isl_multi_aff_align_params(ma,
 					isl_multi_union_pw_aff_get_space(mupa));
-	if (!mupa || !ma)
+	n_in = isl_multi_aff_dim(ma, isl_dim_in);
+	n_out = isl_multi_aff_dim(ma, isl_dim_out);
+	if (!mupa || n_in < 0 || n_out < 0)
 		goto error;
 
 	space1 = isl_multi_union_pw_aff_get_space(mupa);
@@ -8852,8 +9070,7 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
 	if (!equal)
 		isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
 			"spaces don't match", goto error);
-	n_out = isl_multi_aff_dim(ma, isl_dim_out);
-	if (isl_multi_aff_dim(ma, isl_dim_in) == 0)
+	if (n_in == 0)
 		return mupa_apply_multi_aff_0D(mupa, ma);
 
 	space1 = isl_space_range(isl_multi_aff_get_space(ma));
@@ -8904,7 +9121,8 @@ __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff(
 	__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa)
 {
 	int i;
-	int equal;
+	isl_bool equal;
+	isl_size n_in;
 	isl_space *space, *space2;
 	isl_union_pw_aff *upa;
 
@@ -8925,7 +9143,10 @@ __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff(
 	if (!equal)
 		isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
 			"spaces don't match", goto error);
-	if (isl_pw_aff_dim(pa, isl_dim_in) == 0)
+	n_in = isl_pw_aff_dim(pa, isl_dim_in);
+	if (n_in < 0)
+		goto error;
+	if (n_in == 0)
 		return isl_multi_union_pw_aff_apply_pw_aff_0D(mupa, pa);
 
 	space = isl_space_params(isl_multi_union_pw_aff_get_space(mupa));
@@ -8982,8 +9203,9 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
 {
 	isl_space *space1, *space2;
 	isl_multi_union_pw_aff *res;
-	int equal;
-	int i, n_out;
+	isl_bool equal;
+	int i;
+	isl_size n_in, n_out;
 
 	mupa = isl_multi_union_pw_aff_align_params(mupa,
 					isl_pw_multi_aff_get_space(pma));
@@ -9002,8 +9224,11 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
 	if (!equal)
 		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
 			"spaces don't match", goto error);
+	n_in = isl_pw_multi_aff_dim(pma, isl_dim_in);
 	n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
-	if (isl_pw_multi_aff_dim(pma, isl_dim_in) == 0)
+	if (n_in < 0 || n_out < 0)
+		goto error;
+	if (n_in == 0)
 		return mupa_apply_pw_multi_aff_0D(mupa, pma);
 
 	space1 = isl_space_range(isl_pw_multi_aff_get_space(pma));
@@ -9075,17 +9300,18 @@ isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
 	__isl_take isl_multi_union_pw_aff *mupa,
 	__isl_take isl_union_pw_multi_aff *upma)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	mupa = isl_multi_union_pw_aff_align_params(mupa,
 				    isl_union_pw_multi_aff_get_space(upma));
 	upma = isl_union_pw_multi_aff_align_params(upma,
 				    isl_multi_union_pw_aff_get_space(mupa));
 	mupa = isl_multi_union_pw_aff_cow(mupa);
-	if (!mupa || !upma)
+	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	if (n < 0 || !upma)
 		goto error;
 
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	for (i = 0; i < n; ++i) {
 		isl_union_pw_aff *upa;
 
@@ -9115,11 +9341,13 @@ isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
 __isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
 	__isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space_mpa;
 	isl_multi_pw_aff *mpa;
 
-	if (!mupa || !space)
+	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	if (n < 0 || !space)
 		goto error;
 
 	space_mpa = isl_multi_union_pw_aff_get_space(mupa);
@@ -9130,7 +9358,6 @@ __isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
 
 	space = isl_space_from_domain(space);
 	space = isl_space_add_dims(space, isl_dim_out, 1);
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	for (i = 0; i < n; ++i) {
 		isl_union_pw_aff *upa;
 		isl_pw_aff *pa;
@@ -9149,6 +9376,79 @@ __isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
 	return NULL;
 }
 
+/* Data structure that specifies how isl_union_pw_multi_aff_un_op
+ * should modify the base expressions in the input.
+ *
+ * If "filter" is not NULL, then only the base expressions that satisfy "filter"
+ * are taken into account.
+ * "fn" is applied to each entry in the input.
+ */
+struct isl_union_pw_multi_aff_un_op_control {
+	isl_bool (*filter)(__isl_keep isl_pw_multi_aff *part);
+	__isl_give isl_pw_multi_aff *(*fn)(__isl_take isl_pw_multi_aff *pma);
+};
+
+/* Wrapper for isl_union_pw_multi_aff_un_op base functions (which do not take
+ * a second argument) for use as an isl_union_pw_multi_aff_transform
+ * base function (which does take a second argument).
+ * Simply call control->fn without the second argument.
+ */
+static __isl_give isl_pw_multi_aff *isl_union_pw_multi_aff_un_op_drop_user(
+	__isl_take isl_pw_multi_aff *pma, void *user)
+{
+	struct isl_union_pw_multi_aff_un_op_control *control = user;
+
+	return control->fn(pma);
+}
+
+/* Construct an isl_union_pw_multi_aff that is obtained by
+ * modifying "upma" according to "control".
+ *
+ * isl_union_pw_multi_aff_transform performs essentially
+ * the same operation, but takes a callback function
+ * of a 
diff erent form (with an extra argument).
+ * Call isl_union_pw_multi_aff_transform with a wrapper
+ * that removes this extra argument.
+ */
+static __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_un_op(
+	__isl_take isl_union_pw_multi_aff *upma,
+	struct isl_union_pw_multi_aff_un_op_control *control)
+{
+	struct isl_union_pw_multi_aff_transform_control t_control = {
+		.filter = control->filter,
+		.fn = &isl_union_pw_multi_aff_un_op_drop_user,
+		.fn_user = control,
+	};
+
+	return isl_union_pw_multi_aff_transform(upma, &t_control);
+}
+
+/* For each function in "upma" of the form A -> [B -> C],
+ * extract the function A -> B and collect the results.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_range_factor_domain(
+	__isl_take isl_union_pw_multi_aff *upma)
+{
+	struct isl_union_pw_multi_aff_un_op_control control = {
+		.filter = &isl_pw_multi_aff_range_is_wrapping,
+		.fn = &isl_pw_multi_aff_range_factor_domain,
+	};
+	return isl_union_pw_multi_aff_un_op(upma, &control);
+}
+
+/* For each function in "upma" of the form A -> [B -> C],
+ * extract the function A -> C and collect the results.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_range_factor_range(
+	__isl_take isl_union_pw_multi_aff *upma)
+{
+	struct isl_union_pw_multi_aff_un_op_control control = {
+		.filter = &isl_pw_multi_aff_range_is_wrapping,
+		.fn = &isl_pw_multi_aff_range_factor_range,
+	};
+	return isl_union_pw_multi_aff_un_op(upma, &control);
+}
+
 /* Evaluate the affine function "aff" in the void point "pnt".
  * In particular, return the value NaN.
  */

diff  --git a/polly/lib/External/isl/isl_aff_map.c b/polly/lib/External/isl/isl_aff_map.c
index 2031090292ec..0228bd337bea 100644
--- a/polly/lib/External/isl/isl_aff_map.c
+++ b/polly/lib/External/isl/isl_aff_map.c
@@ -132,13 +132,15 @@ __isl_give isl_basic_map *isl_basic_map_from_multi_aff2(
 	__isl_take isl_multi_aff *maff, int rational)
 {
 	int i;
+	isl_size dim;
 	isl_space *space;
 	isl_basic_map *bmap;
 
-	if (!maff)
-		return NULL;
+	dim = isl_multi_aff_dim(maff, isl_dim_out);
+	if (dim < 0)
+		goto error;
 
-	if (isl_space_dim(maff->space, isl_dim_out) != maff->n)
+	if (dim != maff->n)
 		isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal,
 			"invalid space", goto error);
 
@@ -198,7 +200,7 @@ __isl_give isl_basic_set *isl_basic_set_from_multi_aff(
 {
 	if (check_input_is_set(isl_multi_aff_peek_space(ma)) < 0)
 		ma = isl_multi_aff_free(ma);
-	return bset_from_bmap(isl_basic_map_from_multi_aff(ma));
+	return bset_from_bmap(basic_map_from_multi_aff(ma));
 }
 
 /* Construct a map mapping the domain of the multi-affine expression
@@ -377,11 +379,13 @@ static __isl_give isl_map *map_from_multi_pw_aff(
 	__isl_take isl_multi_pw_aff *mpa)
 {
 	int i;
+	isl_size dim;
 	isl_space *space;
 	isl_map *map;
 
-	if (!mpa)
-		return NULL;
+	dim = isl_multi_pw_aff_dim(mpa, isl_dim_out);
+	if (dim < 0)
+		goto error;
 
 	if (isl_space_dim(mpa->space, isl_dim_out) != mpa->n)
 		isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,

diff  --git a/polly/lib/External/isl/isl_aff_private.h b/polly/lib/External/isl/isl_aff_private.h
index 6ef3d4a39e7c..e1f25e97c439 100644
--- a/polly/lib/External/isl/isl_aff_private.h
+++ b/polly/lib/External/isl/isl_aff_private.h
@@ -76,6 +76,9 @@ __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_size isl_aff_domain_dim(__isl_keep isl_aff *aff, enum isl_dim_type type);
+isl_size isl_aff_domain_offset(__isl_keep isl_aff *aff, enum isl_dim_type type);
+
 __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,
@@ -107,6 +110,9 @@ __isl_give isl_pw_aff *isl_pw_aff_reset_domain_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_domain_factor_domain(
+	__isl_take isl_pw_aff *pa);
+
 __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
 	__isl_take isl_pw_aff *pwaff2, int max);
 
@@ -146,6 +152,11 @@ __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat(
 
 #include <isl_list_templ.h>
 
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_move_dims(
+	__isl_take isl_pw_multi_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_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(
@@ -157,7 +168,7 @@ __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_preimage(isl_int *dst, isl_int *src,
+isl_stat 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);
@@ -169,6 +180,7 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
 	__isl_keep isl_pw_aff *subs);
 
 isl_stat isl_pw_aff_check_named_params(__isl_keep isl_pw_aff *pa);
+isl_stat isl_multi_aff_check_named_params(__isl_keep isl_multi_aff *ma);
 isl_stat isl_pw_multi_aff_check_named_params(__isl_keep isl_pw_multi_aff *pma);
 
 isl_bool isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,

diff  --git a/polly/lib/External/isl/isl_affine_hull.c b/polly/lib/External/isl/isl_affine_hull.c
index a60a34c14870..c013e6792fad 100644
--- a/polly/lib/External/isl/isl_affine_hull.c
+++ b/polly/lib/External/isl/isl_affine_hull.c
@@ -114,18 +114,21 @@ static void delete_row(struct isl_basic_set *bset, unsigned row)
  * 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,
+static isl_stat construct_column(
+	__isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
 	unsigned row, unsigned col)
 {
 	int r;
 	isl_int a;
 	isl_int b;
-	unsigned total;
+	isl_size total;
+
+	total = isl_basic_set_dim(bset1, isl_dim_set);
+	if (total < 0)
+		return isl_stat_error;
 
 	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;
@@ -133,12 +136,14 @@ static void construct_column(
 		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);
+					      b, bset1->eq[row], 1 + total);
+		isl_seq_scale(bset2->eq[r], bset2->eq[r], a, 1 + total);
 	}
 	isl_int_clear(a);
 	isl_int_clear(b);
 	delete_row(bset1, row);
+
+	return isl_stat_ok;
 }
 
 /* Make first row entries in column col of bset1 identical to
@@ -150,21 +155,23 @@ static void construct_column(
  * 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,
+static isl_bool transform_column(
+	__isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
 	unsigned row, unsigned col)
 {
 	int i, t;
 	isl_int a, b, g;
-	unsigned total;
+	isl_size 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;
+		return isl_bool_false;
 
-	total = 1 + isl_basic_set_n_dim(bset1);
+	total = isl_basic_set_dim(bset1, isl_dim_set);
+	if (total < 0)
+		return isl_bool_error;
 	isl_int_init(a);
 	isl_int_init(b);
 	isl_int_init(g);
@@ -175,16 +182,16 @@ static int transform_column(
 		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);
+				1 + total);
 		isl_seq_combine(bset2->eq[i], g, bset2->eq[i], a, bset2->eq[t],
-				total);
+				1 + total);
 	}
 	isl_int_clear(a);
 	isl_int_clear(b);
 	isl_int_clear(g);
 	delete_row(bset1, t);
 	delete_row(bset2, t);
-	return 1;
+	return isl_bool_true;
 }
 
 /* The implementation is based on Section 5.2 of Michael Karr,
@@ -192,17 +199,19 @@ static int transform_column(
  * 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)
+static __isl_give isl_basic_set *affine_hull(
+	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
 {
+	isl_size dim;
 	unsigned total;
 	int col;
 	int row;
 
-	if (!bset1 || !bset2)
+	dim = isl_basic_set_dim(bset1, isl_dim_set);
+	if (dim < 0 || !bset2)
 		goto error;
 
-	total = 1 + isl_basic_set_n_dim(bset1);
+	total = 1 + dim;
 
 	row = 0;
 	for (col = total-1; col >= 0; --col) {
@@ -214,11 +223,18 @@ static struct isl_basic_set *affine_hull(
 			set_common_multiple(bset1, bset2, row, col);
 			++row;
 		} else if (!is_zero1 && is_zero2) {
-			construct_column(bset1, bset2, row, col);
+			if (construct_column(bset1, bset2, row, col) < 0)
+				goto error;
 		} else if (is_zero1 && !is_zero2) {
-			construct_column(bset2, bset1, row, col);
+			if (construct_column(bset2, bset1, row, col) < 0)
+				goto error;
 		} else {
-			if (transform_column(bset1, bset2, row, col))
+			isl_bool transform;
+
+			transform = transform_column(bset1, bset2, row, col);
+			if (transform < 0)
+				goto error;
+			if (transform)
 				--row;
 		}
 	}
@@ -301,11 +317,17 @@ __isl_give isl_basic_set *isl_basic_set_recession_cone(
 	__isl_take isl_basic_set *bset)
 {
 	int i;
+	isl_bool empty;
+
+	empty = isl_basic_set_plain_is_empty(bset);
+	if (empty < 0)
+		return isl_basic_set_free(bset);
+	if (empty)
+		return bset;
 
 	bset = isl_basic_set_cow(bset);
-	if (!bset)
-		return NULL;
-	isl_assert(bset->ctx, bset->n_div == 0, goto error);
+	if (isl_basic_set_check_no_locals(bset) < 0)
+		return isl_basic_set_free(bset);
 
 	for (i = 0; i < bset->n_eq; ++i)
 		isl_int_set_si(bset->eq[i][0], 0);
@@ -315,9 +337,6 @@ __isl_give isl_basic_set *isl_basic_set_recession_cone(
 
 	ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
 	return isl_basic_set_implicit_equalities(bset);
-error:
-	isl_basic_set_free(bset);
-	return NULL;
 }
 
 /* Move "sample" to a point that is one up (or down) from the original
@@ -343,12 +362,11 @@ static __isl_give isl_basic_set *add_adjacent_points(
 	__isl_keep isl_basic_set *bset)
 {
 	int i, up;
-	int dim;
-
-	if (!sample)
-		goto error;
+	isl_size dim;
 
 	dim = isl_basic_set_dim(hull, isl_dim_set);
+	if (!sample || dim < 0)
+		goto error;
 
 	for (i = 0; i < dim; ++i) {
 		for (up = 0; up <= 1; ++up) {
@@ -476,17 +494,20 @@ static __isl_give isl_basic_set *initialize_hull(__isl_keep isl_basic_set *bset,
  * 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)
+static __isl_give isl_basic_set *uset_affine_hull_bounded(
+	__isl_take isl_basic_set *bset)
 {
 	struct isl_vec *sample = NULL;
 	struct isl_basic_set *hull;
 	struct isl_tab *tab = NULL;
-	unsigned dim;
+	isl_size dim;
 
 	if (isl_basic_set_plain_is_empty(bset))
 		return bset;
 
-	dim = isl_basic_set_n_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		return isl_basic_set_free(bset);
 
 	if (bset->sample && bset->sample->size == 1 + dim) {
 		int contains = isl_basic_set_contains(bset, bset->sample);
@@ -557,7 +578,7 @@ static __isl_give isl_basic_set *initial_hull(struct isl_tab *tab,
 	int k;
 	struct isl_basic_set *bset = NULL;
 	struct isl_ctx *ctx;
-	unsigned dim;
+	isl_size dim;
 
 	if (!vec || !tab)
 		return NULL;
@@ -565,9 +586,10 @@ static __isl_give isl_basic_set *initial_hull(struct isl_tab *tab,
 	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)
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
 		goto error;
-	dim = isl_basic_set_n_dim(bset) - tab->n_unbounded;
+	dim -= tab->n_unbounded;
 	for (i = 0; i < dim; ++i) {
 		k = isl_basic_set_alloc_equality(bset);
 		if (k < 0)
@@ -707,15 +729,15 @@ struct isl_tab *isl_tab_detect_equalities(struct isl_tab *tab,
 static struct isl_basic_set *affine_hull_with_cone(struct isl_basic_set *bset,
 	struct isl_basic_set *cone)
 {
-	unsigned total;
+	isl_size total;
 	unsigned cone_dim;
 	struct isl_basic_set *hull;
 	struct isl_mat *M, *U, *Q;
 
-	if (!bset || !cone)
+	total = isl_basic_set_dim(cone, isl_dim_all);
+	if (!bset || total < 0)
 		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);
@@ -785,6 +807,7 @@ static struct isl_basic_set *affine_hull_with_cone(struct isl_basic_set *bset,
 static struct isl_basic_set *uset_affine_hull(struct isl_basic_set *bset)
 {
 	struct isl_basic_set *cone;
+	isl_size total;
 
 	if (isl_basic_set_plain_is_empty(bset))
 		return bset;
@@ -800,7 +823,10 @@ static struct isl_basic_set *uset_affine_hull(struct isl_basic_set *bset)
 		return isl_basic_set_universe(space);
 	}
 
-	if (cone->n_eq < isl_basic_set_total_dim(cone))
+	total = isl_basic_set_dim(cone, isl_dim_all);
+	if (total < 0)
+		bset = isl_basic_set_free(bset);
+	if (cone->n_eq < total)
 		return affine_hull_with_cone(bset, cone);
 
 	isl_basic_set_free(cone);
@@ -876,6 +902,7 @@ __isl_give isl_basic_map *isl_basic_map_detect_equalities(
 	__isl_take isl_basic_map *bmap)
 {
 	int i, j;
+	isl_size total;
 	struct isl_basic_set *hull = NULL;
 
 	if (!bmap)
@@ -896,14 +923,15 @@ __isl_give isl_basic_map *isl_basic_map_detect_equalities(
 		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);
+	bmap = isl_basic_map_extend(bmap, 0, hull->n_eq, 0);
+	total = isl_basic_set_dim(hull, isl_dim_all);
+	if (total < 0)
+		goto error;
 	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_seq_cpy(bmap->eq[j], hull->eq[i], 1 + total);
 	}
 	isl_vec_free(bmap->sample);
 	bmap->sample = isl_vec_copy(hull->sample);
@@ -1001,8 +1029,7 @@ static __isl_give isl_basic_map *add_strides(__isl_take isl_basic_map *bmap,
 	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);
+	bmap = isl_basic_map_extend(bmap, M->n_row - 1, M->n_row - 1, 0);
 
 	isl_int_init(gcd);
 	for (i = 1; i < M->n_row; ++i) {
@@ -1060,10 +1087,10 @@ static __isl_give isl_basic_map *add_strides(__isl_take isl_basic_map *bmap,
 static __isl_give isl_basic_map *isl_basic_map_make_strides_explicit(
 	__isl_take isl_basic_map *bmap)
 {
-	int known;
+	isl_bool known;
 	int n_known;
 	int n, n_col;
-	int total;
+	isl_size v_div;
 	isl_ctx *ctx;
 	isl_mat *A, *B, *M;
 
@@ -1081,16 +1108,18 @@ static __isl_give isl_basic_map *isl_basic_map_make_strides_explicit(
 		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);
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(bmap);
 	for (n = 0; n < bmap->n_eq; ++n)
-		if (isl_seq_first_non_zero(bmap->eq[n] + 1 + total + n_known,
+		if (isl_seq_first_non_zero(bmap->eq[n] + 1 + v_div + 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);
+	B = isl_mat_sub_alloc6(ctx, bmap->eq, 0, n, 0, 1 + v_div + 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_sub_alloc6(ctx, bmap->eq, 0, n, 1 + v_div + 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);

diff  --git a/polly/lib/External/isl/isl_align_params_bin_templ.c b/polly/lib/External/isl/isl_align_params_bin_templ.c
new file mode 100644
index 000000000000..eae8d4d7fd0c
--- /dev/null
+++ b/polly/lib/External/isl/isl_align_params_bin_templ.c
@@ -0,0 +1,8 @@
+#undef ARG1
+#define ARG1	TYPE
+#undef ARG2
+#define ARG2	TYPE
+#undef SUFFIX
+#define SUFFIX	bin
+
+#include "isl_align_params_templ.c"

diff  --git a/polly/lib/External/isl/isl_align_params_templ.c b/polly/lib/External/isl/isl_align_params_templ.c
new file mode 100644
index 000000000000..f56df4956646
--- /dev/null
+++ b/polly/lib/External/isl/isl_align_params_templ.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011      Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege
+ */
+
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Align the parameters of the two arguments of type ARG1 and ARG2
+ * (if needed).
+ */
+isl_stat FN(FN(ARG1,align_params),SUFFIX)(__isl_keep ARG1 **obj1,
+	__isl_keep ARG2 **obj2)
+{
+	isl_space *space1, *space2;
+	isl_bool equal_params;
+
+	space1 = FN(ARG1,peek_space)(*obj1);
+	space2 = FN(ARG2,peek_space)(*obj2);
+	equal_params = isl_space_has_equal_params(space1, space2);
+	if (equal_params < 0)
+		goto error;
+	if (equal_params)
+		return isl_stat_ok;
+	if (FN(ARG1,check_named_params)(*obj1) < 0 ||
+	    FN(ARG2,check_named_params)(*obj2) < 0)
+		goto error;
+	*obj1 = FN(ARG1,align_params)(*obj1, FN(ARG2,get_space)(*obj2));
+	*obj2 = FN(ARG2,align_params)(*obj2, FN(ARG1,get_space)(*obj1));
+	if (!*obj1 || !*obj2)
+		goto error;
+	return isl_stat_ok;
+error:
+	*obj1 = FN(ARG1,free)(*obj1);
+	*obj2 = FN(ARG2,free)(*obj2);
+	return isl_stat_error;
+}

diff  --git a/polly/lib/External/isl/isl_arg.c b/polly/lib/External/isl/isl_arg.c
index 4798a421dc28..2494837692c5 100644
--- a/polly/lib/External/isl/isl_arg.c
+++ b/polly/lib/External/isl/isl_arg.c
@@ -21,7 +21,7 @@ ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
 
 static void set_default_choice(struct isl_arg *arg, void *opt)
 {
-	if (arg->offset == (size_t) -1)
+	if (arg->offset == ISL_ARG_OFFSET_NONE)
 		return;
 	*(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value;
 }
@@ -33,7 +33,7 @@ static void set_default_flags(struct isl_arg *arg, void *opt)
 
 static void set_default_bool(struct isl_arg *arg, void *opt)
 {
-	if (arg->offset == (size_t) -1)
+	if (arg->offset == ISL_ARG_OFFSET_NONE)
 		return;
 	*(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value;
 }
@@ -42,7 +42,7 @@ static void set_default_child(struct isl_arg *arg, void *opt)
 {
 	void *child;
 
-	if (arg->offset == (size_t) -1)
+	if (arg->offset == ISL_ARG_OFFSET_NONE)
 		child = opt;
 	else {
 		child = calloc(1, arg->u.child.child->options_size);
@@ -137,7 +137,7 @@ 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)
+	if (arg->offset == ISL_ARG_OFFSET_NONE)
 		free_args(arg->u.child.child->args, opt);
 	else
 		isl_args_free(arg->u.child.child,
@@ -520,7 +520,7 @@ static void print_bool_help(struct isl_arg *decl,
 	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)
+	if (decl->offset != ISL_ARG_OFFSET_NONE)
 		print_default(decl, no ? "yes" : "no", pos);
 	printf("\n");
 }
@@ -667,7 +667,7 @@ static void print_help(struct isl_arg *arg,
 			printf("\n");
 		if (arg[i].help_msg)
 			printf(" %s\n", arg[i].help_msg);
-		if (arg[i].offset == (size_t) -1)
+		if (arg[i].offset == ISL_ARG_OFFSET_NONE)
 			child = opt;
 		else
 			child = *(void **)(((char *) opt) + arg[i].offset);
@@ -812,7 +812,7 @@ static int parse_choice_option(struct isl_arg *decl, char **arg,
 
 	if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
 		unsigned u = decl->u.choice.default_selected;
-		if (decl->offset != (size_t) -1)
+		if (decl->offset != ISL_ARG_OFFSET_NONE)
 			*(unsigned *)(((char *)opt) + decl->offset) = u;
 		if (decl->u.choice.set)
 			decl->u.choice.set(opt, u);
@@ -830,7 +830,7 @@ static int parse_choice_option(struct isl_arg *decl, char **arg,
 			continue;
 
 		u = decl->u.choice.choice[i].value;
-		if (decl->offset != (size_t) -1)
+		if (decl->offset != ISL_ARG_OFFSET_NONE)
 			*(unsigned *)(((char *)opt) + decl->offset) = u;
 		if (decl->u.choice.set)
 			decl->u.choice.set(opt, u);
@@ -904,14 +904,14 @@ static int parse_bool_option(struct isl_arg *decl, char **arg,
 			char *endptr;
 			int val = strtol(arg[1], &endptr, 0);
 			if (*endptr == '\0' && (val == 0 || val == 1)) {
-				if (decl->offset != (size_t) -1)
+				if (decl->offset != ISL_ARG_OFFSET_NONE)
 					*p = val;
 				if (decl->u.b.set)
 					decl->u.b.set(opt, val);
 				return 2;
 			}
 		}
-		if (decl->offset != (size_t) -1)
+		if (decl->offset != ISL_ARG_OFFSET_NONE)
 			*p = 1;
 		if (decl->u.b.set)
 			decl->u.b.set(opt, 1);
@@ -936,7 +936,7 @@ static int parse_bool_option(struct isl_arg *decl, char **arg,
 	name = skip_prefixes(name, prefixes, &next_prefix);
 
 	if (match_long_name(decl, name, name + strlen(name))) {
-		if (decl->offset != (size_t) -1)
+		if (decl->offset != ISL_ARG_OFFSET_NONE)
 			*p = 0;
 		if (decl->u.b.set)
 			decl->u.b.set(opt, 0);
@@ -1116,7 +1116,7 @@ static int parse_child_option(struct isl_arg *decl, char **arg,
 	void *child;
 	int first, parsed;
 
-	if (decl->offset == (size_t) -1)
+	if (decl->offset == ISL_ARG_OFFSET_NONE)
 		child = opt;
 	else
 		child = *(void **)(((char *)opt) + decl->offset);
@@ -1240,7 +1240,7 @@ static int next_arg(struct isl_arg *arg, int a)
 }
 
 /* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is
- * equal to "--help" and if so call print_help_and_exit.
+ * equal to "--help" or "-h" and if so call print_help_and_exit.
  */
 static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
 	unsigned flags)
@@ -1248,7 +1248,7 @@ static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
 	if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP))
 		return;
 
-	if (strcmp(arg, "--help") == 0)
+	if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0)
 		print_help_and_exit(args->args, prog, opt);
 }
 

diff  --git a/polly/lib/External/isl/isl_ast.c b/polly/lib/External/isl/isl_ast.c
index 96443e9720ac..f0f74336d5da 100644
--- a/polly/lib/External/isl/isl_ast.c
+++ b/polly/lib/External/isl/isl_ast.c
@@ -13,13 +13,13 @@
 #include <isl/val.h>
 #include <isl_ast_private.h>
 
-#undef BASE
-#define BASE ast_expr
+#undef EL_BASE
+#define EL_BASE ast_expr
 
 #include <isl_list_templ.c>
 
-#undef BASE
-#define BASE ast_node
+#undef EL_BASE
+#define EL_BASE ast_node
 
 #include <isl_list_templ.c>
 
@@ -105,7 +105,7 @@ __isl_null isl_ast_print_options *isl_ast_print_options_free(
 
 /* 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.
+ * If this callback is set, then it is 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(
@@ -247,7 +247,7 @@ enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
 
 /* Return the integer value represented by "expr".
  */
-__isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
+__isl_give isl_val *isl_ast_expr_int_get_val(__isl_keep isl_ast_expr *expr)
 {
 	if (!expr)
 		return NULL;
@@ -257,7 +257,14 @@ __isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
 	return isl_val_copy(expr->u.v);
 }
 
-__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
+{
+	return isl_ast_expr_int_get_val(expr);
+}
+
+__isl_give isl_id *isl_ast_expr_id_get_id(__isl_keep isl_ast_expr *expr)
 {
 	if (!expr)
 		return NULL;
@@ -268,27 +275,57 @@ __isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
 	return isl_id_copy(expr->u.id);
 }
 
-enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr)
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
+{
+	return isl_ast_expr_id_get_id(expr);
+}
+
+/* Return the type of operation represented by "expr".
+ */
+enum isl_ast_expr_op_type isl_ast_expr_op_get_type(
+	__isl_keep isl_ast_expr *expr)
 {
 	if (!expr)
-		return isl_ast_op_error;
+		return isl_ast_expr_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);
+			"expression not an operation",
+			return isl_ast_expr_op_error);
 	return expr->u.op.op;
 }
 
-int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
+/* This is an alternative name for the function above.
+ */
+enum isl_ast_expr_op_type isl_ast_expr_get_op_type(
+	__isl_keep isl_ast_expr *expr)
+{
+	return isl_ast_expr_op_get_type(expr);
+}
+
+/* Return the number of arguments of the operation represented by "expr".
+ */
+isl_size isl_ast_expr_op_get_n_arg(__isl_keep isl_ast_expr *expr)
 {
 	if (!expr)
-		return -1;
+		return isl_size_error;
 	if (expr->type != isl_ast_expr_op)
 		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
-			"expression not an operation", return -1);
+			"expression not an operation", return isl_size_error);
 	return expr->u.op.n_arg;
 }
 
-__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+/* This is an alternative name for the function above.
+ */
+isl_size isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
+{
+	return isl_ast_expr_op_get_n_arg(expr);
+}
+
+/* Return the argument at position "pos" of the operation represented by "expr".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_op_get_arg(__isl_keep isl_ast_expr *expr,
 	int pos)
 {
 	if (!expr)
@@ -303,6 +340,14 @@ __isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
 	return isl_ast_expr_copy(expr->u.op.args[pos]);
 }
 
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+	int pos)
+{
+	return isl_ast_expr_op_get_arg(expr, 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,
@@ -345,7 +390,7 @@ isl_bool isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
 	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;
+		return isl_bool_ok(expr1->u.id == expr2->u.id);
 	case isl_ast_expr_op:
 		if (expr1->u.op.op != expr2->u.op.op)
 			return isl_bool_false;
@@ -371,7 +416,7 @@ isl_bool isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
  * 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)
+	enum isl_ast_expr_op_type op, int n_arg)
 {
 	isl_ast_expr *expr;
 
@@ -474,8 +519,8 @@ __isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v)
 /* 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_give isl_ast_expr *isl_ast_expr_alloc_unary(
+	enum isl_ast_expr_op_type type, __isl_take isl_ast_expr *arg)
 {
 	isl_ctx *ctx;
 	isl_ast_expr *expr = NULL;
@@ -500,7 +545,7 @@ __isl_give isl_ast_expr *isl_ast_expr_alloc_unary(enum isl_ast_op_type type,
  */
 __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);
+	return isl_ast_expr_alloc_unary(isl_ast_expr_op_minus, arg);
 }
 
 /* Create an expression representing the address of "expr".
@@ -511,18 +556,19 @@ __isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *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_ast_expr_get_op_type(expr) != isl_ast_expr_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);
+	return isl_ast_expr_alloc_unary(isl_ast_expr_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_give isl_ast_expr *isl_ast_expr_alloc_binary(
+	enum isl_ast_expr_op_type type,
 	__isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2)
 {
 	isl_ctx *ctx;
@@ -551,7 +597,7 @@ __isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_add, expr1, expr2);
 }
 
 /* Create an expression representing the 
diff erence of "expr1" and "expr2".
@@ -559,7 +605,7 @@ __isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_sub, expr1, expr2);
 }
 
 /* Create an expression representing the product of "expr1" and "expr2".
@@ -567,7 +613,7 @@ __isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_mul, expr1, expr2);
 }
 
 /* Create an expression representing the quotient of "expr1" and "expr2".
@@ -575,7 +621,7 @@ __isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_div, expr1, expr2);
 }
 
 /* Create an expression representing the quotient of the integer
@@ -585,7 +631,7 @@ __isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
 __isl_give isl_ast_expr *isl_ast_expr_pdiv_q(__isl_take isl_ast_expr *expr1,
 	__isl_take isl_ast_expr *expr2)
 {
-	return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_q, expr1, expr2);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_q, expr1, expr2);
 }
 
 /* Create an expression representing the remainder of the integer
@@ -595,7 +641,7 @@ __isl_give isl_ast_expr *isl_ast_expr_pdiv_q(__isl_take isl_ast_expr *expr1,
 __isl_give isl_ast_expr *isl_ast_expr_pdiv_r(__isl_take isl_ast_expr *expr1,
 	__isl_take isl_ast_expr *expr2)
 {
-	return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r, expr1, expr2);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_r, expr1, expr2);
 }
 
 /* Create an expression representing the conjunction of "expr1" and "expr2".
@@ -603,7 +649,7 @@ __isl_give isl_ast_expr *isl_ast_expr_pdiv_r(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_and, expr1, expr2);
 }
 
 /* Create an expression representing the conjunction of "expr1" and "expr2",
@@ -612,7 +658,7 @@ __isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
 __isl_give isl_ast_expr *isl_ast_expr_and_then(__isl_take isl_ast_expr *expr1,
 	__isl_take isl_ast_expr *expr2)
 {
-	return isl_ast_expr_alloc_binary(isl_ast_op_and_then, expr1, expr2);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_and_then, expr1, expr2);
 }
 
 /* Create an expression representing the disjunction of "expr1" and "expr2".
@@ -620,7 +666,7 @@ __isl_give isl_ast_expr *isl_ast_expr_and_then(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_or, expr1, expr2);
 }
 
 /* Create an expression representing the disjunction of "expr1" and "expr2",
@@ -629,7 +675,7 @@ __isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
 __isl_give isl_ast_expr *isl_ast_expr_or_else(__isl_take isl_ast_expr *expr1,
 	__isl_take isl_ast_expr *expr2)
 {
-	return isl_ast_expr_alloc_binary(isl_ast_op_or_else, expr1, expr2);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_or_else, expr1, expr2);
 }
 
 /* Create an expression representing "expr1" less than or equal to "expr2".
@@ -637,7 +683,7 @@ __isl_give isl_ast_expr *isl_ast_expr_or_else(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_le, expr1, expr2);
 }
 
 /* Create an expression representing "expr1" less than "expr2".
@@ -645,7 +691,7 @@ __isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_lt, expr1, expr2);
 }
 
 /* Create an expression representing "expr1" greater than or equal to "expr2".
@@ -653,7 +699,7 @@ __isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_ge, expr1, expr2);
 }
 
 /* Create an expression representing "expr1" greater than "expr2".
@@ -661,7 +707,7 @@ __isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_gt, expr1, expr2);
 }
 
 /* Create an expression representing "expr1" equal to "expr2".
@@ -669,17 +715,18 @@ __isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,
 __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);
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_eq, expr1, expr2);
 }
 
 /* Create an expression of type "type" with as arguments "arg0" followed
  * by "arguments".
  */
 static __isl_give isl_ast_expr *ast_expr_with_arguments(
-	enum isl_ast_op_type type, __isl_take isl_ast_expr *arg0,
+	enum isl_ast_expr_op_type type, __isl_take isl_ast_expr *arg0,
 	__isl_take isl_ast_expr_list *arguments)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_ast_expr *res = NULL;
 
@@ -688,6 +735,8 @@ static __isl_give isl_ast_expr *ast_expr_with_arguments(
 
 	ctx = isl_ast_expr_get_ctx(arg0);
 	n = isl_ast_expr_list_n_ast_expr(arguments);
+	if (n < 0)
+		goto error;
 	res = isl_ast_expr_alloc_op(ctx, type, 1 + n);
 	if (!res)
 		goto error;
@@ -715,7 +764,7 @@ static __isl_give isl_ast_expr *ast_expr_with_arguments(
 __isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
 	__isl_take isl_ast_expr_list *indices)
 {
-	return ast_expr_with_arguments(isl_ast_op_access, array, indices);
+	return ast_expr_with_arguments(isl_ast_expr_op_access, array, indices);
 }
 
 /* Create an expression representing a call to "function" with argument
@@ -724,7 +773,7 @@ __isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
 __isl_give isl_ast_expr *isl_ast_expr_call(__isl_take isl_ast_expr *function,
 	__isl_take isl_ast_expr_list *arguments)
 {
-	return ast_expr_with_arguments(isl_ast_op_call, function, arguments);
+	return ast_expr_with_arguments(isl_ast_expr_op_call, function, arguments);
 }
 
 /* For each subexpression of "expr" of type isl_ast_expr_id,
@@ -942,15 +991,22 @@ __isl_give isl_ast_node *isl_ast_node_alloc_block(
 __isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
 	__isl_take isl_ast_node_list *list)
 {
+	isl_size n;
 	isl_ast_node *node;
 
-	if (isl_ast_node_list_n_ast_node(list) != 1)
+	n = isl_ast_node_list_n_ast_node(list);
+	if (n < 0)
+		goto error;
+	if (n != 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;
+error:
+	isl_ast_node_list_free(list);
+	return NULL;
 }
 
 __isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node)
@@ -1120,7 +1176,7 @@ isl_bool isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node)
 	if (node->type != isl_ast_node_for)
 		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
 			"not a for node", return isl_bool_error);
-	return node->u.f.degenerate;
+	return isl_bool_ok(node->u.f.degenerate);
 }
 
 __isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
@@ -1163,7 +1219,7 @@ __isl_give isl_ast_expr *isl_ast_node_for_get_cond(
 	if (!node->u.f.degenerate)
 		return isl_ast_expr_copy(node->u.f.cond);
 
-	return isl_ast_expr_alloc_binary(isl_ast_op_le,
+	return isl_ast_expr_alloc_binary(isl_ast_expr_op_le,
 				isl_ast_expr_copy(node->u.f.iterator),
 				isl_ast_expr_copy(node->u.f.init));
 }
@@ -1208,7 +1264,9 @@ __isl_give isl_ast_node *isl_ast_node_if_set_then(
 	return NULL;
 }
 
-__isl_give isl_ast_node *isl_ast_node_if_get_then(
+/* Return the then-node of the given if-node.
+ */
+__isl_give isl_ast_node *isl_ast_node_if_get_then_node(
 	__isl_keep isl_ast_node *node)
 {
 	if (!node)
@@ -1219,18 +1277,37 @@ __isl_give isl_ast_node *isl_ast_node_if_get_then(
 	return isl_ast_node_copy(node->u.i.then);
 }
 
-isl_bool isl_ast_node_if_has_else(
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_ast_node *isl_ast_node_if_get_then(
 	__isl_keep isl_ast_node *node)
+{
+	return isl_ast_node_if_get_then_node(node);
+}
+
+/* Does the given if-node have an else-node?
+ */
+isl_bool isl_ast_node_if_has_else_node(__isl_keep isl_ast_node *node)
 {
 	if (!node)
 		return isl_bool_error;
 	if (node->type != isl_ast_node_if)
 		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
 			"not an if node", return isl_bool_error);
-	return node->u.i.else_node != NULL;
+	return isl_bool_ok(node->u.i.else_node != NULL);
 }
 
-__isl_give isl_ast_node *isl_ast_node_if_get_else(
+/* This is an alternative name for the function above.
+ */
+isl_bool isl_ast_node_if_has_else(__isl_keep isl_ast_node *node)
+{
+	return isl_ast_node_if_has_else_node(node);
+}
+
+/* Return the else-node of the given if-node,
+ * assuming there is one.
+ */
+__isl_give isl_ast_node *isl_ast_node_if_get_else_node(
 	__isl_keep isl_ast_node *node)
 {
 	if (!node)
@@ -1241,6 +1318,14 @@ __isl_give isl_ast_node *isl_ast_node_if_get_else(
 	return isl_ast_node_copy(node->u.i.else_node);
 }
 
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_ast_node *isl_ast_node_if_get_else(
+	__isl_keep isl_ast_node *node)
+{
+	return isl_ast_node_if_get_else_node(node);
+}
+
 __isl_give isl_ast_expr *isl_ast_node_if_get_cond(
 	__isl_keep isl_ast_node *node)
 {
@@ -1406,28 +1491,28 @@ isl_stat isl_ast_node_foreach_descendant_top_down(
 /* Textual C representation of the various operators.
  */
 static char *op_str_c[] = {
-	[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_fdiv_q] = "floord",
-	[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] = "&"
+	[isl_ast_expr_op_and] = "&&",
+	[isl_ast_expr_op_and_then] = "&&",
+	[isl_ast_expr_op_or] = "||",
+	[isl_ast_expr_op_or_else] = "||",
+	[isl_ast_expr_op_max] = "max",
+	[isl_ast_expr_op_min] = "min",
+	[isl_ast_expr_op_minus] = "-",
+	[isl_ast_expr_op_add] = "+",
+	[isl_ast_expr_op_sub] = "-",
+	[isl_ast_expr_op_mul] = "*",
+	[isl_ast_expr_op_fdiv_q] = "floord",
+	[isl_ast_expr_op_pdiv_q] = "/",
+	[isl_ast_expr_op_pdiv_r] = "%",
+	[isl_ast_expr_op_zdiv_r] = "%",
+	[isl_ast_expr_op_div] = "/",
+	[isl_ast_expr_op_eq] = "==",
+	[isl_ast_expr_op_le] = "<=",
+	[isl_ast_expr_op_ge] = ">=",
+	[isl_ast_expr_op_lt] = "<",
+	[isl_ast_expr_op_gt] = ">",
+	[isl_ast_expr_op_member] = ".",
+	[isl_ast_expr_op_address_of] = "&"
 };
 
 /* Precedence in C of the various operators.
@@ -1435,85 +1520,85 @@ static char *op_str_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
+	[isl_ast_expr_op_and] = 13,
+	[isl_ast_expr_op_and_then] = 13,
+	[isl_ast_expr_op_or] = 14,
+	[isl_ast_expr_op_or_else] = 14,
+	[isl_ast_expr_op_max] = 2,
+	[isl_ast_expr_op_min] = 2,
+	[isl_ast_expr_op_minus] = 3,
+	[isl_ast_expr_op_add] = 6,
+	[isl_ast_expr_op_sub] = 6,
+	[isl_ast_expr_op_mul] = 5,
+	[isl_ast_expr_op_div] = 5,
+	[isl_ast_expr_op_fdiv_q] = 2,
+	[isl_ast_expr_op_pdiv_q] = 5,
+	[isl_ast_expr_op_pdiv_r] = 5,
+	[isl_ast_expr_op_zdiv_r] = 5,
+	[isl_ast_expr_op_cond] = 15,
+	[isl_ast_expr_op_select] = 15,
+	[isl_ast_expr_op_eq] = 9,
+	[isl_ast_expr_op_le] = 8,
+	[isl_ast_expr_op_ge] = 8,
+	[isl_ast_expr_op_lt] = 8,
+	[isl_ast_expr_op_gt] = 8,
+	[isl_ast_expr_op_call] = 2,
+	[isl_ast_expr_op_access] = 2,
+	[isl_ast_expr_op_member] = 2,
+	[isl_ast_expr_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
+	[isl_ast_expr_op_and] = 1,
+	[isl_ast_expr_op_and_then] = 1,
+	[isl_ast_expr_op_or] = 1,
+	[isl_ast_expr_op_or_else] = 1,
+	[isl_ast_expr_op_max] = 1,
+	[isl_ast_expr_op_min] = 1,
+	[isl_ast_expr_op_minus] = 0,
+	[isl_ast_expr_op_add] = 1,
+	[isl_ast_expr_op_sub] = 1,
+	[isl_ast_expr_op_mul] = 1,
+	[isl_ast_expr_op_div] = 1,
+	[isl_ast_expr_op_fdiv_q] = 1,
+	[isl_ast_expr_op_pdiv_q] = 1,
+	[isl_ast_expr_op_pdiv_r] = 1,
+	[isl_ast_expr_op_zdiv_r] = 1,
+	[isl_ast_expr_op_cond] = 0,
+	[isl_ast_expr_op_select] = 0,
+	[isl_ast_expr_op_eq] = 1,
+	[isl_ast_expr_op_le] = 1,
+	[isl_ast_expr_op_ge] = 1,
+	[isl_ast_expr_op_lt] = 1,
+	[isl_ast_expr_op_gt] = 1,
+	[isl_ast_expr_op_call] = 1,
+	[isl_ast_expr_op_access] = 1,
+	[isl_ast_expr_op_member] = 1,
+	[isl_ast_expr_op_address_of] = 0
 };
 
-static int is_and(enum isl_ast_op_type op)
+static int is_and(enum isl_ast_expr_op_type op)
 {
-	return op == isl_ast_op_and || op == isl_ast_op_and_then;
+	return op == isl_ast_expr_op_and || op == isl_ast_expr_op_and_then;
 }
 
-static int is_or(enum isl_ast_op_type op)
+static int is_or(enum isl_ast_expr_op_type op)
 {
-	return op == isl_ast_op_or || op == isl_ast_op_or_else;
+	return op == isl_ast_expr_op_or || op == isl_ast_expr_op_or_else;
 }
 
-static int is_add_sub(enum isl_ast_op_type op)
+static int is_add_sub(enum isl_ast_expr_op_type op)
 {
-	return op == isl_ast_op_add || op == isl_ast_op_sub;
+	return op == isl_ast_expr_op_add || op == isl_ast_expr_op_sub;
 }
 
-static int is_div_mod(enum isl_ast_op_type op)
+static int is_div_mod(enum isl_ast_expr_op_type op)
 {
-	return op == isl_ast_op_div ||
-	       op == isl_ast_op_pdiv_r ||
-	       op == isl_ast_op_zdiv_r;
+	return op == isl_ast_expr_op_div ||
+	       op == isl_ast_expr_op_pdiv_r ||
+	       op == isl_ast_expr_op_zdiv_r;
 }
 
 static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
@@ -1537,7 +1622,7 @@ static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
  * Computations such as "a / b * c" and "a % b + c" can be somewhat
  * 
diff icult to read, so we add parentheses for those as well.
  */
-static int sub_expr_need_parens(enum isl_ast_op_type op,
+static int sub_expr_need_parens(enum isl_ast_expr_op_type op,
 	__isl_keep isl_ast_expr *expr, int left)
 {
 	if (expr->type != isl_ast_expr_op)
@@ -1550,7 +1635,7 @@ static int sub_expr_need_parens(enum isl_ast_op_type op,
 
 	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 &&
+	if (op == isl_ast_expr_op_mul && expr->u.op.op != isl_ast_expr_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))
@@ -1563,7 +1648,7 @@ static int sub_expr_need_parens(enum isl_ast_op_type op,
  * If "left" is set, then "expr" is the left-most operand.
  */
 static __isl_give isl_printer *print_sub_expr_c(__isl_take isl_printer *p,
-	enum isl_ast_op_type op, __isl_keep isl_ast_expr *expr, int left)
+	enum isl_ast_expr_op_type op, __isl_keep isl_ast_expr *expr, int left)
 {
 	int need_parens;
 
@@ -1577,46 +1662,46 @@ static __isl_give isl_printer *print_sub_expr_c(__isl_take isl_printer *p,
 	return p;
 }
 
-#define isl_ast_op_last	isl_ast_op_address_of
+#define isl_ast_expr_op_last	isl_ast_expr_op_address_of
 
 /* Data structure that holds the user-specified textual
  * representations for the operators in C format.
  * The entries are either NULL or copies of strings.
  * A NULL entry means that the default name should be used.
  */
-struct isl_ast_op_names {
-	char *op_str[isl_ast_op_last + 1];
+struct isl_ast_expr_op_names {
+	char *op_str[isl_ast_expr_op_last + 1];
 };
 
-/* Create an empty struct isl_ast_op_names.
+/* Create an empty struct isl_ast_expr_op_names.
  */
 static void *create_names(isl_ctx *ctx)
 {
-	return isl_calloc_type(ctx, struct isl_ast_op_names);
+	return isl_calloc_type(ctx, struct isl_ast_expr_op_names);
 }
 
-/* Free a struct isl_ast_op_names along with all memory
+/* Free a struct isl_ast_expr_op_names along with all memory
  * owned by the struct.
  */
 static void free_names(void *user)
 {
 	int i;
-	struct isl_ast_op_names *names = user;
+	struct isl_ast_expr_op_names *names = user;
 
 	if (!user)
 		return;
 
-	for (i = 0; i <= isl_ast_op_last; ++i)
+	for (i = 0; i <= isl_ast_expr_op_last; ++i)
 		free(names->op_str[i]);
 	free(user);
 }
 
 /* Create an identifier that is used to store
- * an isl_ast_op_names note.
+ * an isl_ast_expr_op_names note.
  */
 static __isl_give isl_id *names_id(isl_ctx *ctx)
 {
-	return isl_id_alloc(ctx, "isl_ast_op_type_names", NULL);
+	return isl_id_alloc(ctx, "isl_ast_expr_op_type_names", NULL);
 }
 
 /* Ensure that "p" has a note identified by "id".
@@ -1653,7 +1738,7 @@ static __isl_give isl_printer *alloc_note(__isl_take isl_printer *p,
 	return p;
 }
 
-/* Ensure that "p" has an isl_ast_op_names note identified by "id".
+/* Ensure that "p" has an isl_ast_expr_op_names note identified by "id".
  */
 static __isl_give isl_printer *alloc_names(__isl_take isl_printer *p,
 	__isl_keep isl_id *id)
@@ -1677,19 +1762,19 @@ static void *get_note(__isl_keep isl_printer *p, __isl_keep isl_id *id)
 
 /* Use "name" to print operations of type "type" to "p".
  *
- * Store the name in an isl_ast_op_names note attached to "p", such that
+ * Store the name in an isl_ast_expr_op_names note attached to "p", such that
  * it can be retrieved by get_op_str.
  */
-__isl_give isl_printer *isl_ast_op_type_set_print_name(
-	__isl_take isl_printer *p, enum isl_ast_op_type type,
+__isl_give isl_printer *isl_ast_expr_op_type_set_print_name(
+	__isl_take isl_printer *p, enum isl_ast_expr_op_type type,
 	__isl_keep const char *name)
 {
 	isl_id *id;
-	struct isl_ast_op_names *names;
+	struct isl_ast_expr_op_names *names;
 
 	if (!p)
 		return NULL;
-	if (type > isl_ast_op_last)
+	if (type > isl_ast_expr_op_last)
 		isl_die(isl_printer_get_ctx(p), isl_error_invalid,
 			"invalid type", return isl_printer_free(p));
 
@@ -1705,18 +1790,27 @@ __isl_give isl_printer *isl_ast_op_type_set_print_name(
 	return p;
 }
 
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_printer *isl_ast_op_type_set_print_name(
+	__isl_take isl_printer *p, enum isl_ast_expr_op_type type,
+	__isl_keep const char *name)
+{
+	return isl_ast_expr_op_type_set_print_name(p, type, name);
+}
+
 /* Return the textual representation of "type" in C format.
  *
- * If there is a user-specified name in an isl_ast_op_names note
+ * If there is a user-specified name in an isl_ast_expr_op_names note
  * associated to "p", then return that.
- * Otherwise, return the default name in op_str.
+ * Otherwise, return the default name in op_str_c.
  */
 static const char *get_op_str_c(__isl_keep isl_printer *p,
-	enum isl_ast_op_type type)
+	enum isl_ast_expr_op_type type)
 {
 	isl_id *id;
 	isl_bool has_names;
-	struct isl_ast_op_names *names = NULL;
+	struct isl_ast_expr_op_names *names = NULL;
 
 	id = names_id(isl_printer_get_ctx(p));
 	has_names = isl_printer_has_note(p, id);
@@ -1801,11 +1895,11 @@ static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
 
 	switch (expr->type) {
 	case isl_ast_expr_op:
-		if (expr->u.op.op == isl_ast_op_call) {
+		if (expr->u.op.op == isl_ast_expr_op_call) {
 			p = print_call_c(p, expr);
 			break;
 		}
-		if (expr->u.op.op == isl_ast_op_access) {
+		if (expr->u.op.op == isl_ast_expr_op_access) {
 			p = print_access_c(p, expr);
 			break;
 		}
@@ -1816,8 +1910,10 @@ static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
 						expr->u.op.args[0], 0);
 			break;
 		}
-		if (expr->u.op.op == isl_ast_op_fdiv_q) {
-			const char *name = get_op_str_c(p, isl_ast_op_fdiv_q);
+		if (expr->u.op.op == isl_ast_expr_op_fdiv_q) {
+			const char *name;
+
+			name = get_op_str_c(p, isl_ast_expr_op_fdiv_q);
 			p = isl_printer_print_str(p, name);
 			p = isl_printer_print_str(p, "(");
 			p = print_ast_expr_c(p, expr->u.op.args[0]);
@@ -1826,13 +1922,13 @@ static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
 			p = isl_printer_print_str(p, ")");
 			break;
 		}
-		if (expr->u.op.op == isl_ast_op_max ||
-		    expr->u.op.op == isl_ast_op_min) {
+		if (expr->u.op.op == isl_ast_expr_op_max ||
+		    expr->u.op.op == isl_ast_expr_op_min) {
 			p = print_min_max_c(p, expr);
 			break;
 		}
-		if (expr->u.op.op == isl_ast_op_cond ||
-		    expr->u.op.op == isl_ast_op_select) {
+		if (expr->u.op.op == isl_ast_expr_op_cond ||
+		    expr->u.op.op == isl_ast_expr_op_select) {
 			p = print_ast_expr_c(p, expr->u.op.args[0]);
 			p = isl_printer_print_str(p, " ? ");
 			p = print_ast_expr_c(p, expr->u.op.args[1]);
@@ -1845,10 +1941,10 @@ static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
 				"operation should have two arguments",
 				return isl_printer_free(p));
 		p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[0], 1);
-		if (expr->u.op.op != isl_ast_op_member)
+		if (expr->u.op.op != isl_ast_expr_op_member)
 			p = isl_printer_print_str(p, " ");
 		p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));
-		if (expr->u.op.op != isl_ast_op_member)
+		if (expr->u.op.op != isl_ast_expr_op_member)
 			p = isl_printer_print_str(p, " ");
 		p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[1], 0);
 		break;
@@ -1865,36 +1961,36 @@ static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
 	return p;
 }
 
-/* Textual representation of the isl_ast_op_type elements
+/* Textual representation of the isl_ast_expr_op_type elements
  * for use in a YAML representation of an isl_ast_expr.
  */
 static char *op_str[] = {
-	[isl_ast_op_and] = "and",
-	[isl_ast_op_and_then] = "and_then",
-	[isl_ast_op_or] = "or",
-	[isl_ast_op_or_else] = "or_else",
-	[isl_ast_op_max] = "max",
-	[isl_ast_op_min] = "min",
-	[isl_ast_op_minus] = "minus",
-	[isl_ast_op_add] = "add",
-	[isl_ast_op_sub] = "sub",
-	[isl_ast_op_mul] = "mul",
-	[isl_ast_op_div] = "div",
-	[isl_ast_op_fdiv_q] = "fdiv_q",
-	[isl_ast_op_pdiv_q] = "pdiv_q",
-	[isl_ast_op_pdiv_r] = "pdiv_r",
-	[isl_ast_op_zdiv_r] = "zdiv_r",
-	[isl_ast_op_cond] = "cond",
-	[isl_ast_op_select] = "select",
-	[isl_ast_op_eq] = "eq",
-	[isl_ast_op_le] = "le",
-	[isl_ast_op_lt] = "lt",
-	[isl_ast_op_ge] = "ge",
-	[isl_ast_op_gt] = "gt",
-	[isl_ast_op_call] = "call",
-	[isl_ast_op_access] = "access",
-	[isl_ast_op_member] = "member",
-	[isl_ast_op_address_of] = "address_of"
+	[isl_ast_expr_op_and] = "and",
+	[isl_ast_expr_op_and_then] = "and_then",
+	[isl_ast_expr_op_or] = "or",
+	[isl_ast_expr_op_or_else] = "or_else",
+	[isl_ast_expr_op_max] = "max",
+	[isl_ast_expr_op_min] = "min",
+	[isl_ast_expr_op_minus] = "minus",
+	[isl_ast_expr_op_add] = "add",
+	[isl_ast_expr_op_sub] = "sub",
+	[isl_ast_expr_op_mul] = "mul",
+	[isl_ast_expr_op_div] = "div",
+	[isl_ast_expr_op_fdiv_q] = "fdiv_q",
+	[isl_ast_expr_op_pdiv_q] = "pdiv_q",
+	[isl_ast_expr_op_pdiv_r] = "pdiv_r",
+	[isl_ast_expr_op_zdiv_r] = "zdiv_r",
+	[isl_ast_expr_op_cond] = "cond",
+	[isl_ast_expr_op_select] = "select",
+	[isl_ast_expr_op_eq] = "eq",
+	[isl_ast_expr_op_le] = "le",
+	[isl_ast_expr_op_lt] = "lt",
+	[isl_ast_expr_op_ge] = "ge",
+	[isl_ast_expr_op_gt] = "gt",
+	[isl_ast_expr_op_call] = "call",
+	[isl_ast_expr_op_access] = "access",
+	[isl_ast_expr_op_member] = "member",
+	[isl_ast_expr_op_address_of] = "address_of"
 };
 
 static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
@@ -1909,7 +2005,8 @@ static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
 static __isl_give isl_printer *print_arguments(__isl_take isl_printer *p,
 	__isl_keep isl_ast_expr *expr)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_ast_expr_get_op_n_arg(expr);
 	if (n < 0)
@@ -1941,7 +2038,7 @@ static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
 	__isl_keep isl_ast_expr *expr)
 {
 	enum isl_ast_expr_type type;
-	enum isl_ast_op_type op;
+	enum isl_ast_expr_op_type op;
 	isl_id *id;
 	isl_val *v;
 
@@ -1955,7 +2052,7 @@ static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
 		return isl_printer_free(p);
 	case isl_ast_expr_op:
 		op = isl_ast_expr_get_op_type(expr);
-		if (op == isl_ast_op_error)
+		if (op == isl_ast_expr_op_error)
 			return isl_printer_free(p);
 		p = isl_printer_print_str(p, "op");
 		p = isl_printer_yaml_next(p);
@@ -2020,7 +2117,8 @@ static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
 static __isl_give isl_printer *print_ast_node_list(__isl_take isl_printer *p,
 	__isl_keep isl_ast_node_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_ast_node_list_n_ast_node(list);
 	if (n < 0)
@@ -2490,15 +2588,15 @@ __isl_give isl_printer *isl_ast_node_list_print(
 	return p;
 }
 
-#define ISL_AST_MACRO_FLOORD	(1 << 0)
+#define ISL_AST_MACRO_FDIV_Q	(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 | \
+#define ISL_AST_MACRO_ALL	(ISL_AST_MACRO_FDIV_Q | \
 				 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".
+/* If "expr" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or
+ * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".
  */
 static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)
 {
@@ -2510,12 +2608,12 @@ static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)
 	if (expr->type != isl_ast_expr_op)
 		return macros;
 
-	if (expr->u.op.op == isl_ast_op_min)
+	if (expr->u.op.op == isl_ast_expr_op_min)
 		macros |= ISL_AST_MACRO_MIN;
-	if (expr->u.op.op == isl_ast_op_max)
+	if (expr->u.op.op == isl_ast_expr_op_max)
 		macros |= ISL_AST_MACRO_MAX;
-	if (expr->u.op.op == isl_ast_op_fdiv_q)
-		macros |= ISL_AST_MACRO_FLOORD;
+	if (expr->u.op.op == isl_ast_expr_op_fdiv_q)
+		macros |= ISL_AST_MACRO_FDIV_Q;
 
 	for (i = 0; i < expr->u.op.n_arg; ++i)
 		macros = ast_expr_required_macros(expr->u.op.args[i], macros);
@@ -2526,8 +2624,8 @@ static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int 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".
+/* If "node" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or
+ * isl_ast_expr_op_fdiv_q then set the corresponding bit in "macros".
  */
 static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)
 {
@@ -2569,8 +2667,8 @@ static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)
 	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".
+/* If "list" contains an isl_ast_expr_op_min, isl_ast_expr_op_max or
+ * isl_ast_expr_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)
@@ -2587,25 +2685,25 @@ static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
  * for a given type has already been printed.
  * The value is zero if no definition has been printed and non-zero otherwise.
  */
-struct isl_ast_op_printed {
-	char printed[isl_ast_op_last + 1];
+struct isl_ast_expr_op_printed {
+	char printed[isl_ast_expr_op_last + 1];
 };
 
-/* Create an empty struct isl_ast_op_printed.
+/* Create an empty struct isl_ast_expr_op_printed.
  */
 static void *create_printed(isl_ctx *ctx)
 {
-	return isl_calloc_type(ctx, struct isl_ast_op_printed);
+	return isl_calloc_type(ctx, struct isl_ast_expr_op_printed);
 }
 
-/* Free a struct isl_ast_op_printed.
+/* Free a struct isl_ast_expr_op_printed.
  */
 static void free_printed(void *user)
 {
 	free(user);
 }
 
-/* Ensure that "p" has an isl_ast_op_printed note identified by "id".
+/* Ensure that "p" has an isl_ast_expr_op_printed note identified by "id".
  */
 static __isl_give isl_printer *alloc_printed(__isl_take isl_printer *p,
 	__isl_keep isl_id *id)
@@ -2614,11 +2712,11 @@ static __isl_give isl_printer *alloc_printed(__isl_take isl_printer *p,
 }
 
 /* Create an identifier that is used to store
- * an isl_ast_op_printed note.
+ * an isl_ast_expr_op_printed note.
  */
 static __isl_give isl_id *printed_id(isl_ctx *ctx)
 {
-	return isl_id_alloc(ctx, "isl_ast_op_type_printed", NULL);
+	return isl_id_alloc(ctx, "isl_ast_expr_op_type_printed", NULL);
 }
 
 /* Did the user specify that a macro definition should only be
@@ -2630,11 +2728,11 @@ static __isl_give isl_id *printed_id(isl_ctx *ctx)
  * The actual printing is taken care of by the caller.
  */
 static isl_bool already_printed_once(__isl_keep isl_printer *p,
-	enum isl_ast_op_type type)
+	enum isl_ast_expr_op_type type)
 {
 	isl_ctx *ctx;
 	isl_id *id;
-	struct isl_ast_op_printed *printed;
+	struct isl_ast_expr_op_printed *printed;
 
 	if (!p)
 		return isl_bool_error;
@@ -2643,7 +2741,7 @@ static isl_bool already_printed_once(__isl_keep isl_printer *p,
 	if (!isl_options_get_ast_print_macro_once(ctx))
 		return isl_bool_false;
 
-	if (type > isl_ast_op_last)
+	if (type > isl_ast_expr_op_last)
 		isl_die(isl_printer_get_ctx(p), isl_error_invalid,
 			"invalid type", return isl_bool_error);
 
@@ -2667,8 +2765,8 @@ static isl_bool already_printed_once(__isl_keep isl_printer *p,
  * only be printed once to any given printer and if the macro definition
  * has already been printed to "p", then do not print the definition.
  */
-__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_expr_op_type_print_macro(
+	enum isl_ast_expr_op_type type, __isl_take isl_printer *p)
 {
 	isl_bool skip;
 
@@ -2679,7 +2777,7 @@ __isl_give isl_printer *isl_ast_op_type_print_macro(
 		return p;
 
 	switch (type) {
-	case isl_ast_op_min:
+	case isl_ast_expr_op_min:
 		p = isl_printer_start_line(p);
 		p = isl_printer_print_str(p, "#define ");
 		p = isl_printer_print_str(p, get_op_str_c(p, type));
@@ -2687,7 +2785,7 @@ __isl_give isl_printer *isl_ast_op_type_print_macro(
 			"(x,y)    ((x) < (y) ? (x) : (y))");
 		p = isl_printer_end_line(p);
 		break;
-	case isl_ast_op_max:
+	case isl_ast_expr_op_max:
 		p = isl_printer_start_line(p);
 		p = isl_printer_print_str(p, "#define ");
 		p = isl_printer_print_str(p, get_op_str_c(p, type));
@@ -2695,7 +2793,7 @@ __isl_give isl_printer *isl_ast_op_type_print_macro(
 			"(x,y)    ((x) > (y) ? (x) : (y))");
 		p = isl_printer_end_line(p);
 		break;
-	case isl_ast_op_fdiv_q:
+	case isl_ast_expr_op_fdiv_q:
 		p = isl_printer_start_line(p);
 		p = isl_printer_print_str(p, "#define ");
 		p = isl_printer_print_str(p, get_op_str_c(p, type));
@@ -2711,17 +2809,26 @@ __isl_give isl_printer *isl_ast_op_type_print_macro(
 	return p;
 }
 
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_printer *isl_ast_op_type_print_macro(
+	enum isl_ast_expr_op_type type, __isl_take isl_printer *p)
+{
+	return isl_ast_expr_op_type_print_macro(type, p);
+}
+
 /* Call "fn" for each type of operation represented in the "macros"
  * bit vector.
  */
-static isl_stat foreach_ast_op_type(int macros,
-	isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user)
+static isl_stat foreach_ast_expr_op_type(int macros,
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
 {
-	if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_op_min, user) < 0)
+	if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_expr_op_min, user) < 0)
 		return isl_stat_error;
-	if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_op_max, user) < 0)
+	if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_expr_op_max, user) < 0)
 		return isl_stat_error;
-	if (macros & ISL_AST_MACRO_FLOORD && fn(isl_ast_op_fdiv_q, user) < 0)
+	if (macros & ISL_AST_MACRO_FDIV_Q &&
+	    fn(isl_ast_expr_op_fdiv_q, user) < 0)
 		return isl_stat_error;
 
 	return isl_stat_ok;
@@ -2730,8 +2837,8 @@ static isl_stat foreach_ast_op_type(int macros,
 /* Call "fn" for each type of operation that appears in "expr"
  * and that requires a macro definition.
  */
-isl_stat isl_ast_expr_foreach_ast_op_type(__isl_keep isl_ast_expr *expr,
-	isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user)
+isl_stat isl_ast_expr_foreach_ast_expr_op_type(__isl_keep isl_ast_expr *expr,
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
 {
 	int macros;
 
@@ -2739,14 +2846,22 @@ isl_stat isl_ast_expr_foreach_ast_op_type(__isl_keep isl_ast_expr *expr,
 		return isl_stat_error;
 
 	macros = ast_expr_required_macros(expr, 0);
-	return foreach_ast_op_type(macros, fn, user);
+	return foreach_ast_expr_op_type(macros, fn, user);
+}
+
+/* This is an alternative name for the function above.
+ */
+isl_stat isl_ast_expr_foreach_ast_op_type(__isl_keep isl_ast_expr *expr,
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
+{
+	return isl_ast_expr_foreach_ast_expr_op_type(expr, fn, user);
 }
 
 /* Call "fn" for each type of operation that appears in "node"
  * and that requires a macro definition.
  */
-isl_stat isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
-	isl_stat (*fn)(enum isl_ast_op_type type, void *user), void *user)
+isl_stat isl_ast_node_foreach_ast_expr_op_type(__isl_keep isl_ast_node *node,
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
 {
 	int macros;
 
@@ -2754,14 +2869,23 @@ isl_stat isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
 		return isl_stat_error;
 
 	macros = ast_node_required_macros(node, 0);
-	return foreach_ast_op_type(macros, fn, user);
+	return foreach_ast_expr_op_type(macros, fn, user);
 }
 
-static isl_stat ast_op_type_print_macro(enum isl_ast_op_type type, void *user)
+/* This is an alternative name for the function above.
+ */
+isl_stat isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
+	isl_stat (*fn)(enum isl_ast_expr_op_type type, void *user), void *user)
+{
+	return isl_ast_node_foreach_ast_expr_op_type(node, fn, user);
+}
+
+static isl_stat ast_op_type_print_macro(enum isl_ast_expr_op_type type,
+	void *user)
 {
 	isl_printer **p = user;
 
-	*p = isl_ast_op_type_print_macro(type, *p);
+	*p = isl_ast_expr_op_type_print_macro(type, *p);
 
 	return isl_stat_ok;
 }
@@ -2772,7 +2896,7 @@ static isl_stat ast_op_type_print_macro(enum isl_ast_op_type type, void *user)
 __isl_give isl_printer *isl_ast_expr_print_macros(
 	__isl_keep isl_ast_expr *expr, __isl_take isl_printer *p)
 {
-	if (isl_ast_expr_foreach_ast_op_type(expr,
+	if (isl_ast_expr_foreach_ast_expr_op_type(expr,
 					    &ast_op_type_print_macro, &p) < 0)
 		return isl_printer_free(p);
 	return p;
@@ -2784,7 +2908,7 @@ __isl_give isl_printer *isl_ast_expr_print_macros(
 __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,
+	if (isl_ast_node_foreach_ast_expr_op_type(node,
 					    &ast_op_type_print_macro, &p) < 0)
 		return isl_printer_free(p);
 	return p;

diff  --git a/polly/lib/External/isl/isl_ast_build.c b/polly/lib/External/isl/isl_ast_build.c
index 4cd94c449663..1c4cbd944bbc 100644
--- a/polly/lib/External/isl/isl_ast_build.c
+++ b/polly/lib/External/isl/isl_ast_build.c
@@ -57,13 +57,17 @@ static __isl_give isl_ast_build *isl_ast_build_init_derived(
 {
 	isl_ctx *ctx;
 	isl_vec *strides;
+	isl_size dim;
 
 	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));
+	dim = isl_space_dim(space, isl_dim_set);
+	if (dim < 0)
+		goto error;
+	strides = isl_vec_alloc(ctx, dim);
 	strides = isl_vec_set_si(strides, 1);
 
 	isl_vec_free(build->strides);
@@ -114,14 +118,16 @@ static __isl_give isl_id *generate_name(isl_ctx *ctx, int i,
  */
 __isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_space *space;
 	isl_ast_build *build;
 
 	set = isl_set_compute_divs(set);
-	if (!set)
-		return NULL;
+	n = isl_set_dim(set, isl_dim_set);
+	if (n < 0)
+		goto error;
 
 	ctx = isl_set_get_ctx(set);
 
@@ -134,7 +140,6 @@ __isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *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) {
@@ -358,14 +363,16 @@ __isl_give isl_ast_build *isl_ast_build_set_options(
 __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;
+	isl_size dim, n_it;
 
 	build = isl_ast_build_cow(build);
 	if (!build)
 		goto error;
 
-	dim = isl_set_dim(build->domain, isl_dim_set);
+	dim = isl_ast_build_dim(build, isl_dim_set);
 	n_it = isl_id_list_n_id(build->iterators);
+	if (dim < 0 || n_it < 0)
+		goto error;
 	if (n_it < dim)
 		isl_die(isl_ast_build_get_ctx(build), isl_error_internal,
 			"isl_ast_build in inconsistent state", goto error);
@@ -562,15 +569,14 @@ static void isl_ast_build_reset_schedule_map(__isl_keep isl_ast_build *build)
  * 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)
+isl_bool isl_ast_build_need_schedule_map(__isl_keep isl_ast_build *build)
 {
-	int dim;
-
-	if (!build)
-		return -1;
+	isl_size dim;
 
-	dim = isl_set_dim(build->domain, isl_dim_set);
-	return build->depth != dim || any_eliminated(build);
+	dim = isl_ast_build_dim(build, isl_dim_set);
+	if (dim < 0)
+		return isl_bool_error;
+	return isl_bool_ok(build->depth != dim || any_eliminated(build));
 }
 
 /* Return a mapping from the internal schedule space to the external
@@ -594,6 +600,7 @@ __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_bool needs_map;
 	isl_space *space;
 	isl_multi_aff *ma;
 
@@ -601,13 +608,19 @@ __isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff(
 		return NULL;
 	if (build->schedule_map)
 		return isl_multi_aff_copy(build->schedule_map);
+	needs_map = isl_ast_build_need_schedule_map(build);
+	if (needs_map < 0)
+		return NULL;
 
 	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)) {
+	if (needs_map) {
 		int i;
-		int dim = isl_set_dim(build->domain, isl_dim_set);
+		isl_size dim = isl_ast_build_dim(build, isl_dim_set);
+
+		if (dim < 0)
+			ma = isl_multi_aff_free(ma);
 		ma = isl_multi_aff_drop_dims(ma, isl_dim_out,
 					build->depth, dim - build->depth);
 		for (i = build->depth - 1; i >= 0; --i)
@@ -762,7 +775,8 @@ static __isl_give isl_set *intersect_stride_constraint(__isl_take isl_set *set,
 static __isl_give isl_ast_build *update_values(
 	__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
 {
-	int sv;
+	isl_bool sv;
+	isl_size n;
 	isl_pw_multi_aff *pma;
 	isl_aff *aff = NULL;
 	isl_map *it_map;
@@ -787,10 +801,10 @@ static __isl_give isl_ast_build *update_values(
 	build->value = isl_pw_aff_coalesce(build->value);
 	isl_pw_multi_aff_free(pma);
 
-	if (!build->value)
+	n = isl_pw_aff_n_piece(build->value);
+	if (n < 0)
 		return isl_ast_build_free(build);
-
-	if (isl_pw_aff_n_piece(build->value) != 1)
+	if (n != 1)
 		return build;
 
 	isl_pw_aff_foreach_piece(build->value, &extract_single_piece, &aff);
@@ -992,15 +1006,24 @@ __isl_give isl_ast_build *isl_ast_build_replace_pending_by_guard(
 __isl_give isl_ast_build *isl_ast_build_restrict(
 	__isl_take isl_ast_build *build, __isl_take isl_set *set)
 {
+	isl_bool needs_map;
+
 	if (isl_set_is_params(set))
 		return isl_ast_build_restrict_generated(build, set);
 
-	if (isl_ast_build_need_schedule_map(build)) {
+	needs_map = isl_ast_build_need_schedule_map(build);
+	if (needs_map < 0)
+		goto error;
+	if (needs_map) {
 		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);
+error:
+	isl_ast_build_free(build);
+	isl_set_free(set);
+	return NULL;
 }
 
 /* Replace build->executed by "executed".
@@ -1049,18 +1072,22 @@ static __isl_give isl_ast_build *extract_loop_types(
 	__isl_take isl_ast_build *build)
 {
 	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_schedule_node *node;
 
 	if (!build)
 		return NULL;
+	n = isl_schedule_node_band_n_member(build->node);
+	if (n < 0)
+		return isl_ast_build_free(build);
 	ctx = isl_ast_build_get_ctx(build);
 	if (!build->node)
 		isl_die(ctx, isl_error_internal, "missing AST node",
 			return isl_ast_build_free(build));
 
 	free(build->loop_type);
-	build->n = isl_schedule_node_band_n_member(build->node);
+	build->n = n;
 	build->loop_type = isl_alloc_array(ctx,
 					    enum isl_ast_loop_type, build->n);
 	if (build->n && !build->loop_type)
@@ -1146,11 +1173,11 @@ __isl_give isl_multi_aff *isl_ast_build_get_internal2input(
 /* 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,
+isl_size isl_ast_build_dim(__isl_keep isl_ast_build *build,
 	enum isl_dim_type type)
 {
 	if (!build)
-		return 0;
+		return isl_size_error;
 	return isl_set_dim(build->domain, type);
 }
 
@@ -1167,7 +1194,8 @@ __isl_give isl_space *isl_ast_build_get_space(__isl_keep isl_ast_build *build,
 	int internal)
 {
 	int i;
-	int dim;
+	isl_size dim;
+	isl_bool needs_map;
 	isl_space *space;
 
 	if (!build)
@@ -1177,10 +1205,15 @@ __isl_give isl_space *isl_ast_build_get_space(__isl_keep isl_ast_build *build,
 	if (internal)
 		return space;
 
-	if (!isl_ast_build_need_schedule_map(build))
+	needs_map = isl_ast_build_need_schedule_map(build);
+	if (needs_map < 0)
+		return isl_space_free(space);
+	if (!needs_map)
 		return space;
 
-	dim = isl_set_dim(build->domain, isl_dim_set);
+	dim = isl_ast_build_dim(build, isl_dim_set);
+	if (dim < 0)
+		return isl_space_free(space);
 	space = isl_space_drop_dims(space, isl_dim_set,
 				    build->depth, dim - build->depth);
 	for (i = build->depth - 1; i >= 0; --i) {
@@ -1232,14 +1265,16 @@ __isl_give isl_space *isl_ast_build_get_schedule_space(
 __isl_give isl_union_map *isl_ast_build_get_schedule(
 	__isl_keep isl_ast_build *build)
 {
+	isl_bool needs_map;
 	isl_union_map *executed;
 	isl_union_map *schedule;
 
-	if (!build)
+	needs_map = isl_ast_build_need_schedule_map(build);
+	if (needs_map < 0)
 		return NULL;
 
 	executed = isl_union_map_copy(build->executed);
-	if (isl_ast_build_need_schedule_map(build)) {
+	if (needs_map) {
 		isl_map *proj = isl_ast_build_get_schedule_map(build);
 		executed = isl_union_map_apply_domain(executed,
 					isl_union_map_from_map(proj));
@@ -1820,7 +1855,7 @@ __isl_give isl_ast_build *isl_ast_build_product(
 	isl_vec *strides;
 	isl_set *set;
 	isl_multi_aff *embedding;
-	int dim, n_it;
+	isl_size dim, space_dim, n_it;
 
 	build = isl_ast_build_cow(build);
 	if (!build)
@@ -1829,9 +1864,12 @@ __isl_give isl_ast_build *isl_ast_build_product(
 	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);
+	dim = isl_ast_build_dim(build, isl_dim_set);
+	space_dim = isl_space_dim(space, isl_dim_set);
 	n_it = isl_id_list_n_id(build->iterators);
+	if (dim < 0 || space_dim < 0 || n_it < 0)
+		goto error;
+	dim += space_dim;
 	if (n_it < dim) {
 		isl_id_list *l;
 		l = generate_names(ctx, dim - n_it, n_it, build);
@@ -1846,7 +1884,7 @@ __isl_give isl_ast_build *isl_ast_build_product(
 	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_alloc(ctx, space_dim);
 	strides = isl_vec_set_si(strides, 1);
 	build->strides = isl_vec_concat(build->strides, strides);
 

diff  --git a/polly/lib/External/isl/isl_ast_build_expr.c b/polly/lib/External/isl/isl_ast_build_expr.c
index ddac02146843..769d56fd36a9 100644
--- a/polly/lib/External/isl/isl_ast_build_expr.c
+++ b/polly/lib/External/isl/isl_ast_build_expr.c
@@ -188,14 +188,14 @@ static __isl_give isl_ast_expr *var_div(struct isl_ast_add_term_data *data,
 	isl_aff *aff;
 	isl_ast_expr *num, *den;
 	isl_val *d;
-	enum isl_ast_op_type type;
+	enum isl_ast_expr_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;
+	type = isl_ast_expr_op_fdiv_q;
 	if (isl_options_get_ast_build_prefer_pdiv(ctx)) {
 		int non_neg = isl_ast_build_aff_is_nonneg(data->build, aff);
 		if (non_neg >= 0 && !non_neg) {
@@ -217,7 +217,7 @@ static __isl_give isl_ast_expr *var_div(struct isl_ast_add_term_data *data,
 		if (non_neg < 0)
 			aff = isl_aff_free(aff);
 		else if (non_neg)
-			type = isl_ast_op_pdiv_q;
+			type = isl_ast_expr_op_pdiv_q;
 	}
 
 	isl_val_free(d);
@@ -297,11 +297,11 @@ static __isl_give isl_ast_expr *ast_expr_add(__isl_take isl_ast_expr *expr1,
  * If expr2 is zero, we simply return expr1.
  * If expr1 is zero, we return
  *
- *	(isl_ast_op_minus, expr2)
+ *	(isl_ast_expr_op_minus, expr2)
  *
  * Otherwise, we return
  *
- *	(isl_ast_op_sub, expr1, expr2)
+ *	(isl_ast_expr_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)
@@ -346,7 +346,7 @@ static __isl_give isl_ast_expr *isl_ast_expr_mod(__isl_keep isl_val *v,
 	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);
+	expr = isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_r, expr, c);
 
 	if (!isl_val_is_one(v)) {
 		c = isl_ast_expr_from_val(isl_val_copy(v));
@@ -361,11 +361,11 @@ static __isl_give isl_ast_expr *isl_ast_expr_mod(__isl_keep isl_val *v,
  * If v is 1, we simply return expr.
  * If v is -1, we return
  *
- *	(isl_ast_op_minus, expr)
+ *	(isl_ast_expr_op_minus, expr)
  *
  * Otherwise, we return
  *
- *	(isl_ast_op_mul, expr(v), expr)
+ *	(isl_ast_expr_op_mul, expr(v), expr)
  */
 static __isl_give isl_ast_expr *scale(__isl_take isl_ast_expr *expr,
 	__isl_take isl_val *v)
@@ -404,17 +404,17 @@ static __isl_give isl_ast_expr *scale(__isl_take isl_ast_expr *expr,
  * multiplied by the absolute value of "*v".
  * If "*v" is negative, we create
  *
- *	(isl_ast_op_sub, expr, e)
+ *	(isl_ast_expr_op_sub, expr, e)
  *
  * except when expr is trivially zero, in which case we create
  *
- *	(isl_ast_op_minus, e)
+ *	(isl_ast_expr_op_minus, e)
  *
  * instead.
  *
  * If "*v" is positive, we simply create
  *
- *	(isl_ast_op_add, expr, e)
+ *	(isl_ast_expr_op_add, expr, e)
  *
  */
 static __isl_give isl_ast_expr *isl_ast_expr_add_term(
@@ -679,11 +679,13 @@ static isl_stat check_parallel_or_opposite(__isl_take isl_constraint *c,
 	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];
+	isl_size n[2];
 	int parallel = 1, opposite = 1;
 
 	for (t = 0; t < 2; ++t) {
 		n[t] = isl_constraint_dim(c, c_type[t]);
+		if (n[t] < 0)
+			return isl_stat_error;
 		for (i = 0; i < n[t]; ++i) {
 			int a, b;
 
@@ -824,12 +826,15 @@ static int try_extract_mod(struct isl_extract_mod_data *data)
 {
 	isl_basic_set *hull;
 	isl_val *v1, *v2;
-	int r, n;
+	isl_stat r;
+	isl_size n;
 
 	if (!data->build)
 		goto error;
 
 	n = isl_aff_dim(data->div, isl_dim_div);
+	if (n < 0)
+		goto error;
 
 	if (isl_aff_involves_dims(data->div, isl_dim_div, 0, n))
 		return extract_nonneg_mod(data);
@@ -901,7 +906,7 @@ static int try_extract_mod(struct isl_extract_mod_data *data)
  *
  * Note that in order to represent "a mod m" as
  *
- *	(isl_ast_op_pdiv_r, a, m)
+ *	(isl_ast_expr_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.
@@ -954,7 +959,7 @@ static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
 {
 	struct isl_extract_mod_data data = { build, aff, *pos, *neg };
 	isl_ctx *ctx;
-	int n;
+	isl_size n;
 
 	if (!aff)
 		return NULL;
@@ -964,6 +969,8 @@ static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
 		return aff;
 
 	n = isl_aff_dim(data.aff, isl_dim_div);
+	if (n < 0)
+		return isl_aff_free(aff);
 	for (data.i = 0; data.i < n; ++data.i) {
 		data.v = isl_aff_get_coefficient_val(data.aff,
 							isl_dim_div, data.i);
@@ -1000,7 +1007,8 @@ static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
 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;
+	int i, j;
+	isl_size n;
 	isl_aff *rat = NULL;
 	isl_local_space *ls = NULL;
 	isl_ast_expr *rat_expr;
@@ -1025,6 +1033,8 @@ static __isl_give isl_aff *extract_rational(__isl_take isl_aff *aff,
 
 	for (i = 0; i < 3; ++i) {
 		n = isl_aff_dim(aff, t[i]);
+		if (n < 0)
+			goto error;
 		for (j = 0; j < n; ++j) {
 			isl_aff *rat_j;
 
@@ -1082,7 +1092,7 @@ __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_size n;
 	isl_val *v;
 	isl_ctx *ctx = isl_aff_get_ctx(aff);
 	isl_ast_expr *expr, *expr_neg;
@@ -1108,6 +1118,8 @@ __isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
 	data.cst = isl_aff_get_constant_val(aff);
 	for (i = 0; i < 3; ++i) {
 		n = isl_aff_dim(aff, t[i]);
+		if (n < 0)
+			expr = isl_ast_expr_free(expr);
 		for (j = 0; j < n; ++j) {
 			v = isl_aff_get_coefficient_val(aff, t[i], j);
 			if (!v)
@@ -1144,7 +1156,9 @@ static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
 	ls = isl_aff_get_domain_local_space(aff);
 
 	for (i = 0; i < 3; ++i) {
-		int n = isl_aff_dim(aff, t[i]);
+		isl_size n = isl_aff_dim(aff, t[i]);
+		if (n < 0)
+			expr = isl_ast_expr_free(expr);
 		for (j = 0; j < n; ++j) {
 			v = isl_aff_get_coefficient_val(aff, t[i], j);
 			if (sign * isl_val_sgn(v) <= 0) {
@@ -1235,24 +1249,26 @@ static int is_stride_constraint(__isl_keep isl_aff *aff, int pos)
 
 /* Are all coefficients of "aff" (zero or) negative?
  */
-static int all_negative_coefficients(__isl_keep isl_aff *aff)
+static isl_bool all_negative_coefficients(__isl_keep isl_aff *aff)
 {
-	int i, n;
-
-	if (!aff)
-		return 0;
+	int i;
+	isl_size n;
 
 	n = isl_aff_dim(aff, isl_dim_param);
+	if (n < 0)
+		return isl_bool_error;
 	for (i = 0; i < n; ++i)
 		if (isl_aff_coefficient_sgn(aff, isl_dim_param, i) > 0)
-			return 0;
+			return isl_bool_false;
 
 	n = isl_aff_dim(aff, isl_dim_in);
+	if (n < 0)
+		return isl_bool_error;
 	for (i = 0; i < n; ++i)
 		if (isl_aff_coefficient_sgn(aff, isl_dim_in, i) > 0)
-			return 0;
+			return isl_bool_false;
 
-	return 1;
+	return isl_bool_true;
 }
 
 /* Give an equality of the form
@@ -1266,17 +1282,20 @@ static int all_negative_coefficients(__isl_keep isl_aff *aff)
  * 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))
+ *	(isl_ast_expr_op_eq,
+ *		(isl_ast_expr_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))
+ *	(isl_ast_expr_op_eq,
+ *		(isl_ast_expr_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_bool all_neg;
 	isl_ctx *ctx;
 	isl_val *c;
 	isl_ast_expr *expr, *cst;
@@ -1289,15 +1308,18 @@ static __isl_give isl_ast_expr *extract_stride_constraint(
 	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))
+	all_neg = all_negative_coefficients(aff);
+	if (all_neg < 0)
+		aff = isl_aff_free(aff);
+	else if (all_neg)
 		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);
+	expr = isl_ast_expr_alloc_binary(isl_ast_expr_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);
+	expr = isl_ast_expr_alloc_binary(isl_ast_expr_op_eq, expr, cst);
 
 	return expr;
 }
@@ -1315,7 +1337,8 @@ static __isl_give isl_ast_expr *extract_stride_constraint(
  *
  * If so, we convert it to
  *
- *	(isl_ast_op_eq, (isl_ast_op_zdiv_r, expr(e), expr(d)), expr(0))
+ *	(isl_ast_expr_op_eq,
+ *		(isl_ast_expr_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"
@@ -1324,11 +1347,11 @@ static __isl_give isl_ast_expr *extract_stride_constraint(
  *
  * The result is then of the form
  *
- *	(isl_ast_op_ge, expr(pos), expr(-neg)))
+ *	(isl_ast_expr_op_ge, expr(pos), expr(-neg)))
  *
  * or
  *
- *	(isl_ast_op_eq, expr(pos), expr(-neg)))
+ *	(isl_ast_expr_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,
@@ -1341,14 +1364,15 @@ static __isl_give isl_ast_expr *extract_stride_constraint(
 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;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_ast_expr *expr_pos;
 	isl_ast_expr *expr_neg;
 	isl_ast_expr *expr;
 	isl_aff *aff;
 	int eq;
-	enum isl_ast_op_type type;
+	enum isl_ast_expr_op_type type;
 	struct isl_ast_add_term_data data;
 
 	if (!constraint)
@@ -1359,6 +1383,8 @@ static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
 	isl_constraint_free(constraint);
 
 	n = isl_aff_dim(aff, isl_dim_div);
+	if (n < 0)
+		aff = isl_aff_free(aff);
 	if (eq && n > 0)
 		for (i = 0; i < n; ++i) {
 			int is_stride;
@@ -1391,10 +1417,10 @@ static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
 
 	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;
+		type = eq ? isl_ast_expr_op_eq : isl_ast_expr_op_le;
 		expr = isl_ast_expr_alloc_binary(type, expr_neg, expr_pos);
 	} else {
-		type = eq ? isl_ast_op_eq : isl_ast_op_ge;
+		type = eq ? isl_ast_expr_op_eq : isl_ast_expr_op_ge;
 		expr = isl_ast_expr_alloc_binary(type, expr_pos, expr_neg);
 	}
 
@@ -1444,7 +1470,8 @@ static int cmp_constraint(__isl_keep isl_constraint *a,
 __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;
+	int i;
+	isl_size n;
 	isl_constraint *c;
 	isl_constraint_list *list;
 	isl_ast_expr *res;
@@ -1453,9 +1480,9 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_basic_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)
+		build = NULL;
 	if (n == 0) {
 		isl_ctx *ctx = isl_constraint_list_get_ctx(list);
 		isl_constraint_list_free(list);
@@ -1510,7 +1537,8 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
 __isl_give isl_ast_expr *isl_ast_build_expr_from_set_internal(
 	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_basic_set *bset;
 	isl_basic_set_list *list;
 	isl_set *domain;
@@ -1519,9 +1547,9 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_set_internal(
 	list = isl_set_get_basic_set_list(set);
 	isl_set_free(set);
 
-	if (!list)
-		return NULL;
 	n = isl_basic_set_list_n_basic_set(list);
+	if (n < 0)
+		build = NULL;
 	if (n == 0) {
 		isl_ctx *ctx = isl_ast_build_get_ctx(build);
 		isl_basic_set_list_free(list);
@@ -1570,7 +1598,12 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_set_internal(
 __isl_give isl_ast_expr *isl_ast_build_expr_from_set(
 	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
 {
-	if (isl_ast_build_need_schedule_map(build)) {
+	isl_bool needs_map;
+
+	needs_map = isl_ast_build_need_schedule_map(build);
+	if (needs_map < 0) {
+		set = isl_set_free(set);
+	} else if (needs_map) {
 		isl_multi_aff *ma;
 		ma = isl_ast_build_get_schedule_map_multi_aff(build);
 		set = isl_set_preimage_multi_aff(set, ma);
@@ -1646,11 +1679,13 @@ struct isl_from_pw_aff_data {
 static isl_stat isl_from_pw_aff_data_init(struct isl_from_pw_aff_data *data,
 	__isl_keep isl_ast_build *build, __isl_keep isl_pw_aff *pa)
 {
-	int n;
+	isl_size n;
 	isl_ctx *ctx;
 
 	ctx = isl_pw_aff_get_ctx(pa);
 	n = isl_pw_aff_n_piece(pa);
+	if (n < 0)
+		return isl_stat_error;
 	if (n == 0)
 		isl_die(ctx, isl_error_invalid,
 			"cannot handle void expression", return isl_stat_error);
@@ -1771,10 +1806,11 @@ static __isl_give isl_ast_expr *ast_expr_from_aff_list(
 	__isl_take isl_aff_list *list, enum isl_from_pw_aff_state state,
 	__isl_keep isl_ast_build *build)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_aff *aff;
-	isl_ast_expr *expr;
-	enum isl_ast_op_type op_type;
+	isl_ast_expr *expr = NULL;
+	enum isl_ast_expr_op_type op_type;
 
 	if (state == isl_state_single) {
 		aff = isl_aff_list_get_aff(list, 0);
@@ -1782,7 +1818,10 @@ static __isl_give isl_ast_expr *ast_expr_from_aff_list(
 		return isl_ast_expr_from_aff(aff, build);
 	}
 	n = isl_aff_list_n_aff(list);
-	op_type = state == isl_state_min ? isl_ast_op_min : isl_ast_op_max;
+	if (n < 0)
+		goto error;
+	op_type = state == isl_state_min ? isl_ast_expr_op_min
+					 : isl_ast_expr_op_max;
 	expr = isl_ast_expr_alloc_op(isl_ast_build_get_ctx(build), op_type, n);
 	if (!expr)
 		goto error;
@@ -1829,7 +1868,7 @@ static isl_ast_expr **add_intermediate_piece(struct isl_from_pw_aff_data *data,
 	set = data->p[pos].set;
 	data->p[pos].set = NULL;
 	ctx = isl_ast_build_get_ctx(data->build);
-	ternary = isl_ast_expr_alloc_op(ctx, isl_ast_op_select, 3);
+	ternary = isl_ast_expr_alloc_op(ctx, isl_ast_expr_op_select, 3);
 	gist = isl_set_gist(isl_set_copy(set), isl_set_copy(data->dom));
 	arg = isl_ast_build_expr_from_set_internal(data->build, gist);
 	ternary = isl_ast_expr_set_op_arg(ternary, 0, arg);
@@ -1892,7 +1931,7 @@ static int sort_pieces_cmp(const void *p1, const void *p2, void *arg)
 {
 	const struct isl_from_pw_aff_piece *piece1 = p1;
 	const struct isl_from_pw_aff_piece *piece2 = p2;
-	int n1, n2;
+	isl_size n1, n2;
 
 	n1 = isl_set_n_basic_set(piece1->set);
 	n2 = isl_set_n_basic_set(piece2->set);
@@ -1983,10 +2022,14 @@ static isl_bool aff_is_rational(__isl_keep isl_aff *aff)
  */
 static isl_bool is_single_rational_aff(__isl_keep isl_aff_list *list)
 {
+	isl_size n;
 	isl_bool rational;
 	isl_aff *aff;
 
-	if (isl_aff_list_n_aff(list) != 1)
+	n = isl_aff_list_n_aff(list);
+	if (n < 0)
+		return isl_bool_error;
+	if (n != 1)
 		return isl_bool_false;
 	aff = isl_aff_list_get_aff(list, 0);
 	rational = aff_is_rational(aff);
@@ -2019,7 +2062,8 @@ static isl_bool extends(struct isl_from_pw_aff_data *data,
 	__isl_give isl_basic_set *(*test)(__isl_take isl_aff *aff1,
 		__isl_take isl_aff *aff2))
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_bool is_rational;
 	isl_ctx *ctx;
 	isl_set *dom;
@@ -2034,10 +2078,13 @@ static isl_bool extends(struct isl_from_pw_aff_data *data,
 	if (!isl_options_get_ast_build_detect_min_max(ctx))
 		return isl_bool_false;
 
+	n = isl_set_list_n_set(data->p[data->n].set_list);
+	if (n < 0)
+		return isl_bool_error;
+
 	dom = isl_ast_build_get_domain(data->build);
 	set = isl_set_intersect(dom, isl_set_copy(set));
 
-	n = isl_set_list_n_set(data->p[data->n].set_list);
 	for (i = 0; i < n ; ++i) {
 		isl_aff *aff_i;
 		isl_set *valid;
@@ -2206,8 +2253,12 @@ __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;
+	isl_bool needs_map;
 
-	if (isl_ast_build_need_schedule_map(build)) {
+	needs_map = isl_ast_build_need_schedule_map(build);
+	if (needs_map < 0) {
+		pa = isl_pw_aff_free(pa);
+	} else if (needs_map) {
 		isl_multi_aff *ma;
 		ma = isl_ast_build_get_schedule_map_multi_aff(build);
 		pa = isl_pw_aff_pullback_multi_aff(pa, ma);
@@ -2224,9 +2275,12 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
 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;
+	int i;
+	isl_size n;
 
 	n = isl_multi_pw_aff_dim(mpa, isl_dim_in);
+	if (n < 0)
+		return isl_multi_pw_aff_free(mpa);
 	for (i = 0; i < n; ++i) {
 		isl_id *id;
 
@@ -2243,17 +2297,18 @@ static __isl_give isl_multi_pw_aff *set_iterator_names(
  * 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_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
 	__isl_take isl_ast_expr *arg0, __isl_take isl_multi_pw_aff *mpa)
 {
-	int i, n;
+	int i;
+	isl_size 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 = n >= 0 ? isl_ast_expr_alloc_op(ctx, type, 1 + n) : NULL;
 	expr = isl_ast_expr_set_op_arg(expr, 0, arg0);
 	for (i = 0; i < n; ++i) {
 		isl_pw_aff *pa;
@@ -2269,7 +2324,7 @@ static __isl_give isl_ast_expr *isl_ast_build_with_arguments(
 }
 
 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_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
 	__isl_take isl_multi_pw_aff *mpa);
 
 /* Construct an isl_ast_expr that accesses the member specified by "mpa".
@@ -2286,7 +2341,7 @@ static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_member(
 	isl_id *id;
 	isl_multi_pw_aff *domain;
 	isl_ast_expr *domain_expr, *expr;
-	enum isl_ast_op_type type = isl_ast_op_access;
+	enum isl_ast_expr_op_type type = isl_ast_expr_op_access;
 
 	domain = isl_multi_pw_aff_copy(mpa);
 	domain = isl_multi_pw_aff_range_factor_domain(domain);
@@ -2298,7 +2353,8 @@ static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_member(
 			"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);
+	expr = isl_ast_expr_alloc_binary(isl_ast_expr_op_member,
+					domain_expr, expr);
 	return isl_ast_build_with_arguments(build, type, expr, mpa);
 error:
 	isl_multi_pw_aff_free(mpa);
@@ -2316,7 +2372,7 @@ static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_member(
  * 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_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
 	__isl_take isl_multi_pw_aff *mpa)
 {
 	isl_ctx *ctx;
@@ -2326,7 +2382,7 @@ static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
 	if (!mpa)
 		goto error;
 
-	if (type == isl_ast_op_access &&
+	if (type == isl_ast_expr_op_access &&
 	    isl_multi_pw_aff_range_is_wrapping(mpa))
 		return isl_ast_build_from_multi_pw_aff_member(build, mpa);
 
@@ -2356,7 +2412,7 @@ static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
  * 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_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
 	__isl_take isl_pw_multi_aff *pma)
 {
 	isl_multi_pw_aff *mpa;
@@ -2373,10 +2429,11 @@ static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff_internal(
  * 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_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
 	__isl_take isl_multi_pw_aff *mpa)
 {
-	int is_domain;
+	isl_bool is_domain;
+	isl_bool needs_map;
 	isl_ast_expr *expr;
 	isl_space *space_build, *space_mpa;
 
@@ -2392,7 +2449,10 @@ static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff(
 		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)) {
+	needs_map = isl_ast_build_need_schedule_map(build);
+	if (needs_map < 0)
+		goto error;
+	if (needs_map) {
 		isl_multi_aff *ma;
 		ma = isl_ast_build_get_schedule_map_multi_aff(build);
 		mpa = isl_multi_pw_aff_pullback_multi_aff(mpa, ma);
@@ -2414,7 +2474,8 @@ static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff(
 __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);
+	return isl_ast_build_from_multi_pw_aff(build,
+						isl_ast_expr_op_call, mpa);
 }
 
 /* Construct an isl_ast_expr that accesses the array element specified by "mpa".
@@ -2426,7 +2487,8 @@ __isl_give isl_ast_expr *isl_ast_build_call_from_multi_pw_aff(
 __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);
+	return isl_ast_build_from_multi_pw_aff(build,
+						isl_ast_expr_op_access, mpa);
 }
 
 /* Construct an isl_ast_expr of type "type" that calls or accesses
@@ -2437,7 +2499,7 @@ __isl_give isl_ast_expr *isl_ast_build_access_from_multi_pw_aff(
  * 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_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
 	__isl_take isl_pw_multi_aff *pma)
 {
 	isl_multi_pw_aff *mpa;
@@ -2455,7 +2517,8 @@ static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff(
 __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);
+	return isl_ast_build_from_pw_multi_aff(build,
+						isl_ast_expr_op_call, pma);
 }
 
 /* Construct an isl_ast_expr that accesses the array element specified by "pma".
@@ -2467,7 +2530,8 @@ __isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
 __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);
+	return isl_ast_build_from_pw_multi_aff(build,
+						isl_ast_expr_op_access, pma);
 }
 
 /* Construct an isl_ast_expr that calls the domain element
@@ -2486,7 +2550,7 @@ __isl_give isl_ast_node *isl_ast_build_call_from_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);
+	expr = isl_ast_build_from_pw_multi_aff_internal(build,
+					isl_ast_expr_op_call, iteration);
 	return isl_ast_node_alloc_user(expr);
 }

diff  --git a/polly/lib/External/isl/isl_ast_build_private.h b/polly/lib/External/isl/isl_ast_build_private.h
index 0d256af3066a..9767679fe3b9 100644
--- a/polly/lib/External/isl/isl_ast_build_private.h
+++ b/polly/lib/External/isl/isl_ast_build_private.h
@@ -204,7 +204,7 @@ __isl_give isl_ast_build *isl_ast_build_clear_local_info(
 __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,
+isl_size 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);
@@ -244,8 +244,7 @@ __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 int isl_ast_build_need_schedule_map(
-	__isl_keep isl_ast_build *build);
+isl_bool 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(

diff  --git a/polly/lib/External/isl/isl_ast_codegen.c b/polly/lib/External/isl/isl_ast_codegen.c
index 1dcc9f2d7de2..89cc725c8889 100644
--- a/polly/lib/External/isl/isl_ast_codegen.c
+++ b/polly/lib/External/isl/isl_ast_codegen.c
@@ -529,14 +529,15 @@ static int reduce_list_cmp(__isl_keep isl_pw_aff *a, __isl_keep isl_pw_aff *b,
 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;
+	int i, j;
+	isl_size 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 < 0)
+		return isl_pw_aff_list_free(list);
 	if (n <= 1)
 		return list;
 
@@ -600,12 +601,15 @@ static __isl_give isl_pw_aff_list *lower_bounds(
 {
 	isl_ctx *ctx;
 	isl_pw_aff_list *list;
-	int i, n;
+	int i;
+	isl_size n;
 
 	if (!build)
 		return NULL;
 
 	n = isl_constraint_list_n_constraint(constraints);
+	if (n < 0)
+		return NULL;
 	if (n == 0) {
 		isl_pw_aff *pa;
 		pa = exact_bound(domain, build, 0);
@@ -642,9 +646,12 @@ static __isl_give isl_pw_aff_list *upper_bounds(
 {
 	isl_ctx *ctx;
 	isl_pw_aff_list *list;
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_constraint_list_n_constraint(constraints);
+	if (n < 0)
+		return NULL;
 	if (n == 0) {
 		isl_pw_aff *pa;
 		pa = exact_bound(domain, build, 1);
@@ -675,19 +682,19 @@ static __isl_give isl_pw_aff_list *upper_bounds(
  * 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.
+ * using a fairly arbitrary but hopefully reasonably stable order.
  */
-static __isl_give isl_ast_expr *reduce_list(enum isl_ast_op_type type,
+static __isl_give isl_ast_expr *reduce_list(enum isl_ast_expr_op_type type,
 	__isl_keep isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_ast_expr *expr;
 
-	if (!list)
-		return NULL;
-
 	n = isl_pw_aff_list_n_pw_aff(list);
+	if (n < 0)
+		return NULL;
 
 	if (n == 1)
 		return isl_ast_build_expr_from_pw_aff_internal(build,
@@ -803,10 +810,13 @@ static __isl_give isl_ast_graft *refine_degenerate(
 static __isl_give isl_set *intersect_constraints(
 	__isl_keep isl_constraint_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_basic_set *bset;
 
 	n = isl_constraint_list_n_constraint(list);
+	if (n < 0)
+		return NULL;
 	if (n < 1)
 		isl_die(isl_constraint_list_get_ctx(list), isl_error_internal,
 			"expecting at least one constraint", return NULL);
@@ -859,9 +869,11 @@ static __isl_give isl_ast_graft *set_enforced_from_set(
 	isl_space *space;
 	isl_basic_set *enforced;
 	isl_pw_multi_aff *pma;
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!graft || !lower)
+	n = isl_pw_aff_list_n_pw_aff(lower);
+	if (!graft || n < 0)
 		return isl_ast_graft_free(graft);
 
 	space = isl_set_get_space(upper);
@@ -870,7 +882,6 @@ static __isl_give isl_ast_graft *set_enforced_from_set(
 	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;
@@ -971,17 +982,21 @@ static int list_constant_is_negative(__isl_keep isl_pw_aff_list *list)
 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;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_aff *aff;
 	isl_pw_aff *one;
 
+	n = isl_pw_aff_list_n_pw_aff(list);
+	if (n < 0)
+		return isl_pw_aff_list_free(list);
+
 	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);
@@ -1013,7 +1028,7 @@ static __isl_give isl_ast_graft *set_for_cond_from_list(
 {
 	int neg;
 	isl_ast_expr *bound, *iterator, *cond;
-	enum isl_ast_op_type type = isl_ast_op_le;
+	enum isl_ast_expr_op_type type = isl_ast_expr_op_le;
 
 	if (!graft || !list)
 		return isl_ast_graft_free(graft);
@@ -1024,10 +1039,10 @@ static __isl_give isl_ast_graft *set_for_cond_from_list(
 	list = isl_pw_aff_list_copy(list);
 	if (neg) {
 		list = list_add_one(list, build);
-		type = isl_ast_op_lt;
+		type = isl_ast_expr_op_lt;
 	}
 
-	bound = reduce_list(isl_ast_op_min, list, build);
+	bound = reduce_list(isl_ast_expr_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;
@@ -1127,7 +1142,7 @@ static __isl_give isl_ast_graft *set_for_node_expressions(
 	build = isl_ast_build_copy(build);
 
 	node = graft->node;
-	node->u.f.init = reduce_list(isl_ast_op_max, lower, build);
+	node->u.f.init = reduce_list(isl_ast_expr_op_max, lower, build);
 	node->u.f.inc = for_inc(build);
 
 	if (!node->u.f.init || !node->u.f.inc)
@@ -1186,7 +1201,7 @@ static __isl_give isl_ast_graft *refine_generic_bounds(
 	int use_list;
 	isl_set *upper_set = NULL;
 	isl_pw_aff_list *upper_list = NULL;
-	int n_lower, n_upper;
+	isl_size n_lower, n_upper;
 
 	if (!graft || !c_lower || !c_upper || !build)
 		goto error;
@@ -1196,6 +1211,8 @@ static __isl_give isl_ast_graft *refine_generic_bounds(
 
 	n_lower = isl_constraint_list_n_constraint(c_lower);
 	n_upper = isl_constraint_list_n_constraint(c_upper);
+	if (n_lower < 0 || n_upper < 0)
+		goto error;
 
 	use_list = use_upper_bound_list(ctx, n_upper, domain, depth);
 
@@ -1478,6 +1495,7 @@ static __isl_give isl_ast_graft *create_node_scaled(
 	int depth;
 	int degenerate;
 	isl_bool eliminated;
+	isl_size n;
 	isl_basic_set *hull;
 	isl_basic_set *enforced;
 	isl_set *guard, *hoisted;
@@ -1522,7 +1540,10 @@ static __isl_give isl_ast_graft *create_node_scaled(
 	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)
+	n = isl_set_n_basic_set(hoisted);
+	if (n < 0)
+		children = isl_ast_graft_list_free(children);
+	if (n > 1)
 		children = isl_ast_graft_list_gist_guards(children,
 						    isl_set_copy(hoisted));
 	guard = isl_set_intersect(guard, hoisted);
@@ -1579,7 +1600,8 @@ static isl_stat constraint_check_scaled(__isl_take isl_constraint *c,
 	void *user)
 {
 	struct isl_check_scaled_data *data = user;
-	int i, j, n;
+	int i, j;
+	isl_size n;
 	enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_out,
 				    isl_dim_div };
 
@@ -1590,6 +1612,8 @@ static isl_stat constraint_check_scaled(__isl_take isl_constraint *c,
 
 	for (i = 0; i < 4; ++i) {
 		n = isl_constraint_dim(c, t[i]);
+		if (n < 0)
+			break;
 		for (j = 0; j < n; ++j) {
 			isl_val *d;
 
@@ -1770,16 +1794,18 @@ static isl_stat collect_basic_set(__isl_take isl_basic_set *bset, void *user)
 static __isl_give isl_basic_set_list *isl_basic_set_list_from_set(
 	__isl_take isl_set *set)
 {
-	int n;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_basic_set_list *list;
 
+	n = isl_set_n_basic_set(set);
+	if (n < 0)
+		set = isl_set_free(set);
 	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);
@@ -1869,7 +1895,7 @@ static isl_bool domain_follows_at_depth(__isl_keep isl_basic_set *i,
 	empty = isl_basic_map_is_empty(test);
 	isl_basic_map_free(test);
 
-	return empty < 0 ? isl_bool_error : !empty;
+	return isl_bool_not(empty);
 }
 
 /* Split up each element of "list" into a part that is related to "bset"
@@ -1880,15 +1906,16 @@ 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;
+	int i;
+	isl_size n;
 	isl_basic_set_list *res;
 
-	if (!list)
+	n = isl_basic_set_list_n_basic_set(list);
+	if (n < 0)
 		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;
@@ -1976,13 +2003,16 @@ struct isl_add_nodes_data {
 static isl_stat add_nodes(__isl_take isl_basic_set_list *scc, void *user)
 {
 	struct isl_add_nodes_data *data = user;
-	int i, n, depth;
+	int i, depth;
+	isl_size n;
 	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);
+	if (n < 0)
+		goto error;
 	bset = isl_basic_set_list_get_basic_set(scc, 0);
 	if (n == 1) {
 		isl_basic_set_list_free(scc);
@@ -2027,6 +2057,9 @@ static isl_stat add_nodes(__isl_take isl_basic_set_list *scc, void *user)
 	isl_basic_set_list_free(scc);
 
 	return data->list ? isl_stat_ok : isl_stat_error;
+error:
+	isl_basic_set_list_free(scc);
+	return isl_stat_error;
 }
 
 /* Sort the domains in "domain_list" according to the execution order
@@ -2049,13 +2082,13 @@ static __isl_give isl_ast_graft_list *generate_sorted_domains(
 	isl_ctx *ctx;
 	struct isl_add_nodes_data data;
 	int depth;
-	int n;
+	isl_size n;
 
-	if (!domain_list)
+	n = isl_basic_set_list_n_basic_set(domain_list);
+	if (n < 0)
 		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;
@@ -2093,7 +2126,7 @@ static isl_bool shared_outer(__isl_keep isl_basic_set *i,
 	empty = isl_basic_map_is_empty(test);
 	isl_basic_map_free(test);
 
-	return empty < 0 ? isl_bool_error : !empty;
+	return isl_bool_not(empty);
 }
 
 /* Internal data structure for generate_sorted_domains_wrap.
@@ -2107,7 +2140,7 @@ static isl_bool shared_outer(__isl_keep isl_basic_set *i,
  * "list" collects the results.
  */
 struct isl_ast_generate_parallel_domains_data {
-	int n;
+	isl_size n;
 	isl_union_map *executed;
 	isl_ast_build *build;
 
@@ -2129,9 +2162,13 @@ static isl_stat generate_sorted_domains_wrap(__isl_take isl_basic_set_list *scc,
 {
 	struct isl_ast_generate_parallel_domains_data *data = user;
 	isl_ast_graft_list *list;
+	isl_size n;
 
+	n = isl_basic_set_list_n_basic_set(scc);
+	if (n < 0)
+		scc = isl_basic_set_list_free(scc);
 	list = generate_sorted_domains(scc, data->executed, data->build);
-	data->single = isl_basic_set_list_n_basic_set(scc) == data->n;
+	data->single = n == data->n;
 	if (!data->single)
 		list = isl_ast_graft_list_fuse(list, data->build);
 	if (!data->list)
@@ -2169,10 +2206,10 @@ static __isl_give isl_ast_graft_list *generate_parallel_domains(
 	int depth;
 	struct isl_ast_generate_parallel_domains_data data;
 
-	if (!domain_list)
+	data.n = isl_basic_set_list_n_basic_set(domain_list);
+	if (data.n < 0)
 		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);
 
@@ -2232,9 +2269,12 @@ static __isl_give isl_set *explicit_bounds(__isl_take isl_map *map,
 	__isl_keep isl_ast_build *build)
 {
 	isl_set *domain;
-	int depth, dim;
+	int depth;
+	isl_size dim;
 
 	dim = isl_map_dim(map, isl_dim_out);
+	if (dim < 0)
+		return isl_map_domain(isl_map_free(map));
 	map = isl_map_drop_constraints_involving_dims(map, isl_dim_out, 0, dim);
 
 	domain = isl_map_domain(map);
@@ -2343,7 +2383,7 @@ static __isl_give isl_constraint *at_offset(int depth, __isl_keep isl_aff *aff,
 	return isl_equality_from_aff(aff);
 }
 
-/* Update *user to the number of integer divsions in the first element
+/* Update *user to the number of integer divisions in the first element
  * of "ma", if it is larger than the current value.
  */
 static isl_stat update_n_div(__isl_take isl_set *set,
@@ -2351,7 +2391,7 @@ static isl_stat update_n_div(__isl_take isl_set *set,
 {
 	isl_aff *aff;
 	int *n = user;
-	int n_div;
+	isl_size n_div;
 
 	aff = isl_multi_aff_get_aff(ma, 0);
 	n_div = isl_aff_dim(aff, isl_dim_div);
@@ -2362,7 +2402,7 @@ static isl_stat update_n_div(__isl_take isl_set *set,
 	if (n_div > *n)
 		*n = n_div;
 
-	return aff ? isl_stat_ok : isl_stat_error;
+	return n_div >= 0 ? isl_stat_ok : isl_stat_error;
 }
 
 /* Get the number of integer divisions in the expression for the iterator
@@ -2786,8 +2826,9 @@ static __isl_give isl_set *compute_unroll_domains(
 {
 	isl_set *unroll_domain;
 	isl_basic_set_list *unroll_list;
-	int i, n;
-	int empty;
+	int i;
+	isl_size n;
+	isl_bool empty;
 
 	empty = isl_set_is_empty(domains->option[isl_ast_loop_unroll]);
 	if (empty < 0)
@@ -2799,6 +2840,8 @@ static __isl_give isl_set *compute_unroll_domains(
 	unroll_list = isl_basic_set_list_from_set(unroll_domain);
 
 	n = isl_basic_set_list_n_basic_set(unroll_list);
+	if (n < 0)
+		class_domain = isl_set_free(class_domain);
 	for (i = 0; i < n; ++i) {
 		isl_basic_set *bset;
 
@@ -3083,7 +3126,7 @@ static __isl_give isl_basic_set_list *compute_domains(
 	isl_space *space;
 	int n_param;
 	enum isl_ast_loop_type type;
-	int empty;
+	isl_bool empty;
 
 	if (!executed)
 		return NULL;
@@ -3099,6 +3142,8 @@ static __isl_give isl_basic_set_list *compute_domains(
 	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);
+	if (n_param < 0)
+		classes = isl_set_free(classes);
 	classes = isl_set_project_out(classes, isl_dim_param, 0, n_param);
 
 	space = isl_set_get_space(domain);
@@ -3258,14 +3303,21 @@ static isl_bool has_pure_outer_disjunction(__isl_keep isl_set *domain,
 	isl_basic_set *hull;
 	isl_set *shared, *inner;
 	isl_bool equal;
-	int depth, dim;
+	int depth;
+	isl_size n;
+	isl_size dim;
 
-	if (isl_set_n_basic_set(domain) <= 1)
+	n = isl_set_n_basic_set(domain);
+	if (n < 0)
+		return isl_bool_error;
+	if (n <= 1)
 		return isl_bool_false;
+	dim = isl_set_dim(domain, isl_dim_set);
+	if (dim < 0)
+		return isl_bool_error;
 
 	inner = isl_set_copy(domain);
 	depth = isl_ast_build_get_depth(build);
-	dim = isl_set_dim(inner, isl_dim_set);
 	inner = isl_set_drop_constraints_not_involving_dims(inner,
 					    isl_dim_set, depth, dim - depth);
 	hull = isl_set_plain_unshifted_simple_hull(isl_set_copy(inner));
@@ -3375,11 +3427,14 @@ static __isl_give isl_set *extract_disjunction(__isl_take isl_set *domain,
 	__isl_keep isl_ast_build *build)
 {
 	isl_set *hull;
-	int depth, dim;
+	int depth;
+	isl_size dim;
 
 	domain = isl_ast_build_specialize(build, domain);
 	depth = isl_ast_build_get_depth(build);
 	dim = isl_set_dim(domain, isl_dim_set);
+	if (dim < 0)
+		return isl_set_free(domain);
 	domain = isl_set_eliminate(domain, isl_dim_set, depth, dim - depth);
 	domain = isl_set_remove_unknown_divs(domain);
 	hull = isl_set_copy(domain);
@@ -3402,10 +3457,14 @@ static __isl_give isl_ast_graft_list *list_add_guard(
 	__isl_keep isl_ast_build *build, __isl_keep isl_ast_build *sub_build)
 {
 	isl_ast_graft *graft;
+	isl_size n;
 
 	list = isl_ast_graft_list_fuse(list, sub_build);
 
-	if (isl_ast_graft_list_n_ast_graft(list) != 1)
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
+		return isl_ast_graft_list_free(list);
+	if (n != 1)
 		return list;
 
 	graft = isl_ast_graft_list_get_ast_graft(list, 0);
@@ -4231,18 +4290,18 @@ static isl_stat extract_domain(__isl_take isl_map *map, void *user)
 	return isl_stat_ok;
 }
 
-static int after_in_tree(__isl_keep isl_union_map *umap,
+static isl_bool after_in_tree(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node);
 
 /* Is any domain element of "umap" scheduled after any of
  * the corresponding image elements by the tree rooted at
  * the child of "node"?
  */
-static int after_in_child(__isl_keep isl_union_map *umap,
+static isl_bool after_in_child(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
 	isl_schedule_node *child;
-	int after;
+	isl_bool after;
 
 	child = isl_schedule_node_get_child(node, 0);
 	after = after_in_tree(umap, child);
@@ -4263,17 +4322,21 @@ static int after_in_child(__isl_keep isl_union_map *umap,
  * If there are no such pairs then the map passed to after_in_child
  * will be empty causing it to return 0.
  */
-static int after_in_band(__isl_keep isl_union_map *umap,
+static isl_bool after_in_band(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
 	isl_multi_union_pw_aff *mupa;
 	isl_union_map *partial, *test, *gt, *universe, *umap1, *umap2;
 	isl_union_set *domain, *range;
 	isl_space *space;
-	int empty;
-	int after;
+	isl_bool empty;
+	isl_bool after;
+	isl_size n;
 
-	if (isl_schedule_node_band_n_member(node) == 0)
+	n = isl_schedule_node_band_n_member(node);
+	if (n < 0)
+		return isl_bool_error;
+	if (n == 0)
 		return after_in_child(umap, node);
 
 	mupa = isl_schedule_node_band_get_partial_schedule(node);
@@ -4289,7 +4352,7 @@ static int after_in_band(__isl_keep isl_union_map *umap,
 
 	if (empty < 0 || !empty) {
 		isl_union_map_free(partial);
-		return empty < 0 ? -1 : 1;
+		return isl_bool_not(empty);
 	}
 
 	universe = isl_union_map_universe(isl_union_map_copy(umap));
@@ -4315,13 +4378,13 @@ static int after_in_band(__isl_keep isl_union_map *umap,
  * to the range of the prefix schedule for both domain and
  * range of "umap".
  */
-static int after_in_context(__isl_keep isl_union_map *umap,
+static isl_bool after_in_context(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
 	isl_union_map *prefix, *universe, *umap1, *umap2;
 	isl_union_set *domain, *range;
 	isl_set *context;
-	int after;
+	isl_bool after;
 
 	umap = isl_union_map_copy(umap);
 	context = isl_schedule_node_context_get_context(node);
@@ -4351,11 +4414,11 @@ static int after_in_context(__isl_keep isl_union_map *umap,
  * We apply the expansion to domain and range of "umap" and
  * continue with its child.
  */
-static int after_in_expansion(__isl_keep isl_union_map *umap,
+static isl_bool after_in_expansion(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
 	isl_union_map *expansion;
-	int after;
+	isl_bool after;
 
 	expansion = isl_schedule_node_expansion_get_expansion(node);
 	umap = isl_union_map_copy(umap);
@@ -4374,13 +4437,13 @@ static int after_in_expansion(__isl_keep isl_union_map *umap,
  * the extension node "node"?
  *
  * Since the extension node may add statement instances before or
- * after the pairs of statement instances in "umap", we return 1
+ * after the pairs of statement instances in "umap", we return isl_bool_true
  * to ensure that these pairs are not broken up.
  */
-static int after_in_extension(__isl_keep isl_union_map *umap,
+static isl_bool after_in_extension(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
-	return 1;
+	return isl_bool_true;
 }
 
 /* Is any domain element of "umap" scheduled after any of
@@ -4390,11 +4453,11 @@ static int after_in_extension(__isl_keep isl_union_map *umap,
  * We intersect domain and range of "umap" with the filter and
  * continue with its child.
  */
-static int after_in_filter(__isl_keep isl_union_map *umap,
+static isl_bool after_in_filter(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
 	isl_union_set *filter;
-	int after;
+	isl_bool after;
 
 	umap = isl_union_map_copy(umap);
 	filter = isl_schedule_node_filter_get_filter(node);
@@ -4418,15 +4481,18 @@ static int after_in_filter(__isl_keep isl_union_map *umap,
  * are contained in 
diff erent children, then the condition
  * does not hold.
  */
-static int after_in_set(__isl_keep isl_union_map *umap,
+static isl_bool after_in_set(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_schedule_node_n_children(node);
+	if (n < 0)
+		return isl_bool_error;
 	for (i = 0; i < n; ++i) {
 		isl_schedule_node *child;
-		int after;
+		isl_bool after;
 
 		child = isl_schedule_node_get_child(node, i);
 		after = after_in_tree(umap, child);
@@ -4436,7 +4502,7 @@ static int after_in_set(__isl_keep isl_union_map *umap,
 			return after;
 	}
 
-	return 0;
+	return isl_bool_false;
 }
 
 /* Return the filter of child "i" of "node".
@@ -4463,14 +4529,18 @@ static __isl_give isl_union_set *child_filter(
  * if the condition holds within a given child in the sequence.
  * The later part of the condition is checked by after_in_set.
  */
-static int after_in_sequence(__isl_keep isl_union_map *umap,
+static isl_bool after_in_sequence(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
-	int i, j, n;
+	int i, j;
+	isl_size n;
 	isl_union_map *umap_i;
-	int empty, after = 0;
+	isl_bool empty;
+	isl_bool after = isl_bool_false;
 
 	n = isl_schedule_node_n_children(node);
+	if (n < 0)
+		return isl_bool_error;
 	for (i = 1; i < n; ++i) {
 		isl_union_set *filter_i;
 
@@ -4499,7 +4569,7 @@ static int after_in_sequence(__isl_keep isl_union_map *umap,
 			if (empty < 0)
 				goto error;
 			if (!empty)
-				after = 1;
+				after = isl_bool_true;
 			if (after)
 				break;
 		}
@@ -4515,7 +4585,7 @@ static int after_in_sequence(__isl_keep isl_union_map *umap,
 	return after_in_set(umap, node);
 error:
 	isl_union_map_free(umap_i);
-	return -1;
+	return isl_bool_error;
 }
 
 /* Is any domain element of "umap" scheduled after any of
@@ -4524,31 +4594,32 @@ static int after_in_sequence(__isl_keep isl_union_map *umap,
  * If "umap" is empty, then clearly there is no such element.
  * Otherwise, consider the 
diff erent types of nodes separately.
  */
-static int after_in_tree(__isl_keep isl_union_map *umap,
+static isl_bool after_in_tree(__isl_keep isl_union_map *umap,
 	__isl_keep isl_schedule_node *node)
 {
-	int empty;
+	isl_bool empty;
 	enum isl_schedule_node_type type;
 
 	empty = isl_union_map_is_empty(umap);
 	if (empty < 0)
-		return -1;
+		return isl_bool_error;
 	if (empty)
-		return 0;
+		return isl_bool_false;
 	if (!node)
-		return -1;
+		return isl_bool_error;
 
 	type = isl_schedule_node_get_type(node);
 	switch (type) {
 	case isl_schedule_node_error:
-		return -1;
+		return isl_bool_error;
 	case isl_schedule_node_leaf:
-		return 0;
+		return isl_bool_false;
 	case isl_schedule_node_band:
 		return after_in_band(umap, node);
 	case isl_schedule_node_domain:
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_internal,
-			"unexpected internal domain node", return -1);
+			"unexpected internal domain node",
+			return isl_bool_error);
 	case isl_schedule_node_context:
 		return after_in_context(umap, node);
 	case isl_schedule_node_expansion:
@@ -4566,7 +4637,7 @@ static int after_in_tree(__isl_keep isl_union_map *umap,
 		return after_in_sequence(umap, node);
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 /* Is any domain element of "map1" scheduled after any domain
@@ -4582,21 +4653,21 @@ static int after_in_tree(__isl_keep isl_union_map *umap,
  * together and then check if the subtree underneath the current
  * band node determines their relative order.
  */
-static int after_in_subtree(__isl_keep isl_ast_build *build,
+static isl_bool after_in_subtree(__isl_keep isl_ast_build *build,
 	__isl_keep isl_map *map1, __isl_keep isl_map *map2)
 {
 	isl_schedule_node *node;
 	isl_map *map;
 	isl_union_map *umap;
-	int after;
+	isl_bool after;
 
 	node = isl_ast_build_get_schedule_node(build);
 	if (!node)
-		return -1;
+		return isl_bool_error;
 	node = isl_schedule_node_child(node, 0);
 	if (isl_schedule_node_get_type(node) == isl_schedule_node_leaf) {
 		isl_schedule_node_free(node);
-		return 0;
+		return isl_bool_false;
 	}
 	map = isl_map_copy(map2);
 	map = isl_map_apply_domain(map, isl_map_copy(map1));
@@ -4640,9 +4711,12 @@ struct isl_any_scheduled_after_data {
 static isl_bool 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);
+	isl_size dim = isl_set_dim(data->domain[i].set, isl_dim_set);
 	int pos;
 
+	if (dim < 0)
+		return isl_bool_error;
+
 	for (pos = data->depth; pos < dim; ++pos) {
 		int follows;
 
@@ -4658,7 +4732,7 @@ static isl_bool any_scheduled_after(int i, int j, void *user)
 	}
 
 	if (isl_ast_build_has_schedule_node(data->build)) {
-		int after;
+		isl_bool after;
 
 		after = after_in_subtree(data->build, data->domain[i].map,
 					    data->domain[j].map);
@@ -4666,7 +4740,7 @@ static isl_bool any_scheduled_after(int i, int j, void *user)
 			return after;
 	}
 
-	return data->group_coscheduled;
+	return isl_bool_ok(data->group_coscheduled);
 }
 
 /* Look for independent components at the current depth and generate code
@@ -4694,13 +4768,16 @@ static __isl_give isl_ast_graft_list *generate_components(
 {
 	int i;
 	isl_ctx *ctx = isl_ast_build_get_ctx(build);
-	int n = isl_union_map_n_map(executed);
+	isl_size 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 = NULL;
+	if (n < 0)
+		goto error;
 	data.domain = isl_calloc_array(ctx, struct isl_set_map_pair, n);
 	if (!data.domain)
 		goto error;
@@ -4774,6 +4851,8 @@ static __isl_give isl_ast_graft_list *generate_next_level(
 	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
 {
 	int depth;
+	isl_size dim;
+	isl_size n;
 
 	if (!build || !executed)
 		goto error;
@@ -4786,10 +4865,16 @@ static __isl_give isl_ast_graft_list *generate_next_level(
 	}
 
 	depth = isl_ast_build_get_depth(build);
-	if (depth >= isl_ast_build_dim(build, isl_dim_set))
+	dim = isl_ast_build_dim(build, isl_dim_set);
+	if (dim < 0)
+		goto error;
+	if (depth >= dim)
 		return generate_inner_level(executed, build);
 
-	if (isl_union_map_n_map(executed) == 1)
+	n = isl_union_map_n_map(executed);
+	if (n < 0)
+		goto error;
+	if (n == 1)
 		return generate_shifted_component(executed, build);
 
 	return generate_components(executed, build);
@@ -5088,6 +5173,37 @@ __isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
 	return isl_ast_build_node_from_schedule_map(build, schedule);
 }
 
+/* Generate an AST that visits the elements in the domain of "executed"
+ * in the relative order specified by the leaf node "node".
+ *
+ * The relation "executed" maps the outer generated loop iterators
+ * to the domain elements executed by those iterations.
+ *
+ * Simply pass control to generate_inner_level.
+ * Note that the current build does not refer to any band node, so
+ * that generate_inner_level will not try to visit the child of
+ * the leaf node.
+ *
+ * If multiple statement instances reach a leaf,
+ * then they can be executed in any order.
+ * Group the list of grafts based on shared guards
+ * such that identical guards are only generated once
+ * when the list is eventually passed on to isl_ast_graft_list_fuse.
+ */
+static __isl_give isl_ast_graft_list *build_ast_from_leaf(
+	__isl_take isl_ast_build *build, __isl_take isl_schedule_node *node,
+	__isl_take isl_union_map *executed)
+{
+	isl_ast_graft_list *list;
+
+	isl_schedule_node_free(node);
+	list = generate_inner_level(executed, isl_ast_build_copy(build));
+	list = isl_ast_graft_list_group_on_guard(list, build);
+	isl_ast_build_free(build);
+
+	return list;
+}
+
 /* Generate an AST that visits the elements in the domain of "executed"
  * in the relative order specified by the band node "node" and its descendants.
  *
@@ -5110,12 +5226,14 @@ static __isl_give isl_ast_graft_list *build_ast_from_band(
 	isl_multi_union_pw_aff *extra;
 	isl_union_map *extra_umap;
 	isl_ast_graft_list *list;
-	unsigned n1, n2;
+	isl_size n1, n2;
+	isl_size n;
 
-	if (!build || !node || !executed)
+	n = isl_schedule_node_band_n_member(node);
+	if (!build || n < 0 || !executed)
 		goto error;
 
-	if (isl_schedule_node_band_n_member(node) == 0)
+	if (n == 0)
 		return build_ast_from_child(build, node, executed);
 
 	extra = isl_schedule_node_band_get_partial_schedule(node);
@@ -5132,7 +5250,9 @@ static __isl_give isl_ast_graft_list *build_ast_from_band(
 	n1 = isl_ast_build_dim(build, isl_dim_param);
 	build = isl_ast_build_product(build, space);
 	n2 = isl_ast_build_dim(build, isl_dim_param);
-	if (n2 > n1)
+	if (n1 < 0 || n2 < 0)
+		build = isl_ast_build_free(build);
+	else if (n2 > n1)
 		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
 			"band node is not allowed to introduce new parameters",
 			build = isl_ast_build_free(build));
@@ -5165,13 +5285,12 @@ static __isl_give isl_ast_graft_list *hoist_out_of_context(
 	isl_ast_graft *graft;
 	isl_basic_set *enforced;
 	isl_set *guard;
-	unsigned n_param, extra_param;
-
-	if (!build || !sub_build)
-		return isl_ast_graft_list_free(list);
+	isl_size n_param, extra_param;
 
 	n_param = isl_ast_build_dim(build, isl_dim_param);
 	extra_param = isl_ast_build_dim(sub_build, isl_dim_param);
+	if (n_param < 0 || extra_param < 0)
+		return isl_ast_graft_list_free(list);
 
 	if (extra_param == n_param)
 		return list;
@@ -5234,9 +5353,12 @@ static __isl_give isl_ast_graft_list *build_ast_from_context(
 	isl_multi_aff *internal2input;
 	isl_ast_build *sub_build;
 	isl_ast_graft_list *list;
-	int n, depth;
+	isl_size n;
+	isl_size depth;
 
 	depth = isl_schedule_node_get_tree_depth(node);
+	if (depth < 0)
+		build = isl_ast_build_free(build);
 	space = isl_ast_build_get_space(build, 1);
 	context = isl_schedule_node_context_get_context(node);
 	context = isl_set_align_params(context, space);
@@ -5285,7 +5407,7 @@ static __isl_give isl_ast_graft_list *build_ast_from_expansion(
 	__isl_take isl_union_map *executed)
 {
 	isl_union_map *expansion;
-	unsigned n1, n2;
+	isl_size n1, n2;
 
 	expansion = isl_schedule_node_expansion_get_expansion(node);
 	expansion = isl_union_map_align_params(expansion,
@@ -5294,6 +5416,8 @@ static __isl_give isl_ast_graft_list *build_ast_from_expansion(
 	n1 = isl_union_map_dim(executed, isl_dim_param);
 	executed = isl_union_map_apply_range(executed, expansion);
 	n2 = isl_union_map_dim(executed, isl_dim_param);
+	if (n1 < 0 || n2 < 0)
+		goto error;
 	if (n2 > n1)
 		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
 			"expansion node is not allowed to introduce "
@@ -5370,7 +5494,7 @@ static __isl_give isl_ast_graft_list *build_ast_from_filter(
 	isl_ast_graft_list *list;
 	int empty;
 	isl_bool unchanged;
-	unsigned n1, n2;
+	isl_size n1, n2;
 
 	orig = isl_union_map_copy(executed);
 	if (!build || !node || !executed)
@@ -5382,6 +5506,8 @@ static __isl_give isl_ast_graft_list *build_ast_from_filter(
 	n1 = isl_union_map_dim(executed, isl_dim_param);
 	executed = isl_union_map_intersect_range(executed, filter);
 	n2 = isl_union_map_dim(executed, isl_dim_param);
+	if (n1 < 0 || n2 < 0)
+		goto error;
 	if (n2 > n1)
 		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
 			"filter node is not allowed to introduce "
@@ -5436,14 +5562,16 @@ static __isl_give isl_ast_graft_list *build_ast_from_guard(
 	isl_ast_build *sub_build;
 	isl_ast_graft *graft;
 	isl_ast_graft_list *list;
-	unsigned n1, n2;
+	isl_size n1, n2, n;
 
 	space = isl_ast_build_get_space(build, 1);
 	guard = isl_schedule_node_guard_get_guard(node);
 	n1 = isl_space_dim(space, isl_dim_param);
 	guard = isl_set_align_params(guard, space);
 	n2 = isl_set_dim(guard, isl_dim_param);
-	if (n2 > n1)
+	if (n1 < 0 || n2 < 0)
+		guard = isl_set_free(guard);
+	else if (n2 > n1)
 		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
 			"guard node is not allowed to introduce "
 			"new parameters", guard = isl_set_free(guard));
@@ -5460,7 +5588,10 @@ static __isl_give isl_ast_graft_list *build_ast_from_guard(
 							node, executed);
 
 	hoisted = isl_ast_graft_list_extract_hoistable_guard(list, sub_build);
-	if (isl_set_n_basic_set(hoisted) > 1)
+	n = isl_set_n_basic_set(hoisted);
+	if (n < 0)
+		list = isl_ast_graft_list_free(list);
+	if (n > 1)
 		list = isl_ast_graft_list_gist_guards(list,
 						    isl_set_copy(hoisted));
 	guard = isl_set_intersect(guard, hoisted);
@@ -5532,7 +5663,7 @@ static __isl_give isl_ast_graft_list *build_ast_from_mark(
 	isl_id *mark;
 	isl_ast_graft *graft;
 	isl_ast_graft_list *list;
-	int n;
+	isl_size n;
 
 	build = isl_ast_build_set_executed(build, isl_union_map_copy(executed));
 
@@ -5576,7 +5707,8 @@ static __isl_give isl_ast_graft_list *build_ast_from_sequence(
 	__isl_take isl_ast_build *build, __isl_take isl_schedule_node *node,
 	__isl_take isl_union_map *executed)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_ast_graft_list *list;
 
@@ -5584,6 +5716,8 @@ static __isl_give isl_ast_graft_list *build_ast_from_sequence(
 	list = isl_ast_graft_list_alloc(ctx, 0);
 
 	n = isl_schedule_node_n_children(node);
+	if (n < 0)
+		list = isl_ast_graft_list_free(list);
 	for (i = 0; i < n; ++i) {
 		isl_schedule_node *child;
 		isl_ast_graft_list *list_i;
@@ -5606,12 +5740,7 @@ static __isl_give isl_ast_graft_list *build_ast_from_sequence(
  * The relation "executed" maps the outer generated loop iterators
  * to the domain elements executed by those iterations.
  *
- * If the node is a leaf, then we pass control to generate_inner_level.
- * Note that the current build does not refer to any band node, so
- * that generate_inner_level will not try to visit the child of
- * the leaf node.
- *
- * The other node types are handled in separate functions.
+ * The node types are handled in separate functions.
  * Set nodes are currently treated in the same way as sequence nodes.
  * The children of a set node may be executed in any order,
  * including the order of the children.
@@ -5628,8 +5757,7 @@ static __isl_give isl_ast_graft_list *build_ast_from_schedule_node(
 	case isl_schedule_node_error:
 		goto error;
 	case isl_schedule_node_leaf:
-		isl_schedule_node_free(node);
-		return generate_inner_level(executed, build);
+		return build_ast_from_leaf(build, node, executed);
 	case isl_schedule_node_band:
 		return build_ast_from_band(build, node, executed);
 	case isl_schedule_node_context:

diff  --git a/polly/lib/External/isl/isl_ast_graft.c b/polly/lib/External/isl/isl_ast_graft.c
index 5c79eae08078..7a0998661961 100644
--- a/polly/lib/External/isl/isl_ast_graft.c
+++ b/polly/lib/External/isl/isl_ast_graft.c
@@ -1,6 +1,7 @@
 /*
  * Copyright 2012      Ecole Normale Superieure
  * Copyright 2014      INRIA Rocquencourt
+ * Copyright 2019      Cerebras Systems
  *
  * Use of this software is governed by the MIT license
  *
@@ -8,6 +9,7 @@
  * 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
+ * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
  */
 
 #include <isl/id.h>
@@ -16,12 +18,13 @@
 #include <isl_ast_build_expr.h>
 #include <isl_ast_build_private.h>
 #include <isl_ast_graft_private.h>
+#include "isl_set_to_ast_graft_list.h"
 
 static __isl_give isl_ast_graft *isl_ast_graft_copy(
 	__isl_keep isl_ast_graft *graft);
 
-#undef BASE
-#define BASE ast_graft
+#undef EL_BASE
+#define EL_BASE ast_graft
 
 #include <isl_list_templ.c>
 
@@ -102,36 +105,43 @@ static __isl_give isl_ast_graft *isl_ast_graft_copy(
 /* 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,
+static isl_bool equal_independent_guards(__isl_keep isl_ast_graft_list *list,
 	__isl_keep isl_ast_build *build)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	int depth;
+	isl_size dim;
 	isl_ast_graft *graft_0;
-	int equal = 1;
-	int skip;
+	isl_bool equal = isl_bool_true;
+	isl_bool skip;
 
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
+		return isl_bool_error;
 	graft_0 = isl_ast_graft_list_get_ast_graft(list, 0);
 	if (!graft_0)
-		return -1;
+		return isl_bool_error;
 
 	depth = isl_ast_build_get_depth(build);
-	if (isl_set_dim(graft_0->guard, isl_dim_set) <= depth)
-		skip = 0;
+	dim = isl_set_dim(graft_0->guard, isl_dim_set);
+	if (dim < 0)
+		return isl_bool_error;
+	if (dim <= depth)
+		skip = isl_bool_false;
 	else
 		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;
+		return isl_bool_not(skip);
 	}
 
-	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;
+			equal = isl_bool_error;
 		else
 			equal = isl_set_is_equal(graft_0->guard, graft->guard);
 		isl_ast_graft_free(graft);
@@ -152,9 +162,13 @@ static __isl_give isl_set *hoist_guard(__isl_take isl_set *guard,
 	__isl_keep isl_ast_build *build)
 {
 	int depth;
+	isl_size dim;
 
 	depth = isl_ast_build_get_depth(build);
-	if (depth < isl_set_dim(guard, isl_dim_set)) {
+	dim = isl_set_dim(guard, isl_dim_set);
+	if (dim < 0)
+		return isl_set_free(guard);
+	if (depth < dim) {
 		guard = isl_set_remove_divs_involving_dims(guard,
 						isl_dim_set, depth, 1);
 		guard = isl_set_eliminate(guard, isl_dim_set, depth, 1);
@@ -193,8 +207,9 @@ static __isl_give isl_set *hoist_guard(__isl_take isl_set *guard,
 __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;
+	int i;
+	isl_size n;
+	isl_bool equal;
 	isl_ctx *ctx;
 	isl_set *guard;
 	isl_set_list *set_list;
@@ -204,6 +219,8 @@ __isl_give isl_set *isl_ast_graft_list_extract_hoistable_guard(
 		return NULL;
 
 	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
+		return NULL;
 	if (n == 0)
 		return isl_set_universe(isl_ast_build_get_space(build, 1));
 
@@ -277,10 +294,13 @@ static __isl_give isl_ast_node *ast_node_insert_if(
 {
 	struct isl_insert_if_data data;
 	isl_ctx *ctx;
+	isl_size n;
 
+	n = isl_set_n_basic_set(guard);
+	if (n < 0)
+		goto error;
 	ctx = isl_ast_build_get_ctx(build);
-	if (isl_options_get_ast_build_allow_or(ctx) ||
-	    isl_set_n_basic_set(guard) <= 1) {
+	if (isl_options_get_ast_build_allow_or(ctx) || n <= 1) {
 		isl_ast_node *if_node;
 		isl_ast_expr *expr;
 
@@ -301,6 +321,10 @@ static __isl_give isl_ast_node *ast_node_insert_if(
 	isl_set_free(guard);
 	isl_ast_node_free(data.node);
 	return isl_ast_node_alloc_block(data.list);
+error:
+	isl_set_free(guard);
+	isl_ast_node_free(node);
+	return NULL;
 }
 
 /* Insert an if node around a copy of "data->node" testing the condition
@@ -389,10 +413,14 @@ static __isl_give isl_basic_set *update_enforced(
 	__isl_take isl_basic_set *enforced, __isl_keep isl_ast_graft *graft,
 	int depth)
 {
+	isl_size dim;
 	isl_basic_set *enforced_g;
 
 	enforced_g = isl_ast_graft_get_enforced(graft);
-	if (depth < isl_basic_set_dim(enforced_g, isl_dim_set))
+	dim = isl_basic_set_dim(enforced_g, isl_dim_set);
+	if (dim < 0)
+		enforced_g = isl_basic_set_free(enforced_g);
+	if (depth < dim)
 		enforced_g = isl_basic_set_eliminate(enforced_g,
 							isl_dim_set, depth, 1);
 	enforced_g = isl_basic_set_remove_unknown_divs(enforced_g);
@@ -444,19 +472,19 @@ static __isl_give isl_ast_graft_list *graft_extend_body(
 	__isl_keep isl_ast_node **body, __isl_take isl_ast_graft *graft,
 	__isl_keep isl_ast_build *build)
 {
-	int n;
+	isl_size n;
 	int depth;
 	isl_ast_graft *last;
 	isl_space *space;
 	isl_basic_set *enforced;
 
-	if (!list || !graft)
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0 || !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);
@@ -543,17 +571,18 @@ 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 i, j, n_if;
+	isl_size n;
 	int allow_else;
 	isl_ctx *ctx;
 	isl_ast_graft_list *res;
 	struct isl_if_node *if_node = NULL;
 
-	if (!build || !list)
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (!build || n < 0)
 		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);
 
@@ -663,15 +692,16 @@ static __isl_give isl_ast_graft_list *insert_pending_guard_nodes(
 __isl_give isl_ast_graft_list *isl_ast_graft_list_insert_pending_guard_nodes(
 	__isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_set *universe;
 
 	list = insert_pending_guard_nodes(list, build);
-	if (!list)
-		return NULL;
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
+		return isl_ast_graft_list_free(list);
 
 	universe = isl_set_universe(isl_ast_build_get_space(build, 1));
-	n = isl_ast_graft_list_n_ast_graft(list);
 	for (i = 0; i < n; ++i) {
 		isl_ast_graft *graft;
 
@@ -696,14 +726,15 @@ __isl_give isl_ast_graft_list *isl_ast_graft_list_insert_pending_guard_nodes(
 static __isl_give isl_ast_node_list *extract_node_list(
 	__isl_keep isl_ast_graft_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_ast_node_list *node_list;
 
-	if (!list)
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
 		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;
@@ -727,19 +758,20 @@ __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 i;
+	isl_size n;
 	int depth;
 	isl_space *space;
 	isl_basic_set *enforced;
 
-	if (!list)
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
 		return NULL;
 
 	space = isl_ast_build_get_space(build, 1);
 	enforced = isl_basic_set_empty(space);
 
 	depth = isl_ast_build_get_depth(build);
-	n = isl_ast_graft_list_n_ast_graft(list);
 	for (i = 0; i < n; ++i) {
 		isl_ast_graft *graft;
 
@@ -794,12 +826,13 @@ static __isl_give isl_ast_graft *store_guard(__isl_take isl_ast_graft *graft,
 static __isl_give isl_ast_graft_list *gist_guards(
 	__isl_take isl_ast_graft_list *list, __isl_keep isl_set *context)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
+	n = isl_ast_graft_list_n_ast_graft(list);
 	if (!list)
-		return NULL;
+		return isl_ast_graft_list_free(list);
 
-	n = isl_ast_graft_list_n_ast_graft(list);
 	for (i = 0; i < n; ++i) {
 		isl_ast_graft *graft;
 
@@ -909,11 +942,13 @@ __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_size n;
 	isl_ast_graft *graft;
 
-	if (!list)
-		return NULL;
-	if (isl_ast_graft_list_n_ast_graft(list) <= 1)
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
+		return isl_ast_graft_list_free(list);
+	if (n <= 1)
 		return list;
 	graft = ast_graft_list_fuse(list, build);
 	return isl_ast_graft_list_from_ast_graft(graft);
@@ -1098,9 +1133,12 @@ __isl_give isl_ast_graft *isl_ast_graft_unembed(__isl_take isl_ast_graft *graft,
 __isl_give isl_ast_graft_list *isl_ast_graft_list_unembed(
 	__isl_take isl_ast_graft_list *list, int product)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
+		return isl_ast_graft_list_free(list);
 	for (i = 0; i < n; ++i) {
 		isl_ast_graft *graft;
 
@@ -1140,9 +1178,12 @@ __isl_give isl_ast_graft *isl_ast_graft_preimage_multi_aff(
 __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;
+	int i;
+	isl_size n;
 
 	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n < 0)
+		list = isl_ast_graft_list_free(list);
 	for (i = 0; i < n; ++i) {
 		isl_ast_graft *graft;
 
@@ -1278,6 +1319,130 @@ __isl_give isl_ast_graft_list *isl_ast_graft_list_merge(
 	return NULL;
 }
 
+/* Internal data structure for split_on_guard.
+ *
+ * "guard2list" is the constructed associative array.
+ * "any_match" gets set if any guard was seen more than once.
+ */
+struct isl_split_on_guard_data {
+	isl_set_to_ast_graft_list *guard2list;
+	int *any_match;
+};
+
+/* Add "graft" to the list associated to its guard in data->guard2list.
+ * If some other graft was already associated to this guard,
+ * then set data->any_match.
+ */
+static isl_stat add_to_guard_list(__isl_take isl_ast_graft *graft, void *user)
+{
+	struct isl_split_on_guard_data *data = user;
+	isl_set *guard;
+	isl_maybe_isl_ast_graft_list m;
+
+	if (!graft)
+		return isl_stat_error;
+	m = isl_set_to_ast_graft_list_try_get(data->guard2list, graft->guard);
+	if (m.valid < 0)
+		return isl_stat_non_null(isl_ast_graft_free(graft));
+
+	if (m.valid) {
+		*data->any_match = 1;
+		m.value = isl_ast_graft_list_add(m.value, graft);
+	} else {
+		m.value = isl_ast_graft_list_from_ast_graft(graft);
+	}
+	guard = isl_set_copy(graft->guard);
+	data->guard2list =
+		isl_set_to_ast_graft_list_set(data->guard2list, guard, m.value);
+
+	return isl_stat_non_null(data->guard2list);
+}
+
+/* Construct an associative array that groups the elements
+ * of "list" based on their guards.
+ * If any guard appears more than once, then set "any_match".
+ */
+static __isl_give isl_set_to_ast_graft_list *split_on_guard(
+	__isl_keep isl_ast_graft_list *list, int *any_match)
+{
+	struct isl_split_on_guard_data data = { NULL, any_match };
+	isl_size n;
+	isl_ctx *ctx;
+
+	n = isl_ast_graft_list_size(list);
+	if (n < 0)
+		return NULL;
+
+	ctx = isl_ast_graft_list_get_ctx(list);
+	data.guard2list = isl_set_to_ast_graft_list_alloc(ctx, n);
+
+	if (isl_ast_graft_list_foreach(list, &add_to_guard_list, &data) < 0)
+		return isl_set_to_ast_graft_list_free(data.guard2list);
+
+	return data.guard2list;
+}
+
+/* Add the elements of "guard_list" to "list".
+ */
+static isl_stat add_same_guard(__isl_take isl_set *guard,
+	__isl_take isl_ast_graft_list *guard_list, void *user)
+{
+	isl_ast_graft_list **list = user;
+
+	isl_set_free(guard);
+	*list = isl_ast_graft_list_concat(*list, guard_list);
+
+	return isl_stat_non_null(*list);
+}
+
+/* Given an associative array "guard2list" containing the elements
+ * of "list" grouped on common guards, reconstruct "list"
+ * by placing elements with the same guard consecutively.
+ */
+static __isl_give isl_ast_graft_list *reconstruct(
+	__isl_take isl_ast_graft_list *list,
+	__isl_keep isl_set_to_ast_graft_list *guard2list,
+	__isl_keep isl_ast_build *build)
+{
+	list = isl_ast_graft_list_clear(list);
+	if (isl_set_to_ast_graft_list_foreach(guard2list,
+						&add_same_guard, &list) < 0)
+		list = isl_ast_graft_list_free(list);
+
+	return list;
+}
+
+/* Group the grafts in "list" based on identical guards.
+ *
+ * Note that there need to be a least three elements in the list
+ * for the elements not to be grouped already.
+ *
+ * Group the elements in an associative array based on their guards.
+ * If any guard was seen more than once, then reconstruct the list
+ * from the associative array.  Otherwise, simply return the original list.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_group_on_guard(
+	__isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+	int any_match = 0;
+	isl_size n;
+	isl_set_to_ast_graft_list *guard2list;
+
+	n = isl_ast_graft_list_size(list);
+	if (n < 0)
+		return isl_ast_graft_list_free(list);
+	if (n <= 2)
+		return list;
+
+	guard2list = split_on_guard(list, &any_match);
+	if (any_match)
+		list = reconstruct(list, guard2list, build);
+
+	isl_set_to_ast_graft_list_free(guard2list);
+
+	return list;
+}
+
 __isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
 	__isl_keep isl_ast_graft *graft)
 {

diff  --git a/polly/lib/External/isl/isl_ast_graft_private.h b/polly/lib/External/isl/isl_ast_graft_private.h
index 0456a6f8cfcb..5ca7c0336638 100644
--- a/polly/lib/External/isl/isl_ast_graft_private.h
+++ b/polly/lib/External/isl/isl_ast_graft_private.h
@@ -2,6 +2,7 @@
 #define ISL_AST_GRAFT_PRIVATE_H
 
 #include <isl/ast.h>
+#include <isl/ast_build.h>
 #include <isl/set.h>
 #include <isl/list.h>
 #include <isl/printer.h>
@@ -61,6 +62,8 @@ __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_graft_list *isl_ast_graft_list_group_on_guard(
+	__isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
 
 __isl_give isl_ast_node *isl_ast_graft_get_node(
 	__isl_keep isl_ast_graft *graft);

diff  --git a/polly/lib/External/isl/isl_ast_private.h b/polly/lib/External/isl/isl_ast_private.h
index 9470019ca9c3..a7726a28df72 100644
--- a/polly/lib/External/isl/isl_ast_private.h
+++ b/polly/lib/External/isl/isl_ast_private.h
@@ -22,7 +22,7 @@ struct isl_ast_expr {
 		isl_val *v;
 		isl_id *id;
 		struct {
-			enum isl_ast_op_type op;
+			enum isl_ast_expr_op_type op;
 			unsigned n_arg;
 			isl_ast_expr **args;
 		} op;
@@ -36,8 +36,9 @@ struct isl_ast_expr {
 
 __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,
+	enum isl_ast_expr_op_type op, int n_arg);
+__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(
+	enum isl_ast_expr_op_type type,
 	__isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2);
 
 #undef EL

diff  --git a/polly/lib/External/isl/isl_bernstein.c b/polly/lib/External/isl/isl_bernstein.c
index 3036e8fd3004..2b83c64dbac4 100644
--- a/polly/lib/External/isl/isl_bernstein.c
+++ b/polly/lib/External/isl/isl_bernstein.c
@@ -38,92 +38,105 @@ struct bernstein_data {
 	isl_pw_qpolynomial_fold *pwf_tight;
 };
 
-static int vertex_is_integral(__isl_keep isl_basic_set *vertex)
+static isl_bool vertex_is_integral(__isl_keep isl_basic_set *vertex)
 {
-	unsigned nvar;
-	unsigned nparam;
+	isl_size nvar;
+	isl_size nparam;
 	int i;
 
 	nvar = isl_basic_set_dim(vertex, isl_dim_set);
 	nparam = isl_basic_set_dim(vertex, isl_dim_param);
+	if (nvar < 0 || nparam < 0)
+		return isl_bool_error;
 	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 isl_bool_false;
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 static __isl_give isl_qpolynomial *vertex_coordinate(
-	__isl_keep isl_basic_set *vertex, int i, __isl_take isl_space *dim)
+	__isl_keep isl_basic_set *vertex, int i, __isl_take isl_space *space)
 {
-	unsigned nvar;
-	unsigned nparam;
+	isl_size nvar;
+	isl_size nparam;
+	isl_size total;
 	int r;
 	isl_int denom;
 	isl_qpolynomial *v;
 
+	isl_int_init(denom);
+
 	nvar = isl_basic_set_dim(vertex, isl_dim_set);
 	nparam = isl_basic_set_dim(vertex, isl_dim_param);
+	total = isl_basic_set_dim(vertex, isl_dim_all);
+	if (nvar < 0 || nparam < 0 || total < 0)
+		goto error;
 	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));
+		isl_seq_neg(vertex->eq[r], vertex->eq[r], 1 + total);
 	else
 		isl_int_neg(denom, denom);
 
-	v = isl_qpolynomial_from_affine(dim, vertex->eq[r], denom);
+	v = isl_qpolynomial_from_affine(space, vertex->eq[r], denom);
 	isl_int_clear(denom);
 
 	return v;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	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
+ * which is the case if we select exactly one vertex (i.e., one of the
+ * exponents in "k" is exactly "d") 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)
+static isl_bool 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;
+		if (!k[i])
 			continue;
-		}
+		if (k[i] != d)
+			return isl_bool_false;
 		v = cell->ids[n - 1 - i];
 		return vertex_is_integral(cell->vertices->v[v].vertex);
 	}
 
-	return 0;
+	return isl_bool_false;
 }
 
-static void add_fold(__isl_take isl_qpolynomial *b, __isl_keep isl_set *dom,
+static isl_stat 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;
+	isl_bool tight;
 
 	fold = isl_qpolynomial_fold_alloc(data->type, b);
 
-	if (data->check_tight && is_tight(k, n, d, data->cell))
+	tight = isl_bool_false;
+	if (data->check_tight)
+		tight = is_tight(k, n, d, data->cell);
+	if (tight < 0)
+		return isl_stat_error;
+	if (tight)
 		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);
+	return isl_stat_ok;
 }
 
 /* Extract the coefficients of the Bernstein base polynomials and store
@@ -136,25 +149,25 @@ static void add_fold(__isl_take isl_qpolynomial *b, __isl_keep isl_set *dom,
  * 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,
+static isl_stat extract_coefficients(isl_qpolynomial *poly,
 	__isl_keep isl_set *dom, struct bernstein_data *data)
 {
 	int i;
 	int d;
-	int n;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_qpolynomial **c = NULL;
 	int *k = NULL;
 	int *left = NULL;
 	isl_vec *multinom = NULL;
 
-	if (!poly)
-		return;
+	n = isl_qpolynomial_dim(poly, isl_dim_in);
+	if (n < 0)
+		return isl_stat_error;
 
 	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);
+	isl_assert(ctx, n >= 2, return isl_stat_error);
 
 	c = isl_calloc_array(ctx, isl_qpolynomial *, n);
 	k = isl_alloc_array(ctx, int, n);
@@ -188,7 +201,8 @@ static void extract_coefficients(isl_qpolynomial *poly,
 					multinom->el[i]);
 				b = isl_qpolynomial_mul(b, f);
 				k[n - 1] = left[n - 2];
-				add_fold(b, dom, k, n, d, data);
+				if (add_fold(b, dom, k, n, d, data) < 0)
+					goto error;
 				--i;
 				continue;
 			}
@@ -218,7 +232,7 @@ static void extract_coefficients(isl_qpolynomial *poly,
 	free(left);
 	free(k);
 	free(c);
-	return;
+	return isl_stat_ok;
 error:
 	isl_vec_free(multinom);
 	free(left);
@@ -227,7 +241,7 @@ static void extract_coefficients(isl_qpolynomial *poly,
 		for (i = 0; i < n; ++i)
 			isl_qpolynomial_free(c[i]);
 	free(c);
-	return;
+	return isl_stat_error;
 }
 
 /* Perform bernstein expansion on the parametric vertices that are active
@@ -247,9 +261,10 @@ static isl_stat bernstein_coefficients_cell(__isl_take isl_cell *cell,
 {
 	int i, j;
 	struct bernstein_data *data = (struct bernstein_data *)user;
-	isl_space *dim_param;
-	isl_space *dim_dst;
+	isl_space *space_param;
+	isl_space *space_dst;
 	isl_qpolynomial *poly = data->poly;
+	isl_size n_in;
 	unsigned nvar;
 	int n_vertices;
 	isl_qpolynomial **subs;
@@ -257,10 +272,11 @@ static isl_stat bernstein_coefficients_cell(__isl_take isl_cell *cell,
 	isl_set *dom;
 	isl_ctx *ctx;
 
-	if (!poly)
+	n_in = isl_qpolynomial_dim(poly, isl_dim_in);
+	if (n_in < 0)
 		goto error;
 
-	nvar = isl_qpolynomial_dim(poly, isl_dim_in) - 1;
+	nvar = n_in - 1;
 	n_vertices = cell->n_vertices;
 
 	ctx = isl_qpolynomial_get_ctx(poly);
@@ -272,22 +288,23 @@ static isl_stat bernstein_coefficients_cell(__isl_take isl_cell *cell,
 	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);
+	space_param = isl_basic_set_get_space(cell->dom);
+	space_dst = isl_qpolynomial_get_domain_space(poly);
+	space_dst = isl_space_add_dims(space_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));
+		subs[i] =
+		    isl_qpolynomial_zero_on_domain(isl_space_copy(space_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);
+		c = isl_qpolynomial_var_on_domain(isl_space_copy(space_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));
+						isl_space_copy(space_param));
 			v = isl_qpolynomial_add_dims(v, isl_dim_in,
 							1 + nvar + n_vertices);
 			v = isl_qpolynomial_mul(v, isl_qpolynomial_copy(c));
@@ -295,7 +312,7 @@ static isl_stat bernstein_coefficients_cell(__isl_take isl_cell *cell,
 		}
 		subs[0] = isl_qpolynomial_add(subs[0], c);
 	}
-	isl_space_free(dim_dst);
+	isl_space_free(space_dst);
 
 	poly = isl_qpolynomial_copy(poly);
 
@@ -305,9 +322,13 @@ static isl_stat bernstein_coefficients_cell(__isl_take isl_cell *cell,
 
 	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);
+	data->fold = isl_qpolynomial_fold_empty(data->type,
+						isl_space_copy(space_param));
+	data->fold_tight = isl_qpolynomial_fold_empty(data->type, space_param);
+	if (extract_coefficients(poly, dom, data) < 0) {
+		data->fold = isl_qpolynomial_fold_free(data->fold);
+		data->fold_tight = isl_qpolynomial_fold_free(data->fold_tight);
+	}
 
 	pwf = isl_pw_qpolynomial_fold_alloc(data->type, isl_set_copy(dom),
 					    data->fold);
@@ -334,15 +355,18 @@ static isl_stat bernstein_coefficients_cell(__isl_take isl_cell *cell,
  */
 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)
+	__isl_take isl_qpolynomial *poly, struct bernstein_data *data,
+	isl_bool *tight)
 {
-	unsigned nvar;
-	isl_space *dim;
+	isl_size nvar;
+	isl_space *space;
 	isl_pw_qpolynomial_fold *pwf;
 	isl_vertices *vertices;
-	int covers;
+	isl_bool covers;
 
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0)
+		bset = isl_basic_set_free(bset);
 	if (nvar == 0) {
 		isl_set *dom;
 		isl_qpolynomial_fold *fold;
@@ -350,7 +374,7 @@ static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_base(
 		fold = isl_qpolynomial_fold_alloc(data->type, poly);
 		dom = isl_set_from_basic_set(bset);
 		if (tight)
-			*tight = 1;
+			*tight = isl_bool_true;
 		pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold);
 		return isl_pw_qpolynomial_fold_project_domain_on_params(pwf);
 	}
@@ -362,16 +386,17 @@ static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_base(
 		dom = isl_set_from_basic_set(bset);
 		pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold);
 		if (tight)
-			*tight = 1;
+			*tight = isl_bool_true;
 		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);
+	space = isl_basic_set_get_space(bset);
+	space = isl_space_params(space);
+	space = isl_space_from_domain(space);
+	space = isl_space_add_dims(space, isl_dim_set, 1);
+	data->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(space),
+						data->type);
+	data->pwf_tight = isl_pw_qpolynomial_fold_zero(space, data->type);
 	data->poly = isl_qpolynomial_homogenize(isl_qpolynomial_copy(poly));
 	vertices = isl_basic_set_compute_vertices(bset);
 	if (isl_vertices_foreach_disjoint_cell(vertices,
@@ -409,18 +434,17 @@ static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_base(
  */
 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 n_group, int *len, struct bernstein_data *data, isl_bool *tight)
 {
 	int i;
-	unsigned nparam;
-	unsigned nvar;
+	isl_size nparam;
+	isl_size 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);
+	if (nparam < 0 || nvar < 0)
+		goto error;
 
 	pwqp = isl_pw_qpolynomial_move_dims(pwqp, isl_dim_param, nparam,
 					isl_dim_in, 0, nvar - len[n_group - 1]);
@@ -428,6 +452,8 @@ static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_recursive(
 
 	for (i = n_group - 2; i >= 0; --i) {
 		nparam = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_param);
+		if (nparam < 0)
+			return isl_pw_qpolynomial_fold_free(pwf);
 		pwf = isl_pw_qpolynomial_fold_move_dims(pwf, isl_dim_in, 0,
 				isl_dim_param, nparam - len[i], len[i]);
 		if (tight && !*tight)
@@ -436,11 +462,15 @@ static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_recursive(
 	}
 
 	return pwf;
+error:
+	isl_pw_qpolynomial_free(pwqp);
+	return NULL;
 }
 
 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_take isl_qpolynomial *poly, struct bernstein_data *data,
+	isl_bool *tight)
 {
 	isl_factorizer *f;
 	isl_set *set;
@@ -473,19 +503,19 @@ static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_factors(
 
 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)
+	__isl_take isl_qpolynomial *poly, struct bernstein_data *data,
+	isl_bool *tight)
 {
 	int i;
 	int *len;
-	unsigned nvar;
+	isl_size 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);
+	if (nvar < 0 || !poly)
+		goto error;
 	
 	len = isl_alloc_array(bset->ctx, int, nvar);
 	if (nvar && !len)
@@ -525,18 +555,17 @@ isl_stat isl_qpolynomial_bound_on_domain_bernstein(
 {
 	struct bernstein_data data;
 	isl_pw_qpolynomial_fold *pwf;
-	unsigned nvar;
-	int tight = 0;
-	int *tp = bound->check_tight ? &tight : NULL;
+	isl_size nvar;
+	isl_bool tight = isl_bool_false;
+	isl_bool *tp = bound->check_tight ? &tight : NULL;
 
-	if (!bset || !poly)
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0 || !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 &&

diff  --git a/polly/lib/External/isl/isl_bind_domain_templ.c b/polly/lib/External/isl/isl_bind_domain_templ.c
new file mode 100644
index 000000000000..06cbf07c7ef7
--- /dev/null
+++ b/polly/lib/External/isl/isl_bind_domain_templ.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2018      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#include <isl/space.h>
+
+/* Merge parameter "param" into the input dimension "i" of "obj".
+ *
+ * First plug in the parameter for the input dimension in "obj".
+ * The drop the (now defunct) input dimension and
+ * move the parameter in its original position.
+ * Since dimension manipulations destroy spaces, modify the space
+ * separately by only dropping the parameter.
+ */
+static __isl_give TYPE *FN(TYPE,merge_param)(__isl_take TYPE *obj, int i,
+	int param)
+{
+	isl_id *id;
+	isl_aff *aff;
+	isl_space *space;
+	isl_multi_aff *ma;
+
+	space = FN(TYPE,get_domain_space)(obj);
+	id = isl_space_get_dim_id(space, isl_dim_param, param);
+	aff = isl_aff_param_on_domain_space_id(isl_space_copy(space), id);
+	space = isl_space_map_from_set(space);
+	ma = isl_multi_aff_identity(space);
+	ma = isl_multi_aff_set_aff(ma, i, aff);
+	obj = FN(TYPE,pullback_multi_aff)(obj, ma);
+	space = FN(TYPE,get_domain_space)(obj);
+	obj = FN(TYPE,drop_dims)(obj, isl_dim_in, i, 1);
+	obj = FN(TYPE,move_dims)(obj, isl_dim_in, i, isl_dim_param, param, 1);
+	space = isl_space_drop_dims(space, isl_dim_param, param, 1);
+	obj = FN(TYPE,reset_domain_space)(obj, space);
+
+	return obj;
+}
+
+/* Given a tuple of identifiers "tuple" that correspond
+ * to the initial input dimensions of "obj",
+ * if any of those identifiers appear as parameters
+ * in "obj", then equate those parameters with the corresponding
+ * input dimensions and project out the parameters.
+ * The result therefore has no such parameters.
+ */
+static __isl_give TYPE *FN(TYPE,equate_initial_params)(__isl_take TYPE *obj,
+	__isl_keep isl_multi_id *tuple)
+{
+	int i;
+	isl_size n;
+
+	n = isl_multi_id_size(tuple);
+	if (n < 0)
+		return FN(TYPE,free)(obj);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+		int pos;
+
+		id = isl_multi_id_get_at(tuple, i);
+		if (!id)
+			return FN(TYPE,free)(obj);
+		pos = FN(TYPE,find_dim_by_id)(obj, isl_dim_param, id);
+		isl_id_free(id);
+		if (pos < 0)
+			continue;
+		obj = FN(TYPE,merge_param)(obj, i, pos);
+	}
+
+	return obj;
+}
+
+/* Given a tuple of identifiers "tuple" in a space that corresponds
+ * to the domain of "obj", if any of those identifiers appear as parameters
+ * in "obj", then equate those parameters with the corresponding
+ * input dimensions and project out the parameters.
+ * The result therefore has no such parameters.
+ */
+static __isl_give TYPE *FN(TYPE,equate_domain_params)(__isl_take TYPE *obj,
+	__isl_keep isl_multi_id *tuple)
+{
+	isl_stat r;
+	isl_space *obj_space, *tuple_space;
+
+	obj_space = FN(TYPE,get_space)(obj);
+	tuple_space = isl_multi_id_peek_space(tuple);
+	r = isl_space_check_domain_tuples(tuple_space, obj_space);
+	isl_space_free(obj_space);
+	if (r < 0)
+		return FN(TYPE,free)(obj);
+
+	return FN(TYPE,equate_initial_params)(obj, tuple);
+}
+
+/* Bind the domain dimensions of the function "obj" to parameters
+ * with identifiers specified by "tuple", living in the same space
+ * as the domain of "obj".
+ *
+ * If no parameters with these identifiers appear in "obj" already,
+ * then the domain dimensions are simply reinterpreted as parameters.
+ * Otherwise, the parameters are first equated to the corresponding
+ * domain dimensions.
+ */
+__isl_give TYPE *FN(TYPE,bind_domain)(__isl_take TYPE *obj,
+	__isl_take isl_multi_id *tuple)
+{
+	isl_space *space;
+
+	obj = FN(TYPE,equate_domain_params)(obj, tuple);
+	space = FN(TYPE,get_space)(obj);
+	space = isl_space_bind_map_domain(space, tuple);
+	isl_multi_id_free(tuple);
+	obj = FN(TYPE,reset_space)(obj, space);
+
+	return obj;
+}
+
+/* Given a tuple of identifiers "tuple" in a space that corresponds
+ * to the domain of the wrapped relation in the domain of "obj",
+ * if any of those identifiers appear as parameters
+ * in "obj", then equate those parameters with the corresponding
+ * input dimensions and project out the parameters.
+ * The result therefore has no such parameters.
+ */
+static __isl_give TYPE *FN(TYPE,equate_domain_wrapped_domain_params)(
+	__isl_take TYPE *obj, __isl_keep isl_multi_id *tuple)
+{
+	isl_stat r;
+	isl_space *obj_space, *tuple_space;
+
+	obj_space = FN(TYPE,get_space)(obj);
+	tuple_space = isl_multi_id_peek_space(tuple);
+	r = isl_space_check_domain_wrapped_domain_tuples(tuple_space,
+							obj_space);
+	isl_space_free(obj_space);
+	if (r < 0)
+		return FN(TYPE,free)(obj);
+
+	return FN(TYPE,equate_initial_params)(obj, tuple);
+}
+
+/* Given a function living in a space of the form [A -> B] -> C and
+ * a tuple of identifiers in A, bind the domain dimensions of the relation
+ * wrapped in the domain of "obj" with identifiers specified by "tuple",
+ * returning a function in the space B -> C.
+ *
+ * If no parameters with these identifiers appear in "obj" already,
+ * then the domain dimensions are simply reinterpreted as parameters.
+ * Otherwise, the parameters are first equated to the corresponding
+ * domain dimensions.
+ */
+__isl_give TYPE *FN(TYPE,bind_domain_wrapped_domain)(__isl_take TYPE *obj,
+	__isl_take isl_multi_id *tuple)
+{
+	isl_space *space;
+
+	obj = FN(TYPE,equate_domain_wrapped_domain_params)(obj, tuple);
+	space = FN(TYPE,get_space)(obj);
+	space = isl_space_bind_domain_wrapped_domain(space, tuple);
+	isl_multi_id_free(tuple);
+	obj = FN(TYPE,reset_space)(obj, space);
+
+	return obj;
+}

diff  --git a/polly/lib/External/isl/isl_bound.c b/polly/lib/External/isl/isl_bound.c
index 29aae9a213ec..60d4ec7d37d1 100644
--- a/polly/lib/External/isl/isl_bound.c
+++ b/polly/lib/External/isl/isl_bound.c
@@ -109,11 +109,11 @@ static isl_stat 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_space *space;
 	isl_pw_qpolynomial_fold *top_pwf;
 	isl_pw_qpolynomial_fold *top_pwf_tight;
-	int nparam;
-	int n_in;
+	isl_size nparam;
+	isl_size n_in;
 	isl_stat r;
 
 	if (!bound->wrapping)
@@ -121,23 +121,25 @@ static isl_stat guarded_poly_bound(__isl_take isl_basic_set *bset,
 
 	nparam = isl_space_dim(bound->dim, isl_dim_param);
 	n_in = isl_space_dim(bound->dim, isl_dim_in);
+	if (nparam < 0 || n_in < 0)
+		goto error;
 
 	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);
+	space = isl_basic_set_get_space(bset);
+	space = isl_space_params(space);
 
 	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),
+	space = isl_space_from_domain(space);
+	space = isl_space_add_dims(space, isl_dim_out, 1);
+	bound->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(space),
 						  bound->type);
-	bound->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, bound->type);
+	bound->pwf_tight = isl_pw_qpolynomial_fold_zero(space, bound->type);
 
 	r = unwrapped_guarded_poly_bound(bset, poly, user);
 
@@ -151,6 +153,10 @@ static isl_stat guarded_poly_bound(__isl_take isl_basic_set *bset,
 							bound->pwf_tight);
 
 	return r;
+error:
+	isl_basic_set_free(bset);
+	isl_qpolynomial_free(poly);
+	return isl_stat_error;
 }
 
 static isl_stat guarded_qp(__isl_take isl_qpolynomial *qp, void *user)
@@ -203,11 +209,11 @@ static isl_stat guarded_fold(__isl_take isl_set *set,
 }
 
 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
-	__isl_take isl_pw_qpolynomial_fold *pwf, int *tight)
+	__isl_take isl_pw_qpolynomial_fold *pwf, isl_bool *tight)
 {
-	unsigned nvar;
+	isl_size nvar;
 	struct isl_bound bound;
-	int covers;
+	isl_bool covers;
 
 	if (!pwf)
 		return NULL;
@@ -218,13 +224,15 @@ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
 	if (bound.wrapping)
 		bound.dim = isl_space_unwrap(bound.dim);
 	nvar = isl_space_dim(bound.dim, isl_dim_out);
+	if (nvar < 0)
+		bound.dim = isl_space_free(bound.dim);
 	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;
+			*tight = isl_bool_true;
 		return isl_pw_qpolynomial_fold_reset_space(pwf, bound.dim);
 	}
 
@@ -232,7 +240,7 @@ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
 		enum isl_fold type = pwf->type;
 		isl_pw_qpolynomial_fold_free(pwf);
 		if (tight)
-			*tight = 1;
+			*tight = isl_bool_true;
 		return isl_pw_qpolynomial_fold_zero(bound.dim, type);
 	}
 
@@ -273,7 +281,8 @@ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
 }
 
 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_bound(
-	__isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type, int *tight)
+	__isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type,
+	isl_bool *tight)
 {
 	isl_pw_qpolynomial_fold *pwf;
 
@@ -283,7 +292,7 @@ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_bound(
 
 struct isl_union_bound_data {
 	enum isl_fold type;
-	int tight;
+	isl_bool tight;
 	isl_union_pw_qpolynomial_fold *res;
 };
 
@@ -302,7 +311,7 @@ static isl_stat bound_pw(__isl_take isl_pw_qpolynomial *pwqp, void *user)
 
 __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)
+	enum isl_fold type, isl_bool *tight)
 {
 	isl_space *dim;
 	struct isl_union_bound_data data = { type, 1, NULL };
@@ -311,7 +320,7 @@ __isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_bound(
 		return NULL;
 
 	if (!tight)
-		data.tight = 0;
+		data.tight = isl_bool_false;
 
 	dim = isl_union_pw_qpolynomial_get_space(upwqp);
 	data.res = isl_union_pw_qpolynomial_fold_zero(dim, type);

diff  --git a/polly/lib/External/isl/isl_box.c b/polly/lib/External/isl/isl_box.c
index b90ef869f349..437b136c4d98 100644
--- a/polly/lib/External/isl/isl_box.c
+++ b/polly/lib/External/isl/isl_box.c
@@ -76,7 +76,8 @@ static __isl_give isl_fixed_box *isl_fixed_box_init(
 	isl_multi_val *size;
 
 	offset = isl_multi_aff_zero(isl_space_copy(space));
-	size = isl_multi_val_zero(isl_space_range(space));
+	space = isl_space_drop_all_params(isl_space_range(space));
+	size = isl_multi_val_zero(space);
 	return isl_fixed_box_alloc(offset, size);
 }
 
@@ -130,7 +131,8 @@ static __isl_give isl_fixed_box *isl_fixed_box_set_valid_extent(
 static __isl_give isl_fixed_box *isl_fixed_box_invalidate(
 	__isl_take isl_fixed_box *box)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_val *infty;
 	isl_aff *nan;
@@ -138,6 +140,8 @@ static __isl_give isl_fixed_box *isl_fixed_box_invalidate(
 	if (!box)
 		return NULL;
 	n = isl_multi_val_dim(box->size, isl_dim_set);
+	if (n < 0)
+		return isl_fixed_box_free(box);
 
 	infty = isl_val_infty(isl_fixed_box_get_ctx(box));
 	space = isl_space_domain(isl_fixed_box_get_space(box));
@@ -152,6 +156,27 @@ static __isl_give isl_fixed_box *isl_fixed_box_invalidate(
 	return box;
 }
 
+/* Project the domain of the fixed box onto its parameter space.
+ * In particular, project out the domain of the offset.
+ */
+static __isl_give isl_fixed_box *isl_fixed_box_project_domain_on_params(
+	__isl_take isl_fixed_box *box)
+{
+	isl_bool valid;
+
+	valid = isl_fixed_box_is_valid(box);
+	if (valid < 0)
+		return isl_fixed_box_free(box);
+	if (!valid)
+		return box;
+
+	box->offset = isl_multi_aff_project_domain_on_params(box->offset);
+	if (!box->offset)
+		return isl_fixed_box_free(box);
+
+	return box;
+}
+
 /* Return the isl_ctx to which "box" belongs.
  */
 isl_ctx *isl_fixed_box_get_ctx(__isl_keep isl_fixed_box *box)
@@ -212,7 +237,7 @@ __isl_give isl_multi_val *isl_fixed_box_get_size(__isl_keep isl_fixed_box *box)
  */
 struct isl_size_info {
 	isl_basic_set *bset;
-	int pos;
+	isl_size pos;
 	isl_val *size;
 	isl_aff *offset;
 };
@@ -225,7 +250,7 @@ struct isl_size_info {
  */
 static isl_bool is_suitable_bound(__isl_keep isl_constraint *c, unsigned pos)
 {
-	unsigned n_div;
+	isl_size n_div;
 	isl_bool is_bound, any_divs;
 
 	is_bound = isl_constraint_is_lower_bound(c, isl_dim_set, pos);
@@ -233,6 +258,8 @@ static isl_bool is_suitable_bound(__isl_keep isl_constraint *c, unsigned pos)
 		return is_bound;
 
 	n_div = isl_constraint_dim(c, isl_dim_div);
+	if (n_div < 0)
+		return isl_bool_error;
 	any_divs = isl_constraint_involves_dims(c, isl_dim_div, 0, n_div);
 	return isl_bool_not(any_divs);
 }
@@ -316,6 +343,8 @@ static __isl_give isl_fixed_box *set_dim_extent(__isl_take isl_fixed_box *box,
 	info.offset = NULL;
 	info.pos = isl_map_dim(map, isl_dim_in);
 	info.bset = isl_basic_map_wrap(isl_map_simple_hull(map));
+	if (info.pos < 0)
+		info.bset = isl_basic_set_free(info.bset);
 	if (isl_basic_set_foreach_constraint(info.bset,
 					&compute_size_in_direction, &info) < 0)
 		box = isl_fixed_box_free(box);
@@ -345,11 +374,14 @@ static __isl_give isl_fixed_box *set_dim_extent(__isl_take isl_fixed_box *box,
 __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull(
 	__isl_keep isl_map *map)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_fixed_box *box;
 
 	n = isl_map_dim(map, isl_dim_out);
+	if (n < 0)
+		return NULL;
 	space = isl_map_get_space(map);
 	box = isl_fixed_box_init(space);
 
@@ -366,3 +398,55 @@ __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull(
 
 	return box;
 }
+
+/* Try and construct a fixed-size rectangular box with an offset
+ * in terms of the parameters of "set" that contains "set".
+ * If no such box can be constructed, then return an invalidated box,
+ * i.e., one where isl_fixed_box_is_valid returns false.
+ *
+ * Compute the box using isl_map_get_range_simple_fixed_box_hull
+ * by constructing a map from the set and
+ * project out the domain again from the result.
+ */
+__isl_give isl_fixed_box *isl_set_get_simple_fixed_box_hull(
+	__isl_keep isl_set *set)
+{
+	isl_map *map;
+	isl_fixed_box *box;
+
+	map = isl_map_from_range(isl_set_copy(set));
+	box = isl_map_get_range_simple_fixed_box_hull(map);
+	isl_map_free(map);
+	box = isl_fixed_box_project_domain_on_params(box);
+
+	return box;
+}
+
+#undef BASE
+#define BASE multi_val
+#include "print_yaml_field_templ.c"
+
+#undef BASE
+#define BASE multi_aff
+#include "print_yaml_field_templ.c"
+
+/* Print the information contained in "box" to "p".
+ * The information is printed as a YAML document.
+ */
+__isl_give isl_printer *isl_printer_print_fixed_box(
+	__isl_take isl_printer *p, __isl_keep isl_fixed_box *box)
+{
+	if (!box)
+		return isl_printer_free(p);
+
+	p = isl_printer_yaml_start_mapping(p);
+	p = print_yaml_field_multi_aff(p, "offset", box->offset);
+	p = print_yaml_field_multi_val(p, "size", box->size);
+	p = isl_printer_yaml_end_mapping(p);
+
+	return p;
+}
+
+#undef BASE
+#define BASE fixed_box
+#include <print_templ_yaml.c>

diff  --git a/polly/lib/External/isl/isl_check_named_params_templ.c b/polly/lib/External/isl/isl_check_named_params_templ.c
new file mode 100644
index 000000000000..f900768ec478
--- /dev/null
+++ b/polly/lib/External/isl/isl_check_named_params_templ.c
@@ -0,0 +1,10 @@
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Check that "obj" has only named parameters, reporting an error
+ * if it does not.
+ */
+isl_stat FN(TYPE,check_named_params)(__isl_keep TYPE *obj)
+{
+	return isl_space_check_named_params(FN(TYPE,peek_space)(obj));
+}

diff  --git a/polly/lib/External/isl/isl_coalesce.c b/polly/lib/External/isl/isl_coalesce.c
index 1f96b7b4f296..79f1c1927afc 100644
--- a/polly/lib/External/isl/isl_coalesce.c
+++ b/polly/lib/External/isl/isl_coalesce.c
@@ -66,13 +66,17 @@ static int *eq_status_in(__isl_keep isl_basic_map *bmap_i,
 	struct isl_tab *tab_j)
 {
 	int k, l;
-	int *eq = isl_calloc_array(bmap_i->ctx, int, 2 * bmap_i->n_eq);
-	unsigned dim;
+	int *eq;
+	isl_size dim;
+
+	dim = isl_basic_map_dim(bmap_i, isl_dim_all);
+	if (dim < 0)
+		return NULL;
 
+	eq = isl_calloc_array(bmap_i->ctx, int, 2 * bmap_i->n_eq);
 	if (!eq)
 		return NULL;
 
-	dim = isl_basic_map_total_dim(bmap_i);
 	for (k = 0; k < bmap_i->n_eq; ++k) {
 		for (l = 0; l < 2; ++l) {
 			isl_seq_neg(bmap_i->eq[k], bmap_i->eq[k], 1+dim);
@@ -173,6 +177,8 @@ static int all(int *con, unsigned len, int status)
  * "bmap" is the basic map itself (or NULL if "removed" is set)
  * "tab" is the corresponding tableau (or NULL if "removed" is set)
  * "hull_hash" identifies the affine space in which "bmap" lives.
+ * "modified" is set if this basic map may not be identical
+ * to any of the basic maps in the input.
  * "removed" is set if this basic map has been removed from the map
  * "simplify" is set if this basic map may have some unknown integer
  * divisions that were not present in the input basic maps.  The basic
@@ -190,6 +196,7 @@ struct isl_coalesce_info {
 	isl_basic_map *bmap;
 	struct isl_tab *tab;
 	uint32_t hull_hash;
+	int modified;
 	int removed;
 	int simplify;
 	int *eq;
@@ -309,11 +316,13 @@ static int all_valid_or_cut(struct isl_coalesce_info *info)
 static int coalesce_info_set_hull_hash(struct isl_coalesce_info *info)
 {
 	isl_basic_map *hull;
-	unsigned n_div;
+	isl_size n_div;
 
 	hull = isl_basic_map_copy(info->bmap);
 	hull = isl_basic_map_plain_affine_hull(hull);
 	n_div = isl_basic_map_dim(hull, isl_dim_div);
+	if (n_div < 0)
+		hull = isl_basic_map_free(hull);
 	hull = isl_basic_map_drop_constraints_involving_dims(hull,
 							isl_dim_div, 0, n_div);
 	info->hull_hash = isl_basic_map_get_hash(hull);
@@ -340,15 +349,22 @@ static void clear_coalesce_info(int n, struct isl_coalesce_info *info)
 	free(info);
 }
 
+/* Clear the memory associated to "info".
+ */
+static void clear(struct isl_coalesce_info *info)
+{
+	info->bmap = isl_basic_map_free(info->bmap);
+	isl_tab_free(info->tab);
+	info->tab = NULL;
+}
+
 /* Drop the basic map represented by "info".
  * That is, clear the memory associated to the entry and
  * mark it as having been removed.
  */
 static void drop(struct isl_coalesce_info *info)
 {
-	info->bmap = isl_basic_map_free(info->bmap);
-	isl_tab_free(info->tab);
-	info->tab = NULL;
+	clear(info);
 	info->removed = 1;
 }
 
@@ -491,11 +507,13 @@ static enum isl_change fuse(int i, int j, struct isl_coalesce_info *info,
 	int k, l;
 	struct isl_basic_map *fused = NULL;
 	struct isl_tab *fused_tab = NULL;
-	unsigned total = isl_basic_map_total_dim(info[i].bmap);
+	isl_size total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
 	unsigned extra_rows = extra ? extra->n_row : 0;
 	unsigned n_eq, n_ineq;
 	int simplify = 0;
 
+	if (total < 0)
+		return isl_change_error;
 	if (j < i)
 		return fuse(j, i, info, extra, detect_equalities, check_number);
 
@@ -552,10 +570,10 @@ static enum isl_change fuse(int i, int j, struct isl_coalesce_info *info,
 		return isl_change_none;
 	}
 
-	isl_basic_map_free(info[i].bmap);
+	clear(&info[i]);
 	info[i].bmap = fused;
-	isl_tab_free(info[i].tab);
 	info[i].tab = fused_tab;
+	info[i].modified = 1;
 	drop(&info[j]);
 
 	return isl_change_fuse;
@@ -644,10 +662,12 @@ static enum isl_change check_facets(int i, int j,
 static isl_bool contains(struct isl_coalesce_info *info, struct isl_tab *tab)
 {
 	int k;
-	unsigned dim;
+	isl_size dim;
 	isl_basic_map *bmap = info->bmap;
 
-	dim = isl_basic_map_total_dim(bmap);
+	dim = isl_basic_map_dim(bmap, isl_dim_all);
+	if (dim < 0)
+		return isl_bool_error;
 	for (k = 0; k < bmap->n_eq; ++k) {
 		int stat;
 		isl_seq_neg(bmap->eq[k], bmap->eq[k], 1 + dim);
@@ -723,10 +743,12 @@ static enum isl_change is_adj_ineq_extension(int i, int j,
 	int k;
 	struct isl_tab_undo *snap;
 	unsigned n_eq = info[i].bmap->n_eq;
-	unsigned total = isl_basic_map_total_dim(info[i].bmap);
+	isl_size total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
 	isl_stat r;
 	isl_bool super;
 
+	if (total < 0)
+		return isl_change_error;
 	if (isl_tab_extend_cons(info[i].tab, 1 + info[j].bmap->n_ineq) < 0)
 		return isl_change_error;
 
@@ -982,7 +1004,7 @@ static __isl_give isl_vec *try_tightening(struct isl_coalesce_info *info,
 static isl_stat tighten_on_relaxed_facet(struct isl_coalesce_info *info,
 	int n, int *relaxed, int l)
 {
-	unsigned total;
+	isl_size total;
 	isl_ctx *ctx;
 	isl_vec *v = NULL;
 	isl_mat *T;
@@ -992,7 +1014,9 @@ static isl_stat tighten_on_relaxed_facet(struct isl_coalesce_info *info,
 
 	k = relaxed[l];
 	ctx = isl_basic_map_get_ctx(info->bmap);
-	total = isl_basic_map_total_dim(info->bmap);
+	total = isl_basic_map_dim(info->bmap, isl_dim_all);
+	if (total < 0)
+		return isl_stat_error;
 	isl_int_add_ui(info->bmap->ineq[k][0], info->bmap->ineq[k][0], 1);
 	T = isl_mat_sub_alloc6(ctx, info->bmap->ineq, k, 1, 0, 1 + total);
 	T = isl_mat_variable_compression(T, NULL);
@@ -1057,12 +1081,12 @@ static enum isl_change extend(int i, int j, int n, int *relax,
 	struct isl_coalesce_info *info)
 {
 	int l;
-	unsigned total;
+	isl_size total;
 
 	info[i].bmap = isl_basic_map_cow(info[i].bmap);
-	if (!info[i].bmap)
+	total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
+	if (total < 0)
 		return isl_change_error;
-	total = isl_basic_map_total_dim(info[i].bmap);
 	for (l = 0; l < info[i].bmap->n_div; ++l)
 		if (!isl_seq_eq(info[i].bmap->div[l],
 				info[j].bmap->div[l], 1 + 1 + total)) {
@@ -1072,8 +1096,10 @@ static enum isl_change extend(int i, int j, int n, int *relax,
 	for (l = 0; l < n; ++l)
 		isl_int_add_ui(info[i].bmap->ineq[relax[l]][0],
 				info[i].bmap->ineq[relax[l]][0], 1);
+	ISL_F_CLR(info[i].bmap, ISL_BASIC_MAP_NO_REDUNDANT);
 	ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_FINAL);
 	drop(&info[j]);
+	info[i].modified = 1;
 	if (j < i)
 		exchange(&info[i], &info[j]);
 	return isl_change_fuse;
@@ -1191,8 +1217,10 @@ static isl_stat wraps_update_max(struct isl_wraps *wraps,
 {
 	int k;
 	isl_int max_k;
-	unsigned total = isl_basic_map_total_dim(info->bmap);
+	isl_size total = isl_basic_map_dim(info->bmap, isl_dim_all);
 
+	if (total < 0)
+		return isl_stat_error;
 	isl_int_init(max_k);
 
 	for (k = 0; k < info->bmap->n_eq; ++k) {
@@ -1256,6 +1284,14 @@ static void wraps_free(struct isl_wraps *wraps)
 		isl_int_clear(wraps->max);
 }
 
+/* Mark the wrapping as failed by resetting wraps->mat->n_row to zero.
+ */
+static isl_stat wraps_mark_failed(struct isl_wraps *wraps)
+{
+	wraps->mat->n_row = 0;
+	return isl_stat_ok;
+}
+
 /* Is the wrapping constraint in row "row" allowed?
  *
  * If wraps->bound is set, we check that none of the coefficients
@@ -1327,7 +1363,11 @@ static isl_stat add_wraps(struct isl_wraps *wraps,
 	int w;
 	int added;
 	isl_basic_map *bmap = info->bmap;
-	unsigned len = 1 + isl_basic_map_total_dim(bmap);
+	isl_size total = isl_basic_map_dim(bmap, isl_dim_all);
+	unsigned len = 1 + total;
+
+	if (total < 0)
+		return isl_stat_error;
 
 	w = wraps->mat->n_row;
 
@@ -1371,8 +1411,7 @@ static isl_stat add_wraps(struct isl_wraps *wraps,
 	wraps->mat->n_row = w;
 	return isl_stat_ok;
 unbounded:
-	wraps->mat->n_row = 0;
-	return isl_stat_ok;
+	return wraps_mark_failed(wraps);
 }
 
 /* Check if the constraints in "wraps" from "first" until the last
@@ -1426,6 +1465,32 @@ static __isl_give isl_set *set_from_updated_bmap(__isl_keep isl_basic_map *bmap,
 	return isl_set_from_basic_set(bset);
 }
 
+/* Does "info" have any cut constraints that are redundant?
+ */
+static isl_bool has_redundant_cuts(struct isl_coalesce_info *info)
+{
+	int l;
+	int n_eq, n_ineq;
+
+	n_eq = isl_basic_map_n_equality(info->bmap);
+	n_ineq = isl_basic_map_n_inequality(info->bmap);
+	if (n_eq < 0 || n_ineq < 0)
+		return isl_bool_error;
+	for (l = 0; l < n_ineq; ++l) {
+		int red;
+
+		if (info->ineq[l] != STATUS_CUT)
+			continue;
+		red = isl_tab_is_redundant(info->tab, n_eq + l);
+		if (red < 0)
+			return isl_bool_error;
+		if (red)
+			return isl_bool_true;
+	}
+
+	return isl_bool_false;
+}
+
 /* Wrap the constraints of info->bmap that bound the facet defined
  * by inequality "k" around (the opposite of) this inequality to
  * include "set".  "bound" may be used to store the negated inequality.
@@ -1433,14 +1498,24 @@ static __isl_give isl_set *set_from_updated_bmap(__isl_keep isl_basic_map *bmap,
  * of info->bmap, we check them in check_wraps.
  * If any of the wrapped constraints turn out to be invalid, then
  * check_wraps will reset wrap->n_row to zero.
+ *
+ * If any of the cut constraints of info->bmap turn out
+ * to be redundant with respect to other constraints
+ * then these will neither be wrapped nor added directly to the result.
+ * The result may therefore not be correct.
+ * Skip wrapping and reset wrap->mat->n_row to zero in this case.
  */
 static isl_stat add_wraps_around_facet(struct isl_wraps *wraps,
 	struct isl_coalesce_info *info, int k, isl_int *bound,
 	__isl_keep isl_set *set)
 {
+	isl_bool nowrap;
 	struct isl_tab_undo *snap;
 	int n;
-	unsigned total = isl_basic_map_total_dim(info->bmap);
+	isl_size total = isl_basic_map_dim(info->bmap, isl_dim_all);
+
+	if (total < 0)
+		return isl_stat_error;
 
 	snap = isl_tab_snap(info->tab);
 
@@ -1448,15 +1523,22 @@ static isl_stat add_wraps_around_facet(struct isl_wraps *wraps,
 		return isl_stat_error;
 	if (isl_tab_detect_redundant(info->tab) < 0)
 		return isl_stat_error;
-
-	isl_seq_neg(bound, info->bmap->ineq[k], 1 + total);
+	nowrap = has_redundant_cuts(info);
+	if (nowrap < 0)
+		return isl_stat_error;
 
 	n = wraps->mat->n_row;
-	if (add_wraps(wraps, info, bound, set) < 0)
-		return isl_stat_error;
+	if (!nowrap) {
+		isl_seq_neg(bound, info->bmap->ineq[k], 1 + total);
+
+		if (add_wraps(wraps, info, bound, set) < 0)
+			return isl_stat_error;
+	}
 
 	if (isl_tab_rollback(info->tab, snap) < 0)
 		return isl_stat_error;
+	if (nowrap)
+		return wraps_mark_failed(wraps);
 	if (check_wraps(wraps->mat, n, info->tab) < 0)
 		return isl_stat_error;
 
@@ -1494,8 +1576,10 @@ static enum isl_change can_wrap_in_facet(int i, int j, int k,
 	struct isl_set *set_i = NULL;
 	struct isl_set *set_j = NULL;
 	struct isl_vec *bound = NULL;
-	unsigned total = isl_basic_map_total_dim(info[i].bmap);
+	isl_size total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
 
+	if (total < 0)
+		return isl_change_error;
 	set_i = set_from_updated_bmap(info[i].bmap, info[i].tab);
 	set_j = set_from_updated_bmap(info[j].bmap, info[j].tab);
 	ctx = isl_basic_map_get_ctx(info[i].bmap);
@@ -1611,10 +1695,12 @@ static enum isl_change try_wrap_in_facets(int i, int j,
 	__isl_keep isl_set *set_i)
 {
 	int k, l, w;
-	unsigned total;
+	isl_size total;
 	struct isl_tab_undo *snap;
 
-	total = isl_basic_map_total_dim(info[i].bmap);
+	total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
+	if (total < 0)
+		return isl_change_error;
 
 	snap = isl_tab_snap(info[j].tab);
 
@@ -1674,9 +1760,11 @@ static enum isl_change wrap_in_facets(int i, int j, int n,
 	isl_ctx *ctx;
 	isl_mat *mat;
 	isl_set *set_i = NULL;
-	unsigned total = isl_basic_map_total_dim(info[i].bmap);
+	isl_size total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
 	int max_wrap;
 
+	if (total < 0)
+		return isl_change_error;
 	if (isl_tab_extend_cons(info[j].tab, 1) < 0)
 		return isl_change_error;
 
@@ -1781,7 +1869,7 @@ static enum isl_change can_wrap_in_set(int i, int j,
 {
 	int k, l;
 	int n;
-	unsigned total;
+	isl_size total;
 
 	if (ISL_F_ISSET(info[i].bmap, ISL_BASIC_MAP_RATIONAL) ||
 	    ISL_F_ISSET(info[j].bmap, ISL_BASIC_MAP_RATIONAL))
@@ -1791,7 +1879,9 @@ static enum isl_change can_wrap_in_set(int i, int j,
 	if (n == 0)
 		return isl_change_none;
 
-	total = isl_basic_map_total_dim(info[i].bmap);
+	total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
+	if (total < 0)
+		return isl_change_error;
 	for (k = 0; k < info[i].bmap->n_eq; ++k) {
 		for (l = 0; l < 2; ++l) {
 			enum isl_ineq_type type;
@@ -2028,8 +2118,10 @@ static enum isl_change check_eq_adj_eq(int i, int j,
 	struct isl_set *set_i = NULL;
 	struct isl_set *set_j = NULL;
 	struct isl_vec *bound = NULL;
-	unsigned total = isl_basic_map_total_dim(info[i].bmap);
+	isl_size total = isl_basic_map_dim(info[i].bmap, isl_dim_all);
 
+	if (total < 0)
+		return isl_change_error;
 	if (count_eq(&info[i], STATUS_ADJ_EQ) != 1)
 		detect_equalities = 1;
 
@@ -2372,14 +2464,17 @@ static enum isl_change coalesce_local_pair(int i, int j,
 static isl_stat shift_div(struct isl_coalesce_info *info, int div,
 	isl_int shift)
 {
-	unsigned total;
+	isl_size total, n_div;
 
 	info->bmap = isl_basic_map_shift_div(info->bmap, div, 0, shift);
 	if (!info->bmap)
 		return isl_stat_error;
 
 	total = isl_basic_map_dim(info->bmap, isl_dim_all);
-	total -= isl_basic_map_dim(info->bmap, isl_dim_div);
+	n_div = isl_basic_map_dim(info->bmap, isl_dim_div);
+	if (total < 0 || n_div < 0)
+		return isl_stat_error;
+	total -= n_div;
 	if (isl_tab_shift_var(info->tab, total + div, shift) < 0)
 		return isl_stat_error;
 
@@ -2466,9 +2561,12 @@ static isl_stat normalize_stride_div(struct isl_coalesce_info *info, int div)
 static isl_stat harmonize_stride_divs(struct isl_coalesce_info *info1,
 	struct isl_coalesce_info *info2)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_basic_map_dim(info1->bmap, isl_dim_div);
+	if (n < 0)
+		return isl_stat_error;
 	for (i = 0; i < n; ++i) {
 		isl_bool known, harmonize;
 
@@ -2577,10 +2675,12 @@ static isl_stat harmonize_divs_with_hulls(struct isl_coalesce_info *info1,
 	__isl_keep isl_basic_set *eq2)
 {
 	int i;
-	int total;
+	isl_size total;
 	isl_local_space *ls1, *ls2;
 
-	total = isl_basic_map_total_dim(info1->bmap);
+	total = isl_basic_map_dim(info1->bmap, isl_dim_all);
+	if (total < 0)
+		return isl_stat_error;
 	ls1 = isl_local_space_wrap(isl_basic_map_get_local_space(info1->bmap));
 	ls2 = isl_local_space_wrap(isl_basic_map_get_local_space(info2->bmap));
 	for (i = 0; i < info1->bmap->n_div; ++i) {
@@ -2684,7 +2784,7 @@ static isl_bool same_divs(__isl_keep isl_basic_map *bmap1,
 {
 	int i;
 	isl_bool known;
-	int total;
+	isl_size total;
 
 	if (!bmap1 || !bmap2)
 		return isl_bool_error;
@@ -2701,7 +2801,9 @@ static isl_bool same_divs(__isl_keep isl_basic_map *bmap1,
 	if (known < 0 || !known)
 		return known;
 
-	total = isl_basic_map_total_dim(bmap1);
+	total = isl_basic_map_dim(bmap1, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
 	for (i = 0; i < bmap1->n_div; ++i)
 		if (!isl_seq_eq(bmap1->div[i], bmap2->div[i], 2 + total))
 			return isl_bool_false;
@@ -2784,9 +2886,8 @@ static isl_stat fix_constant_divs(struct isl_coalesce_info *info,
 		if (!expanded[i].cst) {
 			info->bmap = isl_basic_map_extend_constraints(
 						info->bmap, 0, 2);
-			if (isl_basic_map_add_div_constraints(info->bmap,
-						expanded[i].pos - o_div) < 0)
-				break;
+			info->bmap = isl_basic_map_add_div_constraints(
+					info->bmap, expanded[i].pos - o_div);
 		} else {
 			isl_int_set_si(ineq->el[1 + expanded[i].pos], -1);
 			isl_int_set(ineq->el[0], expanded[i].val);
@@ -2891,7 +2992,8 @@ static isl_stat tab_insert_divs(struct isl_coalesce_info *info,
 		if (isl_tab_rollback(info->tab, snap) < 0)
 			return isl_stat_error;
 		info->bmap = isl_basic_map_cow(info->bmap);
-		if (isl_basic_map_free_inequality(info->bmap, 2 * n) < 0)
+		info->bmap = isl_basic_map_free_inequality(info->bmap, 2 * n);
+		if (info->bmap < 0)
 			return isl_stat_error;
 
 		return fix_constant_divs(info, n, expanded);
@@ -2929,11 +3031,14 @@ static isl_stat expand_tab(struct isl_coalesce_info *info, int *exp,
 	struct isl_expanded *expanded;
 	int i, j, k, n;
 	int extra_var;
-	unsigned total, pos, n_div;
+	isl_size total, n_div;
+	unsigned pos;
 	isl_stat r;
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (total < 0 || n_div < 0)
+		return isl_stat_error;
 	pos = total - n_div;
 	extra_var = total - info->tab->n_var;
 	n = n_div - extra_var;
@@ -3297,11 +3402,13 @@ static enum isl_change coalesce_divs(int i, int j,
 static isl_bool has_nested_div(__isl_keep isl_basic_map *bmap)
 {
 	int i;
-	unsigned total;
-	unsigned n_div;
+	isl_size total;
+	isl_size n_div;
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (total < 0 || n_div < 0)
+		return isl_bool_error;
 	total -= n_div;
 
 	for (i = 0; i < n_div; ++i)
@@ -3327,7 +3434,7 @@ static __isl_give isl_aff_list *set_up_substitutions(
 	__isl_keep isl_basic_map *bmap_i, __isl_keep isl_basic_map *bmap_j,
 	__isl_take isl_basic_map *hull)
 {
-	unsigned n_div_i, n_div_j, total;
+	isl_size n_div_i, n_div_j, total;
 	isl_ctx *ctx;
 	isl_local_space *ls;
 	isl_basic_set *wrap_hull;
@@ -3335,14 +3442,14 @@ static __isl_give isl_aff_list *set_up_substitutions(
 	isl_aff_list *list;
 	int i, j;
 
-	if (!hull)
+	n_div_i = isl_basic_map_dim(bmap_i, isl_dim_div);
+	n_div_j = isl_basic_map_dim(bmap_j, isl_dim_div);
+	total = isl_basic_map_dim(bmap_i, isl_dim_all);
+	if (!hull || n_div_i < 0 || n_div_j < 0 || total < 0)
 		return NULL;
 
 	ctx = isl_basic_map_get_ctx(hull);
-
-	n_div_i = isl_basic_map_dim(bmap_i, isl_dim_div);
-	n_div_j = isl_basic_map_dim(bmap_j, isl_dim_div);
-	total = isl_basic_map_total_dim(bmap_i) - n_div_i;
+	total -= n_div_i;
 
 	ls = isl_basic_map_get_local_space(bmap_i);
 	ls = isl_local_space_wrap(ls);
@@ -3354,6 +3461,7 @@ static __isl_give isl_aff_list *set_up_substitutions(
 	j = 0;
 	for (i = 0; i < n_div_i; ++i) {
 		isl_aff *aff;
+		isl_size n_div;
 
 		if (j < n_div_j &&
 		    isl_basic_map_equal_div_expr_part(bmap_i, i, bmap_j, j,
@@ -3369,9 +3477,10 @@ static __isl_give isl_aff_list *set_up_substitutions(
 		aff = isl_aff_substitute_equalities(aff,
 						isl_basic_set_copy(wrap_hull));
 		aff = isl_aff_floor(aff);
-		if (!aff)
+		n_div = isl_aff_dim(aff, isl_dim_div);
+		if (n_div < 0)
 			goto error;
-		if (isl_aff_dim(aff, isl_dim_div) != 0) {
+		if (n_div != 0) {
 			isl_aff_free(aff);
 			break;
 		}
@@ -3411,16 +3520,14 @@ static __isl_give isl_aff_list *set_up_substitutions(
 static isl_stat add_sub_vars(struct isl_coalesce_info *info,
 	__isl_keep isl_aff_list *list, int dim, int extra_var)
 {
-	int i, j, n, d;
-	isl_space *space;
+	int i, j, d;
+	isl_size n;
 
-	space = isl_basic_map_get_space(info->bmap);
 	info->bmap = isl_basic_map_cow(info->bmap);
-	info->bmap = isl_basic_map_extend_space(info->bmap, space,
-						extra_var, 0, 0);
-	if (!info->bmap)
-		return isl_stat_error;
+	info->bmap = isl_basic_map_extend(info->bmap, extra_var, 0, 0);
 	n = isl_aff_list_n_aff(list);
+	if (!info->bmap || n < 0)
+		return isl_stat_error;
 	for (i = 0; i < n; ++i) {
 		int is_nan;
 		isl_aff *aff;
@@ -3439,10 +3546,11 @@ static isl_stat add_sub_vars(struct isl_coalesce_info *info,
 		if (d < 0)
 			return isl_stat_error;
 		info->bmap = isl_basic_map_mark_div_unknown(info->bmap, d);
+		for (j = d; j > i; --j)
+			info->bmap = isl_basic_map_swap_div(info->bmap,
+							    j - 1, j);
 		if (!info->bmap)
 			return isl_stat_error;
-		for (j = d; j > i; --j)
-			isl_basic_map_swap_div(info->bmap, j - 1, j);
 	}
 
 	return isl_stat_ok;
@@ -3456,20 +3564,23 @@ static isl_stat add_sub_vars(struct isl_coalesce_info *info,
  * This function assumes that a sufficient number of rows and
  * elements in the constraint array are available in the tableau.
  */
-static int add_sub_equalities(struct isl_tab *tab,
+static isl_stat add_sub_equalities(struct isl_tab *tab,
 	__isl_keep isl_aff_list *list, int dim)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_vec *sub;
 	isl_aff *aff;
 
 	n = isl_aff_list_n_aff(list);
+	if (n < 0)
+		return isl_stat_error;
 
 	ctx = isl_tab_get_ctx(tab);
 	sub = isl_vec_alloc(ctx, 1 + dim + n);
 	if (!sub)
-		return -1;
+		return isl_stat_error;
 	isl_seq_clr(sub->el + 1 + dim, n);
 
 	for (i = 0; i < n; ++i) {
@@ -3489,11 +3600,11 @@ static int add_sub_equalities(struct isl_tab *tab,
 	}
 
 	isl_vec_free(sub);
-	return 0;
+	return isl_stat_ok;
 error:
 	isl_aff_free(aff);
 	isl_vec_free(sub);
-	return -1;
+	return isl_stat_error;
 }
 
 /* Add variables to info->tab and info->bmap corresponding to the elements
@@ -3504,24 +3615,24 @@ static int add_sub_equalities(struct isl_tab *tab,
  * When this function returns, the total number of variables in info->tab
  * is equal to "dim" plus the number of elements in "list".
  */
-static int add_subs(struct isl_coalesce_info *info,
+static isl_stat add_subs(struct isl_coalesce_info *info,
 	__isl_keep isl_aff_list *list, int dim)
 {
 	int extra_var;
-	int n;
-
-	if (!list)
-		return -1;
+	isl_size n;
 
 	n = isl_aff_list_n_aff(list);
+	if (n < 0)
+		return isl_stat_error;
+
 	extra_var = n - (info->tab->n_var - dim);
 
 	if (isl_tab_extend_vars(info->tab, extra_var) < 0)
-		return -1;
+		return isl_stat_error;
 	if (isl_tab_extend_cons(info->tab, 2 * extra_var) < 0)
-		return -1;
+		return isl_stat_error;
 	if (add_sub_vars(info, list, dim, extra_var) < 0)
-		return -1;
+		return isl_stat_error;
 
 	return add_sub_equalities(info->tab, list, dim);
 }
@@ -3544,14 +3655,17 @@ static enum isl_change coalesce_with_subs(int i, int j,
 {
 	isl_basic_map *bmap_j;
 	struct isl_tab_undo *snap;
-	unsigned dim;
+	isl_size dim, n_div;
 	enum isl_change change;
 
 	bmap_j = isl_basic_map_copy(info[j].bmap);
 	snap = isl_tab_snap(info[j].tab);
 
 	dim = isl_basic_map_dim(bmap_j, isl_dim_all);
-	dim -= isl_basic_map_dim(bmap_j, isl_dim_div);
+	n_div = isl_basic_map_dim(bmap_j, isl_dim_div);
+	if (dim < 0 || n_div < 0)
+		goto error;
+	dim -= n_div;
 	if (add_subs(&info[j], list, dim) < 0)
 		goto error;
 
@@ -3583,20 +3697,22 @@ static enum isl_change coalesce_with_subs(int i, int j,
  * extra equalities to a purely affine expression.
  * If these tests succeed, then we try to coalesce the two basic maps
  * by introducing extra dimensions in "j" corresponding to
- * the extra integer divsisions "i" fixed to the corresponding
+ * the extra integer divisions "i" fixed to the corresponding
  * purely affine expression.
  */
 static enum isl_change check_coalesce_into_eq(int i, int j,
 	struct isl_coalesce_info *info)
 {
-	unsigned n_div_i, n_div_j;
+	isl_size n_div_i, n_div_j, n;
 	isl_basic_map *hull_i, *hull_j;
-	int equal, empty;
+	isl_bool equal, empty;
 	isl_aff_list *list;
 	enum isl_change change;
 
 	n_div_i = isl_basic_map_dim(info[i].bmap, isl_dim_div);
 	n_div_j = isl_basic_map_dim(info[j].bmap, isl_dim_div);
+	if (n_div_i < 0 || n_div_j < 0)
+		return isl_change_error;
 	if (n_div_i <= n_div_j)
 		return isl_change_none;
 	if (info[j].bmap->n_eq == 0)
@@ -3622,7 +3738,10 @@ static enum isl_change check_coalesce_into_eq(int i, int j,
 	list = set_up_substitutions(info[i].bmap, info[j].bmap, hull_j);
 	if (!list)
 		return isl_change_error;
-	if (isl_aff_list_n_aff(list) < n_div_i)
+	n = isl_aff_list_n_aff(list);
+	if (n < 0)
+		change = isl_change_error;
+	else if (n < n_div_i)
 		change = isl_change_none;
 	else
 		change = coalesce_with_subs(i, j, info, list);
@@ -3813,6 +3932,10 @@ static int coalesce(isl_ctx *ctx, int n, struct isl_coalesce_info *info)
  * isl_basic_map_gauss, we need to do it now.
  * Also call isl_basic_map_simplify if we may have lost the definition
  * of one or more integer divisions.
+ * If a basic map is still equal to the one from which the corresponding "info"
+ * entry was created, then redundant constraint and
+ * implicit equality constraint detection have been performed
+ * on the corresponding tableau and the basic map can be marked as such.
  */
 static __isl_give isl_map *update_basic_maps(__isl_take isl_map *map,
 	int n, struct isl_coalesce_info *info)
@@ -3839,8 +3962,10 @@ static __isl_give isl_map *update_basic_maps(__isl_take isl_map *map,
 		info[i].bmap = isl_basic_map_finalize(info[i].bmap);
 		if (!info[i].bmap)
 			return isl_map_free(map);
-		ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_NO_IMPLICIT);
-		ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+		if (!info[i].modified) {
+			ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_NO_IMPLICIT);
+			ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+		}
 		isl_basic_map_free(map->p[i]);
 		map->p[i] = info[i].bmap;
 		info[i].bmap = NULL;
@@ -3855,16 +3980,22 @@ static __isl_give isl_map *update_basic_maps(__isl_take isl_map *map,
  *
  * We factor out any (hidden) common factor from the constraint
  * coefficients to improve the detection of adjacent constraints.
+ * Note that this function does not call isl_basic_map_gauss,
+ * but it does make sure that only a single copy of the basic map
+ * is affected.  This means that isl_basic_map_gauss may have
+ * to be called at the end of the computation (in update_basic_maps)
+ * on this single copy to ensure that
+ * the basic maps are not left in an unexpected state.
  *
  * Since we are constructing the tableaus of the basic maps anyway,
  * we exploit them to detect implicit equalities and redundant constraints.
  * This also helps the coalescing as it can ignore the redundant constraints.
  * In order to avoid confusion, we make all implicit equalities explicit
- * in the basic maps.  We don't call isl_basic_map_gauss, though,
- * as that may affect the number of constraints.
- * This means that we have to call isl_basic_map_gauss at the end
- * of the computation (in update_basic_maps) to ensure that
- * the basic maps are not left in an unexpected state.
+ * in the basic maps.  If the basic map only has a single reference
+ * (this happens in particular if it was modified by
+ * isl_basic_map_reduce_coefficients), then isl_basic_map_gauss
+ * does not get called on the result.  The call to
+ * isl_basic_map_gauss in update_basic_maps resolves this as well.
  * For each basic map, we also compute the hash of the apparent affine hull
  * for use in coalesce.
  */

diff  --git a/polly/lib/External/isl/isl_config.h.in b/polly/lib/External/isl/isl_config.h.in
index 781c960eab21..0170b3115c9c 100644
--- a/polly/lib/External/isl/isl_config.h.in
+++ b/polly/lib/External/isl/isl_config.h.in
@@ -18,6 +18,9 @@
 /* Define if TargetInfo::CreateTargetInfo takes shared_ptr */
 #undef CREATETARGETINFO_TAKES_SHARED_PTR
 
+/* Define if CompilerInvocation::CreateFromArgs takes ArrayRef */
+#undef CREATE_FROM_ARGS_TAKES_ARRAYREF
+
 /* Define if Driver constructor takes default image name */
 #undef DRIVER_CTOR_TAKES_DEFAULTIMAGENAME
 
@@ -94,6 +97,9 @@
 /* Define to 1 if you have the `gmp' library (-lgmp). */
 #undef HAVE_LIBGMP
 
+/* Define if llvm/Option/Arg.h exists */
+#undef HAVE_LLVM_OPTION_ARG_H
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -130,7 +136,7 @@
 /* Return type of HandleTopLevelDeclReturn */
 #undef HandleTopLevelDeclReturn
 
-/* Define to InputKind::C for newer versions of clang */
+/* Define to Language::C or InputKind::C for newer versions of clang */
 #undef IK_C
 
 /* Define to the sub-directory where libtool stores uninstalled libraries. */

diff  --git a/polly/lib/External/isl/isl_config_post.h b/polly/lib/External/isl/isl_config_post.h
index 39373af3ae93..4ceb7f0edb73 100644
--- a/polly/lib/External/isl/isl_config_post.h
+++ b/polly/lib/External/isl/isl_config_post.h
@@ -27,7 +27,7 @@ int isl_ffs(int i);
 #define strncasecmp _strnicmp
 #endif
 
-#if !HAVE_DECL_SNPRINTF && HAVE_DECL__SNPRINTF
+#if HAVE_DECL__SNPRINTF
 #define snprintf _snprintf
 #endif
 

diff  --git a/polly/lib/External/isl/isl_constraint.c b/polly/lib/External/isl/isl_constraint.c
index f135c8f45719..af1f216c680a 100644
--- a/polly/lib/External/isl/isl_constraint.c
+++ b/polly/lib/External/isl/isl_constraint.c
@@ -22,8 +22,8 @@
 #include <bset_to_bmap.c>
 #include <bset_from_bmap.c>
 
-#undef BASE
-#define BASE constraint
+#undef EL_BASE
+#define EL_BASE constraint
 
 #include <isl_list_templ.c>
 
@@ -32,7 +32,7 @@ isl_ctx *isl_constraint_get_ctx(__isl_keep isl_constraint *c)
 	return c ? isl_local_space_get_ctx(c->ls) : NULL;
 }
 
-static unsigned n(struct isl_constraint *c, enum isl_dim_type type)
+static isl_size n(struct isl_constraint *c, enum isl_dim_type type)
 {
 	return isl_local_space_dim(c->ls, type);
 }
@@ -42,26 +42,6 @@ static unsigned offset(struct isl_constraint *c, enum isl_dim_type type)
 	return isl_local_space_offset(c->ls, type);
 }
 
-static unsigned basic_map_offset(__isl_keep isl_basic_map *bmap,
-							enum isl_dim_type type)
-{
-	return type == isl_dim_div ? 1 + isl_space_dim(bmap->dim, isl_dim_all)
-				   : 1 + isl_space_offset(bmap->dim, type);
-}
-
-static unsigned basic_set_offset(struct isl_basic_set *bset,
-							enum isl_dim_type type)
-{
-	isl_space *dim = bset->dim;
-	switch (type) {
-	case isl_dim_param:	return 1;
-	case isl_dim_in:	return 1 + dim->nparam;
-	case isl_dim_out:	return 1 + dim->nparam + dim->n_in;
-	case isl_dim_div:	return 1 + dim->nparam + dim->n_in + dim->n_out;
-	default:		return 0;
-	}
-}
-
 __isl_give isl_constraint *isl_constraint_alloc_vec(int eq,
 	__isl_take isl_local_space *ls, __isl_take isl_vec *v)
 {
@@ -89,14 +69,18 @@ __isl_give isl_constraint *isl_constraint_alloc_vec(int eq,
 __isl_give isl_constraint *isl_constraint_alloc(int eq,
 	__isl_take isl_local_space *ls)
 {
+	isl_size dim;
 	isl_ctx *ctx;
 	isl_vec *v;
 
+	dim = isl_local_space_dim(ls, isl_dim_all);
+	if (dim < 0)
+		ls = isl_local_space_free(ls);
 	if (!ls)
 		return NULL;
 
 	ctx = isl_local_space_get_ctx(ls);
-	v = isl_vec_alloc(ctx, 1 + isl_local_space_dim(ls, isl_dim_all));
+	v = isl_vec_alloc(ctx, 1 + dim);
 	v = isl_vec_clr(v);
 	return isl_constraint_alloc_vec(eq, ls, v);
 }
@@ -105,6 +89,7 @@ struct isl_constraint *isl_basic_map_constraint(struct isl_basic_map *bmap,
 	isl_int **line)
 {
 	int eq;
+	isl_size dim;
 	isl_ctx *ctx;
 	isl_vec *v;
 	isl_local_space *ls = NULL;
@@ -117,7 +102,10 @@ struct isl_constraint *isl_basic_map_constraint(struct isl_basic_map *bmap,
 
 	ctx = isl_basic_map_get_ctx(bmap);
 	ls = isl_basic_map_get_local_space(bmap);
-	v = isl_vec_alloc(ctx, 1 + isl_local_space_dim(ls, isl_dim_all));
+	dim = isl_local_space_dim(ls, isl_dim_all);
+	if (dim < 0)
+		goto error;
+	v = isl_vec_alloc(ctx, 1 + dim);
 	if (!v)
 		goto error;
 	isl_seq_cpy(v->el, line[0], v->size);
@@ -197,10 +185,10 @@ __isl_null isl_constraint *isl_constraint_free(__isl_take isl_constraint *c)
  * number of times isl_basic_map_foreach_constraint will
  * call the callback.
  */
-int isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap)
+isl_size isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap)
 {
 	if (!bmap)
-		return -1;
+		return isl_size_error;
 
 	return bmap->n_eq + bmap->n_ineq;
 }
@@ -209,7 +197,7 @@ int isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap)
  * number of times isl_basic_set_foreach_constraint will
  * call the callback.
  */
-int isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset)
+isl_size isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset)
 {
 	return isl_basic_map_n_constraint(bset);
 }
@@ -260,13 +248,15 @@ static isl_stat collect_constraint(__isl_take isl_constraint *constraint,
 	void *user)
 {
 	isl_constraint_list **list = user;
+	isl_bool is_div;
 
-	if (isl_constraint_is_div_constraint(constraint))
+	is_div = isl_constraint_is_div_constraint(constraint);
+	if (is_div < 0 || is_div)
 		isl_constraint_free(constraint);
 	else
 		*list = isl_constraint_list_add(*list, constraint);
 
-	return isl_stat_ok;
+	return is_div < 0 ? isl_stat_error : isl_stat_ok;
 }
 
 /* Return a list of constraints that, when combined, are equivalent
@@ -278,8 +268,8 @@ static isl_stat collect_constraint(__isl_take isl_constraint *constraint,
 __isl_give isl_constraint_list *isl_basic_map_get_constraint_list(
 	__isl_keep isl_basic_map *bmap)
 {
-	int n;
-	int known;
+	isl_size n;
+	isl_bool known;
 	isl_ctx *ctx;
 	isl_constraint_list *list;
 
@@ -292,6 +282,8 @@ __isl_give isl_constraint_list *isl_basic_map_get_constraint_list(
 			"input involves unknown divs", return NULL);
 
 	n = isl_basic_map_n_constraint(bmap);
+	if (n < 0)
+		return NULL;
 	list = isl_constraint_list_alloc(ctx, n);
 	if (isl_basic_map_foreach_constraint(bmap,
 					    &collect_constraint, &list) < 0)
@@ -328,16 +320,16 @@ struct isl_basic_map *isl_basic_map_add_constraint(
 	struct isl_basic_map *bmap, struct isl_constraint *constraint)
 {
 	isl_ctx *ctx;
-	isl_space *dim;
+	isl_space *space;
 	int equal_space;
 
 	if (!bmap || !constraint)
 		goto error;
 
 	ctx = isl_constraint_get_ctx(constraint);
-	dim = isl_constraint_get_space(constraint);
-	equal_space = isl_space_is_equal(bmap->dim, dim);
-	isl_space_free(dim);
+	space = isl_constraint_get_space(constraint);
+	equal_space = isl_space_is_equal(bmap->dim, space);
+	isl_space_free(space);
 	isl_assert(ctx, equal_space, goto error);
 
 	bmap = isl_basic_map_intersect(bmap,
@@ -373,6 +365,14 @@ __isl_give isl_set *isl_set_add_constraint(__isl_take isl_set *set,
 	return isl_map_add_constraint(set, constraint);
 }
 
+/* Return the space of "constraint".
+ */
+static __isl_keep isl_space *isl_constraint_peek_space(
+	__isl_keep isl_constraint *constraint)
+{
+	return constraint ? isl_local_space_peek_space(constraint->ls) : NULL;
+}
+
 __isl_give isl_space *isl_constraint_get_space(
 	__isl_keep isl_constraint *constraint)
 {
@@ -385,19 +385,23 @@ __isl_give isl_local_space *isl_constraint_get_local_space(
 	return constraint ? isl_local_space_copy(constraint->ls) : NULL;
 }
 
-int isl_constraint_dim(struct isl_constraint *constraint,
+isl_size isl_constraint_dim(__isl_keep isl_constraint *constraint,
 	enum isl_dim_type type)
 {
 	if (!constraint)
-		return -1;
+		return isl_size_error;
 	return n(constraint, type);
 }
 
+#undef TYPE
+#define TYPE	isl_constraint
+static
+#include "check_type_range_templ.c"
+
 isl_bool isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
 	int i;
-	isl_ctx *ctx;
 	int *active = NULL;
 	isl_bool involves = isl_bool_false;
 
@@ -406,10 +410,8 @@ isl_bool isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
 	if (n == 0)
 		return isl_bool_false;
 
-	ctx = isl_constraint_get_ctx(constraint);
-	if (first + n > isl_constraint_dim(constraint, type))
-		isl_die(ctx, isl_error_invalid,
-			"range out of bounds", return isl_bool_error);
+	if (isl_constraint_check_range(constraint, type, first, n) < 0)
+		return isl_bool_error;
 
 	active = isl_local_space_get_active(constraint->ls,
 					    constraint->v->el + 1);
@@ -437,15 +439,11 @@ isl_bool isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
 isl_bool isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint,
 	enum isl_dim_type type, unsigned pos)
 {
-	if (!constraint)
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
 		return isl_bool_error;
 
-	if (pos >= isl_local_space_dim(constraint->ls, type))
-		isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
-			"position out of bounds", return isl_bool_error);
-
 	pos += isl_local_space_offset(constraint->ls, type);
-	return isl_int_is_pos(constraint->v->el[pos]);
+	return isl_bool_ok(isl_int_is_pos(constraint->v->el[pos]));
 }
 
 /* Does the given constraint represent an upper bound on the given
@@ -454,15 +452,11 @@ isl_bool isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint,
 isl_bool isl_constraint_is_upper_bound(__isl_keep isl_constraint *constraint,
 	enum isl_dim_type type, unsigned pos)
 {
-	if (!constraint)
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
 		return isl_bool_error;
 
-	if (pos >= isl_local_space_dim(constraint->ls, type))
-		isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
-			"position out of bounds", return isl_bool_error);
-
 	pos += isl_local_space_offset(constraint->ls, type);
-	return isl_int_is_neg(constraint->v->el[pos]);
+	return isl_bool_ok(isl_int_is_neg(constraint->v->el[pos]));
 }
 
 const char *isl_constraint_get_dim_name(__isl_keep isl_constraint *constraint,
@@ -497,13 +491,9 @@ __isl_give isl_val *isl_constraint_get_constant_val(
 void isl_constraint_get_coefficient(struct isl_constraint *constraint,
 	enum isl_dim_type type, int pos, isl_int *v)
 {
-	if (!constraint)
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
 		return;
 
-	if (pos >= isl_local_space_dim(constraint->ls, type))
-		isl_die(constraint->v->ctx, isl_error_invalid,
-			"position out of bounds", return);
-
 	pos += isl_local_space_offset(constraint->ls, type);
 	isl_int_set(*v, constraint->v->el[pos]);
 }
@@ -516,14 +506,10 @@ __isl_give isl_val *isl_constraint_get_coefficient_val(
 {
 	isl_ctx *ctx;
 
-	if (!constraint)
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
 		return NULL;
 
 	ctx = isl_constraint_get_ctx(constraint);
-	if (pos < 0 || pos >= isl_local_space_dim(constraint->ls, type))
-		isl_die(ctx, isl_error_invalid,
-			"position out of bounds", return NULL);
-
 	pos += isl_local_space_offset(constraint->ls, type);
 	return isl_val_int_from_isl_int(ctx, constraint->v->el[pos]);
 }
@@ -592,17 +578,8 @@ __isl_give isl_constraint *isl_constraint_set_coefficient(
 	enum isl_dim_type type, int pos, isl_int v)
 {
 	constraint = isl_constraint_cow(constraint);
-	if (!constraint)
-		return NULL;
-
-	if (pos >= isl_local_space_dim(constraint->ls, type))
-		isl_die(constraint->v->ctx, isl_error_invalid,
-			"position out of bounds",
-			return isl_constraint_free(constraint));
-
-	constraint = isl_constraint_cow(constraint);
-	if (!constraint)
-		return NULL;
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
+		return isl_constraint_free(constraint);
 
 	constraint->v = isl_vec_cow(constraint->v);
 	if (!constraint->v)
@@ -627,10 +604,8 @@ __isl_give isl_constraint *isl_constraint_set_coefficient_val(
 	if (!isl_val_is_int(v))
 		isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
 			"expecting integer value", goto error);
-
-	if (pos >= isl_local_space_dim(constraint->ls, type))
-		isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
-			"position out of bounds", goto error);
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
+		goto error;
 
 	pos += isl_local_space_offset(constraint->ls, type);
 	constraint->v = isl_vec_set_element_val(constraint->v, pos, v);
@@ -647,17 +622,8 @@ __isl_give isl_constraint *isl_constraint_set_coefficient_si(
 	enum isl_dim_type type, int pos, int v)
 {
 	constraint = isl_constraint_cow(constraint);
-	if (!constraint)
-		return NULL;
-
-	if (pos >= isl_local_space_dim(constraint->ls, type))
-		isl_die(constraint->v->ctx, isl_error_invalid,
-			"position out of bounds",
-			return isl_constraint_free(constraint));
-
-	constraint = isl_constraint_cow(constraint);
-	if (!constraint)
-		return NULL;
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
+		return isl_constraint_free(constraint);
 
 	constraint->v = isl_vec_cow(constraint->v);
 	if (!constraint->v)
@@ -693,19 +659,21 @@ isl_bool isl_constraint_is_equality(struct isl_constraint *constraint)
 {
 	if (!constraint)
 		return isl_bool_error;
-	return constraint->eq;
+	return isl_bool_ok(constraint->eq);
 }
 
-int isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint)
+isl_bool isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint)
 {
 	int i;
-	int n_div;
+	isl_size n_div;
 
 	if (!constraint)
-		return -1;
+		return isl_bool_error;
 	if (isl_constraint_is_equality(constraint))
-		return 0;
+		return isl_bool_false;
 	n_div = isl_constraint_dim(constraint, isl_dim_div);
+	if (n_div < 0)
+		return isl_bool_error;
 	for (i = 0; i < n_div; ++i) {
 		isl_bool is_div;
 		is_div = isl_local_space_is_div_constraint(constraint->ls,
@@ -714,7 +682,7 @@ int isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint)
 			return is_div;
 	}
 
-	return 0;
+	return isl_bool_false;
 }
 
 /* Is "constraint" an equality that corresponds to integer division "div"?
@@ -755,7 +723,7 @@ __isl_give isl_basic_map *isl_basic_map_from_constraint(
 	isl_local_space *ls;
 	struct isl_basic_map *bmap;
 	isl_int *c;
-	unsigned total;
+	isl_size total;
 
 	if (!constraint)
 		return NULL;
@@ -775,7 +743,9 @@ __isl_give isl_basic_map *isl_basic_map_from_constraint(
 			goto error;
 		c = bmap->ineq[k];
 	}
-	total = isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		goto error;
 	isl_seq_cpy(c, constraint->v->el, 1 + total);
 	isl_constraint_free(constraint);
 	if (bmap)
@@ -790,12 +760,11 @@ __isl_give isl_basic_map *isl_basic_map_from_constraint(
 __isl_give isl_basic_set *isl_basic_set_from_constraint(
 	__isl_take isl_constraint *constraint)
 {
-	if (!constraint)
-		return NULL;
+	isl_space *space;
 
-	if (isl_constraint_dim(constraint, isl_dim_in) != 0)
-		isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
-			"not a set constraint", goto error);
+	space = isl_constraint_peek_space(constraint);
+	if (isl_space_check_is_set(space) < 0)
+		goto error;
 	return bset_from_bmap(isl_basic_map_from_constraint(constraint));
 error:
 	isl_constraint_free(constraint);
@@ -813,15 +782,14 @@ isl_bool isl_basic_map_has_defining_equality(
 {
 	int i;
 	unsigned offset;
-	unsigned total;
+	isl_size total;
 
-	if (!bmap)
+	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
+		return isl_bool_error;
+	offset = isl_basic_map_offset(bmap, type);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return isl_bool_error;
-	offset = basic_map_offset(bmap, type);
-	total = isl_basic_map_total_dim(bmap);
-	if (pos >= isl_basic_map_dim(bmap, type))
-		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
-			"invalid position", return isl_bool_error);
 	for (i = 0; i < bmap->n_eq; ++i) {
 		if (isl_int_is_zero(bmap->eq[i][offset + pos]) ||
 		    isl_seq_first_non_zero(bmap->eq[i]+offset+pos+1,
@@ -855,17 +823,16 @@ isl_bool isl_basic_set_has_defining_inequalities(
 {
 	int i, j;
 	unsigned offset;
-	unsigned total;
+	isl_size total;
 	isl_int m;
 	isl_int **lower_line, **upper_line;
 
-	if (!bset)
+	if (isl_basic_set_check_range(bset, type, pos, 1) < 0)
+		return isl_bool_error;
+	offset = isl_basic_set_offset(bset, type);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		return isl_bool_error;
-	offset = basic_set_offset(bset, type);
-	total = isl_basic_set_total_dim(bset);
-	if (pos >= isl_basic_set_dim(bset, type))
-		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
-			"invalid position", return isl_bool_error);
 	isl_int_init(m);
 	for (i = 0; i < bset->n_ineq; ++i) {
 		if (isl_int_is_zero(bset->ineq[i][offset + pos]))
@@ -921,14 +888,15 @@ static __isl_give isl_basic_set *add_larger_bound_constraint(
 {
 	int k;
 	isl_int t;
-	unsigned total;
+	isl_size total;
 
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
+		return isl_basic_set_free(bset);
 	k = isl_basic_set_alloc_inequality(bset);
 	if (k < 0)
 		goto error;
 
-	total = isl_basic_set_dim(bset, isl_dim_all);
-
 	isl_int_init(t);
 	isl_int_neg(t, b[1 + abs_pos]);
 
@@ -1190,17 +1158,17 @@ isl_stat isl_basic_set_foreach_bound_pair(__isl_keep isl_basic_set *bset,
 	isl_basic_set *context = NULL;
 	unsigned abs_pos;
 	int n_lower, n_upper;
+	isl_size off;
 
-	if (!bset)
+	if (isl_basic_set_check_range(bset, type, pos, 1) < 0)
 		return isl_stat_error;
-	isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type),
-		return isl_stat_error);
 	isl_assert(bset->ctx, type == isl_dim_param || type == isl_dim_set,
 		return isl_stat_error);
 
-	abs_pos = pos;
-	if (type == isl_dim_set)
-		abs_pos += isl_basic_set_dim(bset, isl_dim_param);
+	off = isl_basic_set_var_offset(bset, type);
+	if (off < 0)
+		return isl_stat_error;
+	abs_pos = off + pos;
 
 	for (i = 0; i < bset->n_eq; ++i) {
 		if (isl_int_is_zero(bset->eq[i][1 + abs_pos]))
@@ -1254,19 +1222,17 @@ isl_stat isl_basic_set_foreach_bound_pair(__isl_keep isl_basic_set *bset,
 __isl_give isl_aff *isl_constraint_get_bound(
 	__isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos)
 {
+	isl_space *space;
 	isl_aff *aff;
 	isl_ctx *ctx;
 
-	if (!constraint)
+	if (isl_constraint_check_range(constraint, type, pos, 1) < 0)
+		return NULL;
+	space = isl_constraint_peek_space(constraint);
+	if (isl_space_check_is_set(space) < 0)
 		return NULL;
-	ctx = isl_constraint_get_ctx(constraint);
-	if (pos >= isl_constraint_dim(constraint, type))
-		isl_die(ctx, isl_error_invalid,
-			"index out of bounds", return NULL);
-	if (isl_constraint_dim(constraint, isl_dim_in) != 0)
-		isl_die(ctx, isl_error_invalid,
-			"not a set constraint", return NULL);
 
+	ctx = isl_constraint_get_ctx(constraint);
 	pos += offset(constraint, type);
 	if (isl_int_is_zero(constraint->v->el[pos]))
 		isl_die(ctx, isl_error_invalid,

diff  --git a/polly/lib/External/isl/isl_convex_hull.c b/polly/lib/External/isl/isl_convex_hull.c
index 76a844bfa052..7a4106e8b836 100644
--- a/polly/lib/External/isl/isl_convex_hull.c
+++ b/polly/lib/External/isl/isl_convex_hull.c
@@ -113,7 +113,7 @@ __isl_give isl_set *isl_set_remove_redundancies(__isl_take isl_set *set)
  * constraint c and if so, set the constant term such that the
  * resulting constraint is a bounding constraint for the set.
  */
-static int uset_is_bound(__isl_keep isl_set *set, isl_int *c, unsigned len)
+static isl_bool uset_is_bound(__isl_keep isl_set *set, isl_int *c, unsigned len)
 {
 	int first;
 	int j;
@@ -150,38 +150,11 @@ static int uset_is_bound(__isl_keep isl_set *set, isl_int *c, unsigned len)
 	}
 	isl_int_clear(opt);
 	isl_int_clear(opt_denom);
-	return j >= set->n;
+	return isl_bool_ok(j >= set->n);
 error:
 	isl_int_clear(opt);
 	isl_int_clear(opt_denom);
-	return -1;
-}
-
-static struct isl_basic_set *isl_basic_set_add_equality(
-	struct isl_basic_set *bset, isl_int *c)
-{
-	int i;
-	unsigned dim;
-
-	if (!bset)
-		return NULL;
-
-	if (ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY))
-		return bset;
-
-	isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
-	isl_assert(bset->ctx, bset->n_div == 0, goto error);
-	dim = isl_basic_set_n_dim(bset);
-	bset = isl_basic_set_cow(bset);
-	bset = isl_basic_set_extend(bset, 0, dim, 0, 1, 0);
-	i = isl_basic_set_alloc_equality(bset);
-	if (i < 0)
-		goto error;
-	isl_seq_cpy(bset->eq[i], c, 1 + dim);
-	return bset;
-error:
-	isl_basic_set_free(bset);
-	return NULL;
+	return isl_bool_error;
 }
 
 static __isl_give isl_set *isl_set_add_basic_set_equality(
@@ -193,7 +166,7 @@ static __isl_give isl_set *isl_set_add_basic_set_equality(
 	if (!set)
 		return NULL;
 	for (i = 0; i < set->n; ++i) {
-		set->p[i] = isl_basic_set_add_equality(set->p[i], c);
+		set->p[i] = isl_basic_set_add_eq(set->p[i], c);
 		if (!set->p[i])
 			goto error;
 	}
@@ -226,12 +199,13 @@ static __isl_give isl_basic_set *wrap_constraints(__isl_keep isl_set *set)
 	unsigned n_eq;
 	unsigned n_ineq;
 	int i, j, k;
-	unsigned dim, lp_dim;
+	isl_size dim, lp_dim;
 
-	if (!set)
+	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0)
 		return NULL;
 
-	dim = 1 + isl_set_n_dim(set);
+	dim += 1;
 	n_eq = 1;
 	n_ineq = set->n;
 	for (i = 0; i < set->n; ++i) {
@@ -242,7 +216,9 @@ static __isl_give isl_basic_set *wrap_constraints(__isl_keep isl_set *set)
 	lp = isl_basic_set_set_rational(lp);
 	if (!lp)
 		return NULL;
-	lp_dim = isl_basic_set_n_dim(lp);
+	lp_dim = isl_basic_set_dim(lp, isl_dim_set);
+	if (lp_dim < 0)
+		return isl_basic_set_free(lp);
 	k = isl_basic_set_alloc_equality(lp);
 	isl_int_set_si(lp->eq[k][0], -1);
 	for (i = 0; i < set->n; ++i) {
@@ -339,15 +315,16 @@ isl_int *isl_set_wrap_facet(__isl_keep isl_set *set,
 	struct isl_vec *obj;
 	enum isl_lp_result res;
 	isl_int num, den;
-	unsigned dim;
+	isl_size dim;
 
-	if (!set)
+	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0)
 		return NULL;
 	ctx = set->ctx;
 	set = isl_set_copy(set);
 	set = isl_set_set_rational(set);
 
-	dim = 1 + isl_set_n_dim(set);
+	dim += 1;
 	T = isl_mat_alloc(ctx, 3, dim);
 	if (!T)
 		goto error;
@@ -414,10 +391,12 @@ static __isl_give isl_mat *initial_facet_constraint(__isl_keep isl_set *set)
 	struct isl_set *slice = NULL;
 	struct isl_basic_set *face = NULL;
 	int i;
-	unsigned dim = isl_set_n_dim(set);
-	int is_bound;
+	isl_size dim = isl_set_dim(set, isl_dim_set);
+	isl_bool is_bound;
 	isl_mat *bounds = NULL;
 
+	if (dim < 0)
+		return NULL;
 	isl_assert(set->ctx, set->n > 0, goto error);
 	bounds = isl_mat_alloc(set->ctx, 1, 1 + dim);
 	if (!bounds)
@@ -506,11 +485,13 @@ static __isl_give isl_basic_set *compute_facet(__isl_keep isl_set *set,
 	struct isl_mat *m, *U, *Q;
 	struct isl_basic_set *facet = NULL;
 	struct isl_ctx *ctx;
-	unsigned dim;
+	isl_size dim;
 
+	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0)
+		return NULL;
 	ctx = set->ctx;
 	set = isl_set_copy(set);
-	dim = isl_set_n_dim(set);
 	m = isl_mat_alloc(set->ctx, 2, 1 + dim);
 	if (!m)
 		goto error;
@@ -562,29 +543,27 @@ static __isl_give isl_basic_set *extend(__isl_take isl_basic_set *hull,
 	int k;
 	struct isl_basic_set *facet = NULL;
 	struct isl_basic_set *hull_facet = NULL;
-	unsigned dim;
+	isl_size dim;
 
-	if (!hull)
-		return NULL;
+	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0 || !hull)
+		return isl_basic_set_free(hull);
 
 	isl_assert(set->ctx, set->n > 0, goto error);
 
-	dim = isl_set_n_dim(set);
-
 	for (i = 0; i < hull->n_ineq; ++i) {
 		facet = compute_facet(set, hull->ineq[i]);
-		facet = isl_basic_set_add_equality(facet, hull->ineq[i]);
+		facet = isl_basic_set_add_eq(facet, hull->ineq[i]);
 		facet = isl_basic_set_gauss(facet, NULL);
 		facet = isl_basic_set_normalize_constraints(facet);
 		hull_facet = isl_basic_set_copy(hull);
-		hull_facet = isl_basic_set_add_equality(hull_facet, hull->ineq[i]);
+		hull_facet = isl_basic_set_add_eq(hull_facet, hull->ineq[i]);
 		hull_facet = isl_basic_set_gauss(hull_facet, NULL);
 		hull_facet = isl_basic_set_normalize_constraints(hull_facet);
 		if (!facet || !hull_facet)
 			goto error;
 		hull = isl_basic_set_cow(hull);
-		hull = isl_basic_set_extend_space(hull,
-			isl_space_copy(hull->dim), 0, 0, facet->n_ineq);
+		hull = isl_basic_set_extend(hull, 0, 0, facet->n_ineq);
 		if (!hull)
 			goto error;
 		for (j = 0; j < facet->n_ineq; ++j) {
@@ -768,12 +747,12 @@ static __isl_give isl_basic_set *convex_hull_pair_elim(
 	int i, j, k;
 	struct isl_basic_set *bset[2];
 	struct isl_basic_set *hull = NULL;
-	unsigned dim;
+	isl_size dim;
 
-	if (!bset1 || !bset2)
+	dim = isl_basic_set_dim(bset1, isl_dim_set);
+	if (dim < 0 || !bset2)
 		goto error;
 
-	dim = isl_basic_set_n_dim(bset1);
 	hull = isl_basic_set_alloc(bset1->ctx, 0, 2 + 3 * dim, 0,
 				1 + dim + bset1->n_eq + bset2->n_eq,
 				2 + bset1->n_ineq + bset2->n_ineq);
@@ -849,10 +828,13 @@ isl_bool isl_basic_set_is_bounded(__isl_keep isl_basic_set *bset)
  */
 isl_bool isl_basic_map_image_is_bounded(__isl_keep isl_basic_map *bmap)
 {
-	unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
-	unsigned n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	isl_size nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	isl_size n_in = isl_basic_map_dim(bmap, isl_dim_in);
 	isl_bool bounded;
 
+	if (nparam < 0 || n_in < 0)
+		return isl_bool_error;
+
 	bmap = isl_basic_map_copy(bmap);
 	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_move_dims(bmap, isl_dim_param, nparam,
@@ -891,12 +873,12 @@ static __isl_give isl_basic_set *induced_lineality_space(
 {
 	int i, k;
 	struct isl_basic_set *lin = NULL;
-	unsigned dim;
+	isl_size dim;
 
-	if (!bset1 || !bset2)
+	dim = isl_basic_set_dim(bset1, isl_dim_all);
+	if (dim < 0 || !bset2)
 		goto error;
 
-	dim = isl_basic_set_total_dim(bset1);
 	lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset1), 0,
 					bset1->n_eq + bset2->n_eq,
 					bset1->n_ineq + bset2->n_ineq);
@@ -967,12 +949,12 @@ static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set);
 static __isl_give isl_basic_set *modulo_lineality(__isl_take isl_set *set,
 	__isl_take isl_basic_set *lin)
 {
-	unsigned total = isl_basic_set_total_dim(lin);
+	isl_size total = isl_basic_set_dim(lin, isl_dim_all);
 	unsigned lin_dim;
 	struct isl_basic_set *hull;
 	struct isl_mat *M, *U, *Q;
 
-	if (!set || !lin)
+	if (!set || total < 0)
 		goto error;
 	lin_dim = total - lin->n_eq;
 	M = isl_mat_sub_alloc6(set->ctx, lin->eq, 0, lin->n_eq, 1, total);
@@ -1016,10 +998,12 @@ static __isl_give isl_basic_set *valid_direction_lp(
 	unsigned d;
 	int n;
 	int i, j, k;
+	isl_size total;
 
-	if (!bset1 || !bset2)
+	total = isl_basic_set_dim(bset1, isl_dim_all);
+	if (total < 0 || !bset2)
 		goto error;
-	d = 1 + isl_basic_set_total_dim(bset1);
+	d = 1 + total;
 	n = 2 +
 	    2 * bset1->n_eq + bset1->n_ineq + 2 * bset2->n_eq + bset2->n_ineq;
 	dim = isl_space_set_alloc(bset1->ctx, 0, n);
@@ -1096,7 +1080,7 @@ static __isl_give isl_vec *valid_direction(
 	struct isl_tab *tab;
 	struct isl_vec *sample = NULL;
 	struct isl_vec *dir;
-	unsigned d;
+	isl_size d;
 	int i;
 	int n;
 
@@ -1110,7 +1094,9 @@ static __isl_give isl_vec *valid_direction(
 	isl_basic_set_free(lp);
 	if (!sample)
 		goto error;
-	d = isl_basic_set_total_dim(bset1);
+	d = isl_basic_set_dim(bset1, isl_dim_all);
+	if (d < 0)
+		goto error;
 	dir = isl_vec_alloc(bset1->ctx, 1 + d);
 	if (!dir)
 		goto error;
@@ -1156,14 +1142,16 @@ static __isl_give isl_basic_set *homogeneous_map(__isl_take isl_basic_set *bset,
 	__isl_take isl_mat *T)
 {
 	int k;
+	isl_size total;
 
-	if (!bset)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		goto error;
 	bset = isl_basic_set_extend_constraints(bset, 0, 1);
 	k = isl_basic_set_alloc_inequality(bset);
 	if (k < 0)
 		goto error;
-	isl_seq_clr(bset->ineq[k] + 1, isl_basic_set_total_dim(bset));
+	isl_seq_clr(bset->ineq[k] + 1, total);
 	isl_int_set_si(bset->ineq[k][0], 1);
 	bset = isl_basic_set_preimage(bset, T);
 	return bset;
@@ -1295,7 +1283,8 @@ static __isl_give isl_basic_set *convex_hull_pair(
 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
 {
 	isl_basic_set *lin, *aff;
-	int bounded1, bounded2;
+	isl_bool bounded1, bounded2;
+	isl_size total;
 
 	if (bset1->ctx->opt->convex == ISL_CONVEX_HULL_FM)
 		return convex_hull_pair_elim(bset1, bset2);
@@ -1329,7 +1318,8 @@ static __isl_give isl_basic_set *convex_hull_pair(
 		isl_basic_set_free(bset2);
 		return lin;
 	}
-	if (lin->n_eq < isl_basic_set_total_dim(lin)) {
+	total = isl_basic_set_dim(lin, isl_dim_all);
+	if (lin->n_eq < total) {
 		struct isl_set *set;
 		set = isl_set_alloc_space(isl_basic_set_get_space(bset1), 2, 0);
 		set = isl_set_add_basic_set(set, bset1);
@@ -1337,6 +1327,8 @@ static __isl_give isl_basic_set *convex_hull_pair(
 		return modulo_lineality(set, lin);
 	}
 	isl_basic_set_free(lin);
+	if (total < 0)
+		goto error;
 
 	return convex_hull_pair_pointed(bset1, bset2);
 error:
@@ -1357,12 +1349,12 @@ __isl_give isl_basic_set *isl_basic_set_lineality_space(
 {
 	int i, k;
 	struct isl_basic_set *lin = NULL;
-	unsigned n_div, dim;
+	isl_size n_div, dim;
 
-	if (!bset)
-		goto error;
 	n_div = isl_basic_set_dim(bset, isl_dim_div);
-	dim = isl_basic_set_total_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (n_div < 0 || dim < 0)
+		return isl_basic_set_free(bset);
 
 	lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset),
 					n_div, dim, 0);
@@ -1441,11 +1433,13 @@ static __isl_give isl_basic_set *uset_convex_hull_unbounded(
 	isl_set_free(set);
 
 	while (list) {
-		int n;
+		isl_size n, total;
 		struct isl_basic_set *t;
 		isl_basic_set *bset1, *bset2;
 
 		n = isl_basic_set_list_n_basic_set(list);
+		if (n < 0)
+			goto error;
 		if (n < 2)
 			isl_die(isl_basic_set_list_get_ctx(list),
 				isl_error_internal,
@@ -1469,11 +1463,14 @@ static __isl_give isl_basic_set *uset_convex_hull_unbounded(
 			isl_basic_set_list_free(list);
 			return t;
 		}
-		if (t->n_eq < isl_basic_set_total_dim(t)) {
+		total = isl_basic_set_dim(t, isl_dim_all);
+		if (t->n_eq < total) {
 			set = isl_basic_set_list_union(list);
 			return modulo_lineality(set, t);
 		}
 		isl_basic_set_free(t);
+		if (total < 0)
+			goto error;
 	}
 
 	return NULL;
@@ -1490,7 +1487,7 @@ static __isl_give isl_basic_set *initial_hull(__isl_take isl_basic_set *hull,
 	__isl_keep isl_set *set)
 {
 	struct isl_mat *bounds = NULL;
-	unsigned dim;
+	isl_size dim;
 	int k;
 
 	if (!hull)
@@ -1501,7 +1498,9 @@ static __isl_give isl_basic_set *initial_hull(__isl_take isl_basic_set *hull,
 	k = isl_basic_set_alloc_inequality(hull);
 	if (k < 0)
 		goto error;
-	dim = isl_set_n_dim(set);
+	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0)
+		goto error;
 	isl_assert(set->ctx, 1 + dim == bounds->n_col, goto error);
 	isl_seq_cpy(hull->ineq[k], bounds->row[0], bounds->n_col);
 	isl_mat_free(bounds);
@@ -1519,15 +1518,16 @@ struct max_constraint {
 	int		ineq;
 };
 
-static int max_constraint_equal(const void *entry, const void *val)
+static isl_bool max_constraint_equal(const void *entry, const void *val)
 {
 	struct max_constraint *a = (struct max_constraint *)entry;
 	isl_int *b = (isl_int *)val;
 
-	return isl_seq_eq(a->c->row[0] + 1, b, a->c->n_col - 1);
+	return isl_bool_ok(isl_seq_eq(a->c->row[0] + 1, b, a->c->n_col - 1));
 }
 
-static void update_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
+static isl_stat update_constraint(struct isl_ctx *ctx,
+	struct isl_hash_table *table,
 	isl_int *con, unsigned len, int n, int ineq)
 {
 	struct isl_hash_table_entry *entry;
@@ -1538,30 +1538,34 @@ static void update_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
 	entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
 			con + 1, 0);
 	if (!entry)
-		return;
+		return isl_stat_error;
+	if (entry == isl_hash_table_entry_none)
+		return isl_stat_ok;
 	c = entry->data;
 	if (c->count < n) {
 		isl_hash_table_remove(ctx, table, entry);
-		return;
+		return isl_stat_ok;
 	}
 	c->count++;
 	if (isl_int_gt(c->c->row[0][0], con[0]))
-		return;
+		return isl_stat_ok;
 	if (isl_int_eq(c->c->row[0][0], con[0])) {
 		if (ineq)
 			c->ineq = ineq;
-		return;
+		return isl_stat_ok;
 	}
 	c->c = isl_mat_cow(c->c);
 	isl_int_set(c->c->row[0][0], con[0]);
 	c->ineq = ineq;
+
+	return isl_stat_ok;
 }
 
 /* Check whether the constraint hash table "table" contains the constraint
  * "con".
  */
-static int has_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
-	isl_int *con, unsigned len, int n)
+static isl_bool has_constraint(struct isl_ctx *ctx,
+	struct isl_hash_table *table, isl_int *con, unsigned len, int n)
 {
 	struct isl_hash_table_entry *entry;
 	struct max_constraint *c;
@@ -1571,14 +1575,34 @@ static int has_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
 	entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
 			con + 1, 0);
 	if (!entry)
-		return 0;
+		return isl_bool_error;
+	if (entry == isl_hash_table_entry_none)
+		return isl_bool_false;
 	c = entry->data;
 	if (c->count < n)
-		return 0;
-	return isl_int_eq(c->c->row[0][0], con[0]);
+		return isl_bool_false;
+	return isl_bool_ok(isl_int_eq(c->c->row[0][0], con[0]));
+}
+
+/* Are the constraints of "bset" known to be facets?
+ * If there are any equality constraints, then they are not.
+ * If there may be redundant constraints, then those
+ * redundant constraints are not facets.
+ */
+static isl_bool has_facets(__isl_keep isl_basic_set *bset)
+{
+	int n_eq;
+
+	n_eq = isl_basic_set_n_equality(bset);
+	if (n_eq < 0)
+		return isl_bool_error;
+	if (n_eq != 0)
+		return isl_bool_false;
+	return ISL_F_ISSET(bset, ISL_BASIC_SET_NO_REDUNDANT);
 }
 
 /* Check for inequality constraints of a basic set without equalities
+ * or redundant constraints
  * such that the same or more stringent copies of the constraint appear
  * in all of the basic sets.  Such constraints are necessarily facet
  * constraints of the convex hull.
@@ -1596,19 +1620,26 @@ static __isl_give isl_basic_set *common_constraints(
 	int best;
 	struct max_constraint *constraints = NULL;
 	struct isl_hash_table *table = NULL;
-	unsigned total;
+	isl_size total;
 
 	*is_hull = 0;
 
-	for (i = 0; i < set->n; ++i)
-		if (set->p[i]->n_eq == 0)
+	for (i = 0; i < set->n; ++i) {
+		isl_bool facets = has_facets(set->p[i]);
+		if (facets < 0)
+			return isl_basic_set_free(hull);
+		if (facets)
 			break;
+	}
 	if (i >= set->n)
 		return hull;
 	min_constraints = set->p[i]->n_ineq;
 	best = i;
 	for (i = best + 1; i < set->n; ++i) {
-		if (set->p[i]->n_eq != 0)
+		isl_bool facets = has_facets(set->p[i]);
+		if (facets < 0)
+			return isl_basic_set_free(hull);
+		if (!facets)
 			continue;
 		if (set->p[i]->n_ineq >= min_constraints)
 			continue;
@@ -1623,7 +1654,9 @@ static __isl_give isl_basic_set *common_constraints(
 	if (isl_hash_table_init(hull->ctx, table, min_constraints))
 		goto error;
 
-	total = isl_space_dim(set->dim, isl_dim_all);
+	total = isl_set_dim(set, isl_dim_all);
+	if (total < 0)
+		goto error;
 	for (i = 0; i < set->p[best]->n_ineq; ++i) {
 		constraints[i].c = isl_mat_sub_alloc6(hull->ctx,
 			set->p[best]->ineq + i, 0, 1, 0, 1 + total);
@@ -1652,14 +1685,16 @@ static __isl_give isl_basic_set *common_constraints(
 			isl_int *eq = set->p[s]->eq[i];
 			for (j = 0; j < 2; ++j) {
 				isl_seq_neg(eq, eq, 1 + total);
-				update_constraint(hull->ctx, table,
-							    eq, total, n, 0);
+				if (update_constraint(hull->ctx, table,
+						    eq, total, n, 0) < 0)
+					goto error;
 			}
 		}
 		for (i = 0; i < set->p[s]->n_ineq; ++i) {
 			isl_int *ineq = set->p[s]->ineq[i];
-			update_constraint(hull->ctx, table, ineq, total, n,
-				set->p[s]->n_eq == 0);
+			if (update_constraint(hull->ctx, table, ineq, total, n,
+					set->p[s]->n_eq == 0) < 0)
+				goto error;
 		}
 		++n;
 	}
@@ -1681,8 +1716,12 @@ static __isl_give isl_basic_set *common_constraints(
 		if (set->p[s]->n_ineq != hull->n_ineq)
 			continue;
 		for (i = 0; i < set->p[s]->n_ineq; ++i) {
+			isl_bool has;
 			isl_int *ineq = set->p[s]->ineq[i];
-			if (!has_constraint(hull->ctx, table, ineq, total, n))
+			has = has_constraint(hull->ctx, table, ineq, total, n);
+			if (has < 0)
+				goto error;
+			if (!has)
 				break;
 		}
 		if (i == set->p[s]->n_ineq)
@@ -1753,10 +1792,14 @@ static __isl_give isl_basic_set *uset_convex_hull_wrap(__isl_take isl_set *set)
 static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set)
 {
 	isl_bool bounded;
+	isl_size dim;
 	struct isl_basic_set *convex_hull = NULL;
 	struct isl_basic_set *lin;
 
-	if (isl_set_n_dim(set) == 0)
+	dim = isl_set_dim(set, isl_dim_all);
+	if (dim < 0)
+		goto error;
+	if (dim == 0)
 		return convex_hull_0d(set);
 
 	set = isl_set_coalesce(set);
@@ -1769,7 +1812,7 @@ static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set)
 		isl_set_free(set);
 		return convex_hull;
 	}
-	if (isl_set_n_dim(set) == 1)
+	if (dim == 1)
 		return convex_hull_1d(set);
 
 	bounded = isl_set_is_bounded(set);
@@ -1785,7 +1828,7 @@ static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set)
 		isl_set_free(set);
 		return lin;
 	}
-	if (lin->n_eq < isl_basic_set_total_dim(lin))
+	if (lin->n_eq < dim)
 		return modulo_lineality(set, lin);
 	isl_basic_set_free(lin);
 
@@ -1804,11 +1847,13 @@ static __isl_give isl_basic_set *uset_convex_hull_wrap_bounded(
 	__isl_take isl_set *set)
 {
 	struct isl_basic_set *convex_hull = NULL;
+	isl_size dim;
 
-	if (!set)
+	dim = isl_set_dim(set, isl_dim_all);
+	if (dim < 0)
 		goto error;
 
-	if (isl_set_n_dim(set) == 0) {
+	if (dim == 0) {
 		convex_hull = isl_basic_set_universe(isl_space_copy(set->dim));
 		isl_set_free(set);
 		convex_hull = isl_basic_set_set_rational(convex_hull);
@@ -1825,7 +1870,7 @@ static __isl_give isl_basic_set *uset_convex_hull_wrap_bounded(
 		convex_hull = isl_basic_map_remove_redundancies(convex_hull);
 		return convex_hull;
 	}
-	if (isl_set_n_dim(set) == 1)
+	if (dim == 1)
 		return convex_hull_1d(set);
 
 	return uset_convex_hull_wrap(set);
@@ -1985,13 +2030,13 @@ struct ineq_cmp_data {
 	isl_int		*p;
 };
 
-static int has_ineq(const void *entry, const void *val)
+static isl_bool has_ineq(const void *entry, const void *val)
 {
 	isl_int *row = (isl_int *)entry;
 	struct ineq_cmp_data *v = (struct ineq_cmp_data *)val;
 
-	return isl_seq_eq(row + 1, v->p + 1, v->len) ||
-	       isl_seq_is_neg(row + 1, v->p + 1, v->len);
+	return isl_bool_ok(isl_seq_eq(row + 1, v->p + 1, v->len) ||
+			   isl_seq_is_neg(row + 1, v->p + 1, v->len));
 }
 
 static int hash_ineq(struct isl_ctx *ctx, struct isl_hash_table *table,
@@ -2015,24 +2060,26 @@ static int hash_ineq(struct isl_ctx *ctx, struct isl_hash_table *table,
  * Equalities are added as two inequalities.
  * The value in the hash table is a pointer to the (in)equality of "bset".
  */
-static int hash_basic_set(struct isl_hash_table *table,
+static isl_stat hash_basic_set(struct isl_hash_table *table,
 	__isl_keep isl_basic_set *bset)
 {
 	int i, j;
-	unsigned dim = isl_basic_set_total_dim(bset);
+	isl_size dim = isl_basic_set_dim(bset, isl_dim_all);
 
+	if (dim < 0)
+		return isl_stat_error;
 	for (i = 0; i < bset->n_eq; ++i) {
 		for (j = 0; j < 2; ++j) {
 			isl_seq_neg(bset->eq[i], bset->eq[i], 1 + dim);
 			if (hash_ineq(bset->ctx, table, bset->eq[i], dim) < 0)
-				return -1;
+				return isl_stat_error;
 		}
 	}
 	for (i = 0; i < bset->n_ineq; ++i) {
 		if (hash_ineq(bset->ctx, table, bset->ineq[i], dim) < 0)
-			return -1;
+			return isl_stat_error;
 	}
-	return 0;
+	return isl_stat_ok;
 }
 
 static struct sh_data *sh_data_alloc(__isl_keep isl_set *set, unsigned n_ineq)
@@ -2116,7 +2163,8 @@ static int is_bound(struct sh_data *data, __isl_keep isl_set *set, int j,
  * least its constant term) may need to be temporarily negated to get
  * the actually hashed constraint.
  */
-static void set_max_constant_term(struct sh_data *data, __isl_keep isl_set *set,
+static isl_stat set_max_constant_term(struct sh_data *data,
+	__isl_keep isl_set *set,
 	int i, isl_int *ineq, uint32_t c_hash, struct ineq_cmp_data *v)
 {
 	int j;
@@ -2131,6 +2179,8 @@ static void set_max_constant_term(struct sh_data *data, __isl_keep isl_set *set,
 		entry = isl_hash_table_find(ctx, data->p[j].table,
 						c_hash, &has_ineq, v, 0);
 		if (!entry)
+			return isl_stat_error;
+		if (entry == isl_hash_table_entry_none)
 			continue;
 
 		ineq_j = entry->data;
@@ -2142,6 +2192,8 @@ static void set_max_constant_term(struct sh_data *data, __isl_keep isl_set *set,
 		if (neg)
 			isl_int_neg(ineq_j[0], ineq_j[0]);
 	}
+
+	return isl_stat_ok;
 }
 
 /* Check if inequality "ineq" from basic set "i" is or can be relaxed to
@@ -2173,23 +2225,29 @@ static __isl_give isl_basic_set *add_bound(__isl_take isl_basic_set *hull,
 	struct ineq_cmp_data v;
 	struct isl_hash_table_entry *entry;
 	int j, k;
+	isl_size total;
 
-	if (!hull)
-		return NULL;
+	total = isl_basic_set_dim(hull, isl_dim_all);
+	if (total < 0)
+		return isl_basic_set_free(hull);
 
-	v.len = isl_basic_set_total_dim(hull);
+	v.len = total;
 	v.p = ineq;
 	c_hash = isl_seq_get_hash(ineq + 1, v.len);
 
 	entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
 					has_ineq, &v, 0);
-	if (entry)
+	if (!entry)
+		return isl_basic_set_free(hull);
+	if (entry != isl_hash_table_entry_none)
 		return hull;
 
 	for (j = 0; j < i; ++j) {
 		entry = isl_hash_table_find(hull->ctx, data->p[j].table,
 						c_hash, has_ineq, &v, 0);
-		if (entry)
+		if (!entry)
+			return isl_basic_set_free(hull);
+		if (entry != isl_hash_table_entry_none)
 			break;
 	}
 	if (j < i)
@@ -2200,7 +2258,8 @@ static __isl_give isl_basic_set *add_bound(__isl_take isl_basic_set *hull,
 		goto error;
 	isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
 
-	set_max_constant_term(data, set, i, hull->ineq[k], c_hash, &v);
+	if (set_max_constant_term(data, set, i, hull->ineq[k], c_hash, &v) < 0)
+		goto error;
 	for (j = 0; j < i; ++j) {
 		int bound;
 		bound = is_bound(data, set, j, hull->ineq[k], shift);
@@ -2209,16 +2268,16 @@ static __isl_give isl_basic_set *add_bound(__isl_take isl_basic_set *hull,
 		if (!bound)
 			break;
 	}
-	if (j < i) {
-		isl_basic_set_free_inequality(hull, 1);
-		return hull;
-	}
+	if (j < i)
+		return isl_basic_set_free_inequality(hull, 1);
 
 	for (j = i + 1; j < set->n; ++j) {
 		int bound;
 		entry = isl_hash_table_find(hull->ctx, data->p[j].table,
 						c_hash, has_ineq, &v, 0);
-		if (entry)
+		if (!entry)
+			return isl_basic_set_free(hull);
+		if (entry != isl_hash_table_entry_none)
 			continue;
 		bound = is_bound(data, set, j, hull->ineq[k], shift);
 		if (bound < 0)
@@ -2226,10 +2285,8 @@ static __isl_give isl_basic_set *add_bound(__isl_take isl_basic_set *hull,
 		if (!bound)
 			break;
 	}
-	if (j < set->n) {
-		isl_basic_set_free_inequality(hull, 1);
-		return hull;
-	}
+	if (j < set->n)
+		return isl_basic_set_free_inequality(hull, 1);
 
 	entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
 					has_ineq, &v, 1);
@@ -2251,7 +2308,10 @@ static __isl_give isl_basic_set *add_bounds(__isl_take isl_basic_set *bset,
 	struct sh_data *data, __isl_keep isl_set *set, int i, int shift)
 {
 	int j, k;
-	unsigned dim = isl_basic_set_total_dim(bset);
+	isl_size dim = isl_basic_set_dim(bset, isl_dim_all);
+
+	if (dim < 0)
+		return isl_basic_set_free(bset);
 
 	for (j = 0; j < set->p[i]->n_eq; ++j) {
 		for (k = 0; k < 2; ++k) {
@@ -2502,14 +2562,13 @@ static __isl_give isl_basic_map *select_shared_equalities(
 	__isl_take isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
 {
 	int i1, i2;
-	unsigned total;
+	isl_size total;
 
 	bmap1 = isl_basic_map_cow(bmap1);
-	if (!bmap1 || !bmap2)
+	total = isl_basic_map_dim(bmap1, isl_dim_all);
+	if (total < 0 || !bmap2)
 		return isl_basic_map_free(bmap1);
 
-	total = isl_basic_map_total_dim(bmap1);
-
 	i1 = bmap1->n_eq - 1;
 	i2 = bmap2->n_eq - 1;
 	while (bmap1 && i1 >= 0 && i2 >= 0) {
@@ -2554,6 +2613,9 @@ static __isl_give isl_basic_map *select_shared_equalities(
 __isl_give isl_basic_map *isl_basic_map_plain_unshifted_simple_hull(
 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
 {
+	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
+		goto error;
+
 	bmap1 = isl_basic_map_drop_constraint_involving_unknown_divs(bmap1);
 	bmap2 = isl_basic_map_drop_constraint_involving_unknown_divs(bmap2);
 	bmap2 = isl_basic_map_align_divs(bmap2, bmap1);
@@ -2569,6 +2631,10 @@ __isl_give isl_basic_map *isl_basic_map_plain_unshifted_simple_hull(
 	isl_basic_map_free(bmap2);
 	bmap1 = isl_basic_map_finalize(bmap1);
 	return bmap1;
+error:
+	isl_basic_map_free(bmap1);
+	isl_basic_map_free(bmap2);
+	return NULL;
 }
 
 /* Compute a superset of the convex hull of "map" that is described
@@ -2634,11 +2700,13 @@ static __isl_give isl_basic_set *add_bound_from_constraint(
 	isl_ctx *ctx;
 	uint32_t c_hash;
 	struct ineq_cmp_data v;
+	isl_size total;
 
-	if (!hull || !set)
+	total = isl_basic_set_dim(hull, isl_dim_all);
+	if (total < 0 || !set)
 		return isl_basic_set_free(hull);
 
-	v.len = isl_basic_set_total_dim(hull);
+	v.len = total;
 	v.p = ineq;
 	c_hash = isl_seq_get_hash(ineq + 1, v.len);
 
@@ -2649,7 +2717,9 @@ static __isl_give isl_basic_set *add_bound_from_constraint(
 
 		entry = isl_hash_table_find(ctx, data->p[i].table,
 						c_hash, &has_ineq, &v, 0);
-		if (entry) {
+		if (!entry)
+			return isl_basic_set_free(hull);
+		if (entry != isl_hash_table_entry_none) {
 			isl_int *ineq_i = entry->data;
 			int neg, more_relaxed;
 
@@ -2706,7 +2776,7 @@ static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_constraints(
 	int last_added = 0;
 	struct sh_data *data = NULL;
 	isl_basic_set *hull = NULL;
-	unsigned dim;
+	isl_size dim;
 
 	hull = isl_basic_set_alloc_space(isl_set_get_space(set), 0, 0, n_ineq);
 	if (!hull)
@@ -2717,6 +2787,8 @@ static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_constraints(
 		goto error;
 
 	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0)
+		goto error;
 	for (i = 0; i < n_ineq; ++i) {
 		int hull_n_ineq = hull->n_ineq;
 		int parallel;
@@ -2752,14 +2824,15 @@ static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_constraints(
 static __isl_give isl_mat *collect_inequalities(__isl_take isl_mat *mat,
 	__isl_keep isl_basic_set_list *list, isl_int **ineq)
 {
-	int i, j, n, n_eq, n_ineq;
+	int i, j, n_eq, n_ineq;
+	isl_size n;
 
-	if (!mat)
-		return NULL;
+	n = isl_basic_set_list_n_basic_set(list);
+	if (!mat || n < 0)
+		return isl_mat_free(mat);
 
 	n_eq = 0;
 	n_ineq = 0;
-	n = isl_basic_set_list_n_basic_set(list);
 	for (i = 0; i < n; ++i) {
 		isl_basic_set *bset;
 		bset = isl_basic_set_list_get_basic_set(list, i);
@@ -2809,20 +2882,21 @@ static int cmp_ineq(const void *a, const void *b, void *arg)
 static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_basic_set_list(
 	__isl_take isl_set *set, __isl_take isl_basic_set_list *list)
 {
-	int i, n, n_eq, n_ineq;
-	unsigned dim;
+	int i, n_eq, n_ineq;
+	isl_size n;
+	isl_size dim;
 	isl_ctx *ctx;
 	isl_mat *mat = NULL;
 	isl_int **ineq = NULL;
 	isl_basic_set *hull;
 
-	if (!set)
+	n = isl_basic_set_list_n_basic_set(list);
+	if (!set || n < 0)
 		goto error;
 	ctx = isl_set_get_ctx(set);
 
 	n_eq = 0;
 	n_ineq = 0;
-	n = isl_basic_set_list_n_basic_set(list);
 	for (i = 0; i < n; ++i) {
 		isl_basic_set *bset;
 		bset = isl_basic_set_list_get_basic_set(list, i);
@@ -2838,6 +2912,8 @@ static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_basic_set_list(
 		goto error;
 
 	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0)
+		goto error;
 	mat = isl_mat_alloc(ctx, n_eq, 1 + dim);
 	mat = collect_inequalities(mat, list, ineq);
 	if (!mat)
@@ -2874,15 +2950,17 @@ static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_basic_set_list(
 static __isl_give isl_basic_map *map_unshifted_simple_hull_from_basic_map_list(
 	__isl_take isl_map *map, __isl_take isl_basic_map_list *list)
 {
+	isl_size n;
 	isl_basic_map *model;
 	isl_basic_map *hull;
 	isl_set *set;
 	isl_basic_set_list *bset_list;
 
-	if (!map || !list)
+	n = isl_basic_map_list_n_basic_map(list);
+	if (!map || n < 0)
 		goto error;
 
-	if (isl_basic_map_list_n_basic_map(list) == 0) {
+	if (n == 0) {
 		isl_space *space;
 
 		space = isl_map_get_space(map);
@@ -2920,7 +2998,8 @@ static __isl_give isl_basic_map *map_unshifted_simple_hull_from_basic_map_list(
 static __isl_give isl_basic_map_list *collect_basic_maps(
 	__isl_take isl_map_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_basic_map_list *bmap_list;
 
@@ -2929,6 +3008,8 @@ static __isl_give isl_basic_map_list *collect_basic_maps(
 	n = isl_map_list_n_map(list);
 	ctx = isl_map_list_get_ctx(list);
 	bmap_list = isl_basic_map_list_alloc(ctx, 0);
+	if (n < 0)
+		bmap_list = isl_basic_map_list_free(bmap_list);
 
 	for (i = 0; i < n; ++i) {
 		isl_map *map;
@@ -2983,9 +3064,11 @@ __isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
 
 /* Given a set "set", return parametric bounds on the dimension "dim".
  */
-static struct isl_basic_set *set_bounds(struct isl_set *set, int dim)
+static __isl_give isl_basic_set *set_bounds(__isl_keep isl_set *set, int dim)
 {
-	unsigned set_dim = isl_set_dim(set, isl_dim_set);
+	isl_size set_dim = isl_set_dim(set, isl_dim_set);
+	if (set_dim < 0)
+		return NULL;
 	set = isl_set_copy(set);
 	set = isl_set_eliminate_dims(set, dim + 1, set_dim - (dim + 1));
 	set = isl_set_eliminate_dims(set, 0, dim);
@@ -3000,19 +3083,22 @@ __isl_give isl_basic_set *isl_set_bounded_simple_hull(__isl_take isl_set *set)
 {
 	int i, j;
 	struct isl_basic_set *hull;
-	unsigned nparam, left;
+	isl_size nparam, dim, total;
+	unsigned left;
 	int removed_divs = 0;
 
 	hull = isl_set_simple_hull(isl_set_copy(set));
-	if (!hull)
+	nparam = isl_basic_set_dim(hull, isl_dim_param);
+	dim = isl_basic_set_dim(hull, isl_dim_set);
+	total = isl_basic_set_dim(hull, isl_dim_all);
+	if (nparam < 0 || dim < 0 || total < 0)
 		goto error;
 
-	nparam = isl_basic_set_dim(hull, isl_dim_param);
-	for (i = 0; i < isl_basic_set_dim(hull, isl_dim_set); ++i) {
+	for (i = 0; i < dim; ++i) {
 		int lower = 0, upper = 0;
 		struct isl_basic_set *bounds;
 
-		left = isl_basic_set_total_dim(hull) - nparam - i - 1;
+		left = total - nparam - i - 1;
 		for (j = 0; j < hull->n_eq; ++j) {
 			if (isl_int_is_zero(hull->eq[j][1 + nparam + i]))
 				continue;

diff  --git a/polly/lib/External/isl/isl_ctx.c b/polly/lib/External/isl/isl_ctx.c
index 1a57da7d2260..176fd6f56a1d 100644
--- a/polly/lib/External/isl/isl_ctx.c
+++ b/polly/lib/External/isl/isl_ctx.c
@@ -14,12 +14,40 @@
 #define __isl_calloc(type,size)		((type *)calloc(1, size))
 #define __isl_calloc_type(type)		__isl_calloc(type,sizeof(type))
 
+/* Construct an isl_stat indicating whether "obj" is non-NULL.
+ *
+ * That is, return isl_stat_ok if "obj" is non_NULL and
+ * isl_stat_error otherwise.
+ */
+isl_stat isl_stat_non_null(void *obj)
+{
+	if (obj != NULL)
+		return isl_stat_ok;
+	return isl_stat_error;
+}
+
 /* Return the negation of "b", where the negation of isl_bool_error
  * is isl_bool_error again.
  */
 isl_bool isl_bool_not(isl_bool b)
 {
-	return b < 0 ? isl_bool_error : !b;
+	if (b < 0)
+		return isl_bool_error;
+	if (b == isl_bool_false)
+		return isl_bool_true;
+	return isl_bool_false;
+}
+
+/* Create an isl_bool from an integer.
+ *
+ * Return isl_bool_false if b is zero, otherwise return isl_bool_true.
+ * This function never returns isl_bool_error.
+ */
+isl_bool isl_bool_ok(int b)
+{
+	if (b)
+		return isl_bool_true;
+	return isl_bool_false;
 }
 
 /* Check that the result of an allocation ("p") is not NULL and
@@ -136,7 +164,7 @@ static struct isl_options *find_nested_options(struct isl_args *args,
 		if (arg->type != isl_arg_child)
 			continue;
 
-		if (arg->offset == (size_t) -1)
+		if (arg->offset == ISL_ARG_OFFSET_NONE)
 			child = opt;
 		else
 			child = *(void **)(((char *)opt) + arg->offset);

diff  --git a/polly/lib/External/isl/isl_dim_map.c b/polly/lib/External/isl/isl_dim_map.c
index 916765e3e07d..b0b067d80e6d 100644
--- a/polly/lib/External/isl/isl_dim_map.c
+++ b/polly/lib/External/isl/isl_dim_map.c
@@ -42,6 +42,14 @@ __isl_give isl_dim_map *isl_dim_map_alloc(isl_ctx *ctx, unsigned len)
 	return dim_map;
 }
 
+/* Free "dim_map" and return NULL.
+ */
+__isl_null isl_dim_map *isl_dim_map_free(__isl_take isl_dim_map *dim_map)
+{
+	free(dim_map);
+	return NULL;
+}
+
 void isl_dim_map_range(__isl_keep isl_dim_map *dim_map,
 	unsigned dst_pos, int dst_stride, unsigned src_pos, int src_stride,
 	unsigned n, int sign)
@@ -60,27 +68,30 @@ void isl_dim_map_range(__isl_keep isl_dim_map *dim_map,
 }
 
 void isl_dim_map_dim_range(__isl_keep isl_dim_map *dim_map,
-	__isl_keep isl_space *dim, enum isl_dim_type type,
+	__isl_keep isl_space *space, enum isl_dim_type type,
 	unsigned first, unsigned n, unsigned dst_pos)
 {
 	int i;
 	unsigned src_pos;
 
-	if (!dim_map || !dim)
+	if (!dim_map || !space)
 		return;
 	
-	src_pos = 1 + isl_space_offset(dim, type);
+	src_pos = 1 + isl_space_offset(space, type);
 	for (i = 0; i < n; ++i) {
 		dim_map->m[1 + dst_pos + i].pos = src_pos + first + i;
 		dim_map->m[1 + dst_pos + i].sgn = 1;
 	}
 }
 
-void isl_dim_map_dim(__isl_keep isl_dim_map *dim_map, __isl_keep isl_space *dim,
-	enum isl_dim_type type, unsigned dst_pos)
+void isl_dim_map_dim(__isl_keep isl_dim_map *dim_map,
+	__isl_keep isl_space *space, enum isl_dim_type type, unsigned dst_pos)
 {
-	isl_dim_map_dim_range(dim_map, dim, type,
-			      0, isl_space_dim(dim, type), dst_pos);
+	isl_size dim = isl_space_dim(space, type);
+
+	if (dim < 0)
+		return;
+	isl_dim_map_dim_range(dim_map, space, type, 0, dim, dst_pos);
 }
 
 void isl_dim_map_div(__isl_keep isl_dim_map *dim_map,
@@ -92,7 +103,7 @@ void isl_dim_map_div(__isl_keep isl_dim_map *dim_map,
 	if (!dim_map || !bmap)
 		return;
 	
-	src_pos = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	src_pos = isl_basic_map_offset(bmap, isl_dim_div);
 	for (i = 0; i < bmap->n_div; ++i) {
 		dim_map->m[1 + dst_pos + i].pos = src_pos + i;
 		dim_map->m[1 + dst_pos + i].sgn = 1;
@@ -161,12 +172,12 @@ __isl_give isl_basic_map *isl_basic_map_add_constraints_dim_map(
 		copy_div_dim_map(dst->div[i1], src->div[i], dim_map);
 	}
 
-	free(dim_map);
+	isl_dim_map_free(dim_map);
 	isl_basic_map_free(src);
 
 	return dst;
 error:
-	free(dim_map);
+	isl_dim_map_free(dim_map);
 	isl_basic_map_free(src);
 	isl_basic_map_free(dst);
 	return NULL;
@@ -216,6 +227,7 @@ __isl_give isl_dim_map *isl_dim_map_from_reordering(
 {
 	int i;
 	isl_ctx *ctx;
+	isl_size dim;
 	isl_space *space;
 	struct isl_dim_map *dim_map;
 
@@ -224,7 +236,10 @@ __isl_give isl_dim_map *isl_dim_map_from_reordering(
 
 	ctx = isl_reordering_get_ctx(exp);
 	space = isl_reordering_peek_space(exp);
-	dim_map = isl_dim_map_alloc(ctx, isl_space_dim(space, isl_dim_all));
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0)
+		return NULL;
+	dim_map = isl_dim_map_alloc(ctx, dim);
 	if (!dim_map)
 		return NULL;
 

diff  --git a/polly/lib/External/isl/isl_dim_map.h b/polly/lib/External/isl/isl_dim_map.h
index 0c39b493a769..5e45fe00b2b8 100644
--- a/polly/lib/External/isl/isl_dim_map.h
+++ b/polly/lib/External/isl/isl_dim_map.h
@@ -10,14 +10,15 @@ struct isl_dim_map;
 typedef struct isl_dim_map isl_dim_map;
 
 __isl_give isl_dim_map *isl_dim_map_alloc(isl_ctx *ctx, unsigned len);
+__isl_null isl_dim_map *isl_dim_map_free(__isl_take isl_dim_map *dim_map);
 void isl_dim_map_range(__isl_keep isl_dim_map *dim_map,
 	unsigned dst_pos, int dst_stride, unsigned src_pos, int src_stride,
 	unsigned n, int sign);
 void isl_dim_map_dim_range(__isl_keep isl_dim_map *dim_map,
-	isl_space *dim, enum isl_dim_type type,
+	__isl_keep isl_space *space, enum isl_dim_type type,
 	unsigned first, unsigned n, unsigned dst_pos);
-void isl_dim_map_dim(__isl_keep isl_dim_map *dim_map, __isl_keep isl_space *dim,
-	enum isl_dim_type type, unsigned dst_pos);
+void isl_dim_map_dim(__isl_keep isl_dim_map *dim_map,
+	__isl_keep isl_space *space, enum isl_dim_type type, unsigned dst_pos);
 void isl_dim_map_div(__isl_keep isl_dim_map *dim_map,
 	__isl_keep isl_basic_map *bmap, unsigned dst_pos);
 __isl_give isl_basic_set *isl_basic_set_add_constraints_dim_map(

diff  --git a/polly/lib/External/isl/isl_domain_factor_templ.c b/polly/lib/External/isl/isl_domain_factor_templ.c
new file mode 100644
index 000000000000..c64e9a262f0f
--- /dev/null
+++ b/polly/lib/External/isl/isl_domain_factor_templ.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012      Ecole Normale Superieure
+ * Copyright 2017      Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Drop the "n" domain dimensions starting at "first" from "obj",
+ * after checking that they do not appear in the affine expression.
+ */
+static __isl_give TYPE *FN(TYPE,drop_domain)(__isl_take TYPE *obj,
+	unsigned first, unsigned n)
+{
+	isl_bool involves;
+
+	involves = FN(TYPE,involves_dims)(obj, isl_dim_in, first, n);
+	if (involves < 0)
+		return FN(TYPE,free)(obj);
+	if (involves)
+		isl_die(FN(TYPE,get_ctx)(obj), isl_error_invalid,
+		    "affine expression involves some of the domain dimensions",
+		    return FN(TYPE,free)(obj));
+	return FN(TYPE,drop_dims)(obj, isl_dim_in, first, n);
+}
+
+/* Check that the domain of "obj" is a product.
+ */
+static isl_stat FN(TYPE,check_domain_product)(__isl_keep TYPE *obj)
+{
+	isl_bool is_product;
+
+	is_product = FN(TYPE,domain_is_product)(obj);
+	if (is_product < 0)
+		return isl_stat_error;
+	if (!is_product)
+		isl_die(FN(TYPE,get_ctx)(obj), isl_error_invalid,
+			"domain is not a product", return isl_stat_error);
+	return isl_stat_ok;
+}
+
+/* Given an affine function with a domain of the form [A -> B] that
+ * does not depend on B, return the same function on domain A.
+ */
+__isl_give TYPE *FN(TYPE,domain_factor_domain)(__isl_take TYPE *obj)
+{
+	isl_space *space;
+	isl_size n, n_in;
+
+	if (FN(TYPE,check_domain_product)(obj) < 0)
+		return FN(TYPE,free)(obj);
+	space = FN(TYPE,get_domain_space)(obj);
+	n = isl_space_dim(space, isl_dim_set);
+	space = isl_space_factor_domain(space);
+	n_in = isl_space_dim(space, isl_dim_set);
+	if (n < 0 || n_in < 0)
+		obj = FN(TYPE,free)(obj);
+	else
+		obj = FN(TYPE,drop_domain)(obj, n_in, n - n_in);
+	obj = FN(TYPE,reset_domain_space)(obj, space);
+	return obj;
+}

diff  --git a/polly/lib/External/isl/isl_equalities.c b/polly/lib/External/isl/isl_equalities.c
index 0501cd9faaf8..f3d48468b061 100644
--- a/polly/lib/External/isl/isl_equalities.c
+++ b/polly/lib/External/isl/isl_equalities.c
@@ -634,15 +634,15 @@ static __isl_give isl_basic_set *return_with_identity(
 	__isl_take isl_basic_set *bset, __isl_give isl_mat **T,
 	__isl_give isl_mat **T2)
 {
-	unsigned dim;
+	isl_size dim;
 	isl_mat *id;
 
-	if (!bset)
-		return NULL;
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		return isl_basic_set_free(bset);
 	if (!T && !T2)
 		return bset;
 
-	dim = isl_basic_set_dim(bset, isl_dim_set);
 	id = isl_mat_identity(isl_basic_map_get_ctx(bset), 1 + dim);
 	if (T)
 		*T = isl_mat_copy(id);
@@ -660,21 +660,23 @@ static __isl_give isl_basic_set *return_with_identity(
  * the new variables x2' back to the original variables x, while T2
  * maps the original variables to the new variables.
  */
-static struct isl_basic_set *compress_variables(
-	struct isl_basic_set *bset, struct isl_mat **T, struct isl_mat **T2)
+static __isl_give isl_basic_set *compress_variables(
+	__isl_take isl_basic_set *bset,
+	__isl_give isl_mat **T, __isl_give isl_mat **T2)
 {
 	struct isl_mat *B, *TC;
-	unsigned dim;
+	isl_size dim;
 
 	if (T)
 		*T = NULL;
 	if (T2)
 		*T2 = NULL;
-	if (!bset)
-		goto error;
-	isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
-	isl_assert(bset->ctx, bset->n_div == 0, goto error);
-	dim = isl_basic_set_n_dim(bset);
+	if (isl_basic_set_check_no_params(bset) < 0 ||
+	    isl_basic_set_check_no_locals(bset) < 0)
+		return isl_basic_set_free(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		return isl_basic_set_free(bset);
 	isl_assert(bset->ctx, bset->n_eq <= dim, goto error);
 	if (bset->n_eq == 0)
 		return return_with_identity(bset, T, T2);
@@ -709,18 +711,13 @@ struct isl_basic_set *isl_basic_set_remove_equalities(
 		*T = NULL;
 	if (T2)
 		*T2 = NULL;
-	if (!bset)
-		return NULL;
-	isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
+	if (isl_basic_set_check_no_params(bset) < 0)
+		return isl_basic_set_free(bset);
 	bset = isl_basic_set_gauss(bset, NULL);
 	if (ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY))
 		return return_with_identity(bset, T, T2);
 	bset = compress_variables(bset, T, T2);
 	return bset;
-error:
-	isl_basic_set_free(bset);
-	*T = NULL;
-	return NULL;
 }
 
 /* Check if dimension dim belongs to a residue class
@@ -738,8 +735,8 @@ isl_stat isl_basic_set_dim_residue_class(__isl_keep isl_basic_set *bset,
 	isl_bool fixed;
 	struct isl_ctx *ctx;
 	struct isl_mat *H = NULL, *U = NULL, *C, *H1, *U1;
-	unsigned total;
-	unsigned nparam;
+	isl_size total;
+	isl_size nparam;
 
 	if (!bset || !modulo || !residue)
 		return isl_stat_error;
@@ -753,8 +750,10 @@ isl_stat isl_basic_set_dim_residue_class(__isl_keep isl_basic_set *bset,
 	}
 
 	ctx = isl_basic_set_get_ctx(bset);
-	total = isl_basic_set_total_dim(bset);
-	nparam = isl_basic_set_n_param(bset);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (total < 0 || nparam < 0)
+		return isl_stat_error;
 	H = isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 1, total);
 	H = isl_mat_left_hermite(H, 0, &U, NULL);
 	if (!H)

diff  --git a/polly/lib/External/isl/isl_factorization.c b/polly/lib/External/isl/isl_factorization.c
index f692cdbcd0b0..e6036c3a4f33 100644
--- a/polly/lib/External/isl/isl_factorization.c
+++ b/polly/lib/External/isl/isl_factorization.c
@@ -84,16 +84,17 @@ __isl_give isl_factorizer *isl_factorizer_groups(__isl_keep isl_basic_set *bset,
 	__isl_take isl_mat *Q, __isl_take isl_mat *U, int n, int *len)
 {
 	int i;
-	unsigned nvar;
+	isl_size nvar;
 	unsigned ovar;
-	isl_space *dim;
+	isl_space *space;
 	isl_basic_set *dom;
 	isl_basic_set *ran;
 	isl_morph *morph;
 	isl_factorizer *f;
 	isl_mat *id;
 
-	if (!bset || !Q || !U)
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0 || !Q || !U)
 		goto error;
 
 	ovar = 1 + isl_space_offset(bset->dim, isl_dim_set);
@@ -101,12 +102,11 @@ __isl_give isl_factorizer *isl_factorizer_groups(__isl_keep isl_basic_set *bset,
 	Q = isl_mat_diagonal(isl_mat_copy(id), Q);
 	U = isl_mat_diagonal(id, U);
 
-	nvar = isl_basic_set_dim(bset, isl_dim_set);
-	dim = isl_basic_set_get_space(bset);
-	dom = isl_basic_set_universe(isl_space_copy(dim));
-	dim = isl_space_drop_dims(dim, isl_dim_set, 0, nvar);
-	dim = isl_space_add_dims(dim, isl_dim_set, nvar);
-	ran = isl_basic_set_universe(dim);
+	space = isl_basic_set_get_space(bset);
+	dom = isl_basic_set_universe(isl_space_copy(space));
+	space = isl_space_drop_dims(space, isl_dim_set, 0, nvar);
+	space = isl_space_add_dims(space, isl_dim_set, nvar);
+	ran = isl_basic_set_universe(space);
 	morph = isl_morph_alloc(dom, ran, Q, U);
 	f = isl_factorizer_alloc(morph, n);
 	if (!f)
@@ -258,17 +258,14 @@ __isl_give isl_factorizer *isl_basic_set_factorizer(
 {
 	int i, j, n, done;
 	isl_mat *H, *U, *Q;
-	unsigned nvar;
+	isl_size nvar;
 	struct isl_factor_groups g = { 0 };
 	isl_factorizer *f;
 
-	if (!bset)
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0 || isl_basic_set_check_no_locals(bset) < 0)
 		return NULL;
 
-	isl_assert(bset->ctx, isl_basic_set_dim(bset, isl_dim_div) == 0,
-		return NULL);
-
-	nvar = isl_basic_set_dim(bset, isl_dim_set);
 	if (nvar <= 1)
 		return isl_factorizer_identity(bset);
 

diff  --git a/polly/lib/External/isl/isl_farkas.c b/polly/lib/External/isl/isl_farkas.c
index cb45a633a1c1..af982e6ed3bd 100644
--- a/polly/lib/External/isl/isl_farkas.c
+++ b/polly/lib/External/isl/isl_farkas.c
@@ -61,27 +61,29 @@
  * to the left, with the leftmost ending up in the constant position.
  */
 
-/* Add the given prefix to all named isl_dim_set dimensions in "dim".
+/* Add the given prefix to all named isl_dim_set dimensions in "space".
  */
-static __isl_give isl_space *isl_space_prefix(__isl_take isl_space *dim,
+static __isl_give isl_space *isl_space_prefix(__isl_take isl_space *space,
 	const char *prefix)
 {
 	int i;
 	isl_ctx *ctx;
-	unsigned nvar;
+	isl_size nvar;
 	size_t prefix_len = strlen(prefix);
 
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	ctx = isl_space_get_ctx(dim);
-	nvar = isl_space_dim(dim, isl_dim_set);
+	ctx = isl_space_get_ctx(space);
+	nvar = isl_space_dim(space, isl_dim_set);
+	if (nvar < 0)
+		return isl_space_free(space);
 
 	for (i = 0; i < nvar; ++i) {
 		const char *name;
 		char *prefix_name;
 
-		name = isl_space_get_dim_name(dim, isl_dim_set, i);
+		name = isl_space_get_dim_name(space, isl_dim_set, i);
 		if (!name)
 			continue;
 
@@ -92,13 +94,14 @@ static __isl_give isl_space *isl_space_prefix(__isl_take isl_space *dim,
 		memcpy(prefix_name, prefix, prefix_len);
 		strcpy(prefix_name + prefix_len, name);
 
-		dim = isl_space_set_dim_name(dim, isl_dim_set, i, prefix_name);
+		space = isl_space_set_dim_name(space,
+						isl_dim_set, i, prefix_name);
 		free(prefix_name);
 	}
 
-	return dim;
+	return space;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -115,55 +118,61 @@ static __isl_give isl_space *isl_space_prefix(__isl_take isl_space *dim,
  *
  * and prefix each dimension name with "c_".
  */
-static __isl_give isl_space *isl_space_coefficients(__isl_take isl_space *dim)
+static __isl_give isl_space *isl_space_coefficients(__isl_take isl_space *space)
 {
-	isl_space *dim_param;
-	unsigned nvar;
-	unsigned nparam;
-
-	nvar = isl_space_dim(dim, isl_dim_set);
-	nparam = isl_space_dim(dim, isl_dim_param);
-	dim_param = isl_space_copy(dim);
-	dim_param = isl_space_drop_dims(dim_param, isl_dim_set, 0, nvar);
-	dim_param = isl_space_move_dims(dim_param, isl_dim_set, 0,
+	isl_space *space_param;
+	isl_size nvar;
+	isl_size nparam;
+
+	nvar = isl_space_dim(space, isl_dim_set);
+	nparam = isl_space_dim(space, isl_dim_param);
+	if (nvar < 0 || nparam < 0)
+		return isl_space_free(space);
+	space_param = isl_space_copy(space);
+	space_param = isl_space_drop_dims(space_param, isl_dim_set, 0, nvar);
+	space_param = isl_space_move_dims(space_param, isl_dim_set, 0,
 				 isl_dim_param, 0, nparam);
-	dim_param = isl_space_prefix(dim_param, "c_");
-	dim_param = isl_space_insert_dims(dim_param, isl_dim_set, 0, 1);
-	dim_param = isl_space_set_dim_name(dim_param, isl_dim_set, 0, "c_cst");
-	dim = isl_space_drop_dims(dim, isl_dim_param, 0, nparam);
-	dim = isl_space_prefix(dim, "c_");
-	dim = isl_space_join(isl_space_from_domain(dim_param),
-			   isl_space_from_range(dim));
-	dim = isl_space_wrap(dim);
-	dim = isl_space_set_tuple_name(dim, isl_dim_set, "coefficients");
-
-	return dim;
+	space_param = isl_space_prefix(space_param, "c_");
+	space_param = isl_space_insert_dims(space_param, isl_dim_set, 0, 1);
+	space_param = isl_space_set_dim_name(space_param,
+				isl_dim_set, 0, "c_cst");
+	space = isl_space_drop_dims(space, isl_dim_param, 0, nparam);
+	space = isl_space_prefix(space, "c_");
+	space = isl_space_join(isl_space_from_domain(space_param),
+			   isl_space_from_range(space));
+	space = isl_space_wrap(space);
+	space = isl_space_set_tuple_name(space, isl_dim_set, "coefficients");
+
+	return space;
 }
 
-/* Drop the given prefix from all named dimensions of type "type" in "dim".
+/* Drop the given prefix from all named dimensions of type "type" in "space".
  */
-static __isl_give isl_space *isl_space_unprefix(__isl_take isl_space *dim,
+static __isl_give isl_space *isl_space_unprefix(__isl_take isl_space *space,
 	enum isl_dim_type type, const char *prefix)
 {
 	int i;
-	unsigned n;
+	isl_size n;
 	size_t prefix_len = strlen(prefix);
 
-	n = isl_space_dim(dim, type);
+	n = isl_space_dim(space, type);
+	if (n < 0)
+		return isl_space_free(space);
 
 	for (i = 0; i < n; ++i) {
 		const char *name;
 
-		name = isl_space_get_dim_name(dim, type, i);
+		name = isl_space_get_dim_name(space, type, i);
 		if (!name)
 			continue;
 		if (strncmp(name, prefix, prefix_len))
 			continue;
 
-		dim = isl_space_set_dim_name(dim, type, i, name + prefix_len);
+		space = isl_space_set_dim_name(space,
+						type, i, name + prefix_len);
 	}
 
-	return dim;
+	return space;
 }
 
 /* Given a dimension specification of the space of coefficients, construct
@@ -179,19 +188,22 @@ static __isl_give isl_space *isl_space_unprefix(__isl_take isl_space *dim,
  *
  * and drop the "c_" prefix from the dimension names.
  */
-static __isl_give isl_space *isl_space_solutions(__isl_take isl_space *dim)
+static __isl_give isl_space *isl_space_solutions(__isl_take isl_space *space)
 {
-	unsigned nparam;
-
-	dim = isl_space_unwrap(dim);
-	dim = isl_space_drop_dims(dim, isl_dim_in, 0, 1);
-	dim = isl_space_unprefix(dim, isl_dim_in, "c_");
-	dim = isl_space_unprefix(dim, isl_dim_out, "c_");
-	nparam = isl_space_dim(dim, isl_dim_in);
-	dim = isl_space_move_dims(dim, isl_dim_param, 0, isl_dim_in, 0, nparam);
-	dim = isl_space_range(dim);
-
-	return dim;
+	isl_size nparam;
+
+	space = isl_space_unwrap(space);
+	space = isl_space_drop_dims(space, isl_dim_in, 0, 1);
+	space = isl_space_unprefix(space, isl_dim_in, "c_");
+	space = isl_space_unprefix(space, isl_dim_out, "c_");
+	nparam = isl_space_dim(space, isl_dim_in);
+	if (nparam < 0)
+		return isl_space_free(space);
+	space = isl_space_move_dims(space,
+				    isl_dim_param, 0, isl_dim_in, 0, nparam);
+	space = isl_space_range(space);
+
+	return space;
 }
 
 /* Return the rational universe basic set in the given space.
@@ -210,7 +222,7 @@ static __isl_give isl_basic_set *rational_universe(__isl_take isl_space *space)
  * As explained above, we add an extra dimension to represent
  * the coefficient of the constant term when going from solutions
  * to coefficients (shift == 1) and we drop the extra dimension when going
- * in the opposite direction (shift == -1).  "dim" is the space in which
+ * in the opposite direction (shift == -1).  "space" is the space in which
  * the dual should be created.
  *
  * If "bset" is (obviously) empty, then the way this emptiness
@@ -223,14 +235,16 @@ static __isl_give isl_basic_set *farkas(__isl_take isl_space *space,
 {
 	int i, j, k;
 	isl_basic_set *dual = NULL;
-	unsigned total;
+	isl_size total;
 
 	if (isl_basic_set_plain_is_empty(bset)) {
 		isl_basic_set_free(bset);
 		return rational_universe(space);
 	}
 
-	total = isl_basic_set_total_dim(bset);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
+		space = isl_space_free(space);
 
 	dual = isl_basic_set_alloc_space(space, bset->n_eq + bset->n_ineq,
 					total, bset->n_ineq + (shift > 0));
@@ -298,7 +312,7 @@ static __isl_give isl_basic_set *farkas(__isl_take isl_space *space,
 __isl_give isl_basic_set *isl_basic_set_coefficients(
 	__isl_take isl_basic_set *bset)
 {
-	isl_space *dim;
+	isl_space *space;
 
 	if (!bset)
 		return NULL;
@@ -307,10 +321,10 @@ __isl_give isl_basic_set *isl_basic_set_coefficients(
 			"input set not allowed to have local variables",
 			goto error);
 
-	dim = isl_basic_set_get_space(bset);
-	dim = isl_space_coefficients(dim);
+	space = isl_basic_set_get_space(bset);
+	space = isl_space_coefficients(space);
 
-	return farkas(dim, bset, 1);
+	return farkas(space, bset, 1);
 error:
 	isl_basic_set_free(bset);
 	return NULL;
@@ -323,7 +337,7 @@ __isl_give isl_basic_set *isl_basic_set_coefficients(
 __isl_give isl_basic_set *isl_basic_set_solutions(
 	__isl_take isl_basic_set *bset)
 {
-	isl_space *dim;
+	isl_space *space;
 
 	if (!bset)
 		return NULL;
@@ -332,10 +346,10 @@ __isl_give isl_basic_set *isl_basic_set_solutions(
 			"input set not allowed to have local variables",
 			goto error);
 
-	dim = isl_basic_set_get_space(bset);
-	dim = isl_space_solutions(dim);
+	space = isl_basic_set_get_space(bset);
+	space = isl_space_solutions(space);
 
-	return farkas(dim, bset, -1);
+	return farkas(space, bset, -1);
 error:
 	isl_basic_set_free(bset);
 	return NULL;

diff  --git a/polly/lib/External/isl/isl_flow.c b/polly/lib/External/isl/isl_flow.c
index 946be84e4b0b..1b88c2334e3b 100644
--- a/polly/lib/External/isl/isl_flow.c
+++ b/polly/lib/External/isl/isl_flow.c
@@ -162,7 +162,7 @@ struct isl_labeled_map {
 	int		must;
 };
 
-typedef int (*isl_access_coscheduled)(void *first, void *second);
+typedef isl_bool (*isl_access_coscheduled)(void *first, void *second);
 
 /* A structure containing the input for dependence analysis:
  * - a sink
@@ -519,12 +519,12 @@ __isl_give isl_map *isl_flow_get_no_source(__isl_keep isl_flow *deps, int must)
 		return isl_set_unwrap(isl_set_copy(deps->may_no_source));
 }
 
-void isl_flow_free(__isl_take isl_flow *deps)
+__isl_null isl_flow *isl_flow_free(__isl_take isl_flow *deps)
 {
 	int i;
 
 	if (!deps)
-		return;
+		return NULL;
 	isl_set_free(deps->must_no_source);
 	isl_set_free(deps->may_no_source);
 	if (deps->dep) {
@@ -533,6 +533,8 @@ void isl_flow_free(__isl_take isl_flow *deps)
 		free(deps->dep);
 	}
 	free(deps);
+
+	return NULL;
 }
 
 isl_ctx *isl_flow_get_ctx(__isl_keep isl_flow *deps)
@@ -729,8 +731,11 @@ static isl_stat intermediate_sources(__isl_keep isl_access_info *acc,
 	struct isl_map **temp_rel, int j, int sink_level)
 {
 	int k, level;
-	int depth = 2 * isl_map_dim(acc->source[j].map, isl_dim_in) + 1;
+	isl_size n_in = isl_map_dim(acc->source[j].map, isl_dim_in);
+	int depth = 2 * n_in + 1;
 
+	if (n_in < 0)
+		return isl_stat_error;
 	if (isl_map_plain_is_empty(temp_rel[j]))
 		return isl_stat_ok;
 
@@ -842,9 +847,12 @@ static __isl_give isl_map *all_intermediate_sources(
 	int j, int sink_level)
 {
 	int k, level;
-	int depth = 2 * isl_map_dim(acc->source[acc->n_must + j].map,
-					isl_dim_in) + 1;
+	isl_size n_in = isl_map_dim(acc->source[acc->n_must + j].map,
+				    isl_dim_in);
+	int depth = 2 * n_in + 1;
 
+	if (n_in < 0)
+		return isl_map_free(map);
 	for (k = 0; k < acc->n_must; ++k) {
 		int plevel;
 
@@ -988,10 +996,16 @@ static __isl_give isl_flow *handle_coscheduled(__isl_keep isl_access_info *acc,
 		move = isl_map_empty(isl_map_get_space(must_rel[i]));
 		for (j = i - 1; j >= 0; --j) {
 			int depth;
+			isl_bool coscheduled;
 			isl_map *map, *factor;
 
-			if (!acc->coscheduled(acc->source[i].data,
-						acc->source[j].data))
+			coscheduled = acc->coscheduled(acc->source[i].data,
+							acc->source[j].data);
+			if (coscheduled < 0) {
+				isl_map_free(move);
+				return isl_flow_free(flow);
+			}
+			if (!coscheduled)
 				continue;
 			depth = acc->level_before(acc->source[i].data,
 						acc->source[j].data) / 2;
@@ -1003,11 +1017,17 @@ static __isl_give isl_flow *handle_coscheduled(__isl_keep isl_access_info *acc,
 		}
 		for (j = 0; j < acc->n_may; ++j) {
 			int depth, pos;
+			isl_bool coscheduled;
 			isl_map *map, *factor;
 
 			pos = acc->n_must + j;
-			if (!acc->coscheduled(acc->source[i].data,
-						acc->source[pos].data))
+			coscheduled = acc->coscheduled(acc->source[i].data,
+							acc->source[pos].data);
+			if (coscheduled < 0) {
+				isl_map_free(move);
+				return isl_flow_free(flow);
+			}
+			if (!coscheduled)
 				continue;
 			depth = acc->level_before(acc->source[i].data,
 						acc->source[pos].data) / 2;
@@ -1132,6 +1152,7 @@ static __isl_give isl_flow *compute_val_based_dependences(
 	isl_set *mustdo = NULL;
 	isl_set *maydo = NULL;
 	int level, j;
+	isl_size n_in;
 	int depth;
 	isl_map **must_rel = NULL;
 	isl_map **may_rel = NULL;
@@ -1144,7 +1165,10 @@ static __isl_give isl_flow *compute_val_based_dependences(
 		goto error;
 	ctx = isl_map_get_ctx(acc->sink.map);
 
-	depth = 2 * isl_map_dim(acc->sink.map, isl_dim_in) + 1;
+	n_in = isl_map_dim(acc->sink.map, isl_dim_in);
+	if (n_in < 0)
+		goto error;
+	depth = 2 * n_in + 1;
 	mustdo = isl_map_domain(isl_map_copy(acc->sink.map));
 	maydo = isl_set_empty(isl_set_get_space(mustdo));
 	if (!mustdo || !maydo)
@@ -1211,7 +1235,9 @@ static __isl_give isl_flow *compute_val_based_dependences(
 				goto error;
 		}
 
-		handle_coscheduled(acc, must_rel, may_rel, res);
+		res = handle_coscheduled(acc, must_rel, may_rel, res);
+		if (!res)
+			goto error;
 
 		for (j = 0; j < acc->n_may; ++j) {
 			int plevel;
@@ -1395,18 +1421,21 @@ static __isl_give struct isl_sched_info *sched_info_alloc(
 	__isl_keep isl_map *map)
 {
 	isl_ctx *ctx;
-	isl_space *dim;
+	isl_space *space;
 	struct isl_sched_info *info;
-	int i, n;
+	int i;
+	isl_size n;
 
 	if (!map)
 		return NULL;
 
-	dim = isl_space_unwrap(isl_space_domain(isl_map_get_space(map)));
-	if (!dim)
+	space = isl_space_unwrap(isl_space_domain(isl_map_get_space(map)));
+	if (!space)
+		return NULL;
+	n = isl_space_dim(space, isl_dim_in);
+	isl_space_free(space);
+	if (n < 0)
 		return NULL;
-	n = isl_space_dim(dim, isl_dim_in);
-	isl_space_free(dim);
 
 	ctx = isl_map_get_ctx(map);
 	info = isl_alloc_type(ctx, struct isl_sched_info);
@@ -1734,21 +1763,9 @@ __isl_give isl_union_access_info *isl_union_access_info_copy(
 	return copy;
 }
 
-/* Print a key-value pair of a YAML mapping to "p",
- * with key "name" and value "umap".
- */
-static __isl_give isl_printer *print_union_map_field(__isl_take isl_printer *p,
-	const char *name, __isl_keep isl_union_map *umap)
-{
-	p = isl_printer_print_str(p, name);
-	p = isl_printer_yaml_next(p);
-	p = isl_printer_print_str(p, "\"");
-	p = isl_printer_print_union_map(p, umap);
-	p = isl_printer_print_str(p, "\"");
-	p = isl_printer_yaml_next(p);
-
-	return p;
-}
+#undef BASE
+#define BASE union_map
+#include "print_yaml_field_templ.c"
 
 /* An enumeration of the various keys that may appear in a YAML mapping
  * of an isl_union_access_info object.
@@ -1796,7 +1813,7 @@ static __isl_give isl_printer *print_access_field(__isl_take isl_printer *p,
 		if (empty)
 			return p;
 	}
-	return print_union_map_field(p, key_str[type], info->access[type]);
+	return print_yaml_field_union_map(p, key_str[type], info->access[type]);
 }
 
 /* Print the information contained in "access" to "p".
@@ -1819,8 +1836,8 @@ __isl_give isl_printer *isl_printer_print_union_access_info(
 		p = isl_printer_print_schedule(p, access->schedule);
 		p = isl_printer_yaml_next(p);
 	} else {
-		p = print_union_map_field(p, key_str[isl_ai_key_schedule_map],
-						access->schedule_map);
+		p = print_yaml_field_union_map(p,
+			key_str[isl_ai_key_schedule_map], access->schedule_map);
 	}
 	p = isl_printer_yaml_end_mapping(p);
 
@@ -2395,11 +2412,13 @@ static int before(void *first, void *second)
 {
 	struct isl_sched_info *info1 = first;
 	struct isl_sched_info *info2 = second;
-	int n1, n2;
+	isl_size n1, n2;
 	int i;
 
 	n1 = isl_vec_size(info1->cst);
 	n2 = isl_vec_size(info2->cst);
+	if (n1 < 0 || n2 < 0)
+		return -1;
 
 	if (n2 < n1)
 		n1 = n2;
@@ -2425,20 +2444,22 @@ static int before(void *first, void *second)
 }
 
 /* Check if the given two accesses may be coscheduled.
- * If so, return 1.  Otherwise return 0.
+ * If so, return isl_bool_true.  Otherwise return isl_bool_false.
  *
  * Two accesses may only be coscheduled if the fixed schedule
  * coordinates have the same values.
  */
-static int coscheduled(void *first, void *second)
+static isl_bool coscheduled(void *first, void *second)
 {
 	struct isl_sched_info *info1 = first;
 	struct isl_sched_info *info2 = second;
-	int n1, n2;
+	isl_size n1, n2;
 	int i;
 
 	n1 = isl_vec_size(info1->cst);
 	n2 = isl_vec_size(info2->cst);
+	if (n1 < 0 || n2 < 0)
+		return isl_bool_error;
 
 	if (n2 < n1)
 		n1 = n2;
@@ -2452,10 +2473,10 @@ static int coscheduled(void *first, void *second)
 			continue;
 		cmp = isl_vec_cmp_element(info1->cst, info2->cst, i);
 		if (cmp != 0)
-			return 0;
+			return isl_bool_false;
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 /* Given a sink access, look for all the source accesses that access
@@ -2798,6 +2819,7 @@ static isl_bool count_sink_source(__isl_keep isl_schedule_node *node,
 	isl_union_set *domain;
 	isl_union_map *umap;
 	isl_bool r = isl_bool_false;
+	isl_size n;
 
 	if (isl_schedule_node_get_type(node) != isl_schedule_node_leaf)
 		return isl_bool_true;
@@ -2806,23 +2828,23 @@ static isl_bool count_sink_source(__isl_keep isl_schedule_node *node,
 
 	umap = isl_union_map_copy(data->access->access[isl_access_sink]);
 	umap = isl_union_map_intersect_domain(umap, isl_union_set_copy(domain));
-	data->n_sink += isl_union_map_n_map(umap);
+	data->n_sink += n = isl_union_map_n_map(umap);
 	isl_union_map_free(umap);
-	if (!umap)
+	if (n < 0)
 		r = isl_bool_error;
 
 	umap = isl_union_map_copy(data->access->access[isl_access_must_source]);
 	umap = isl_union_map_intersect_domain(umap, isl_union_set_copy(domain));
-	data->n_source += isl_union_map_n_map(umap);
+	data->n_source += n = isl_union_map_n_map(umap);
 	isl_union_map_free(umap);
-	if (!umap)
+	if (n < 0)
 		r = isl_bool_error;
 
 	umap = isl_union_map_copy(data->access->access[isl_access_may_source]);
 	umap = isl_union_map_intersect_domain(umap, isl_union_set_copy(domain));
-	data->n_source += isl_union_map_n_map(umap);
+	data->n_source += n = isl_union_map_n_map(umap);
 	isl_union_map_free(umap);
-	if (!umap)
+	if (n < 0)
 		r = isl_bool_error;
 
 	isl_union_set_free(domain);
@@ -2941,21 +2963,27 @@ static int before_node(void *first, void *second)
 	isl_schedule_node *node1 = first;
 	isl_schedule_node *node2 = second;
 	isl_schedule_node *shared;
-	int depth;
+	isl_size depth;
 	int before = 0;
 
 	shared = isl_schedule_node_get_shared_ancestor(node1, node2);
-	if (!shared)
+	depth = isl_schedule_node_get_schedule_depth(shared);
+	if (depth < 0) {
+		isl_schedule_node_free(shared);
 		return -1;
+	}
 
-	depth = isl_schedule_node_get_schedule_depth(shared);
 	if (isl_schedule_node_get_type(shared) == isl_schedule_node_sequence) {
-		int pos1, pos2;
+		isl_size pos1, pos2;
 
 		pos1 = isl_schedule_node_get_ancestor_child_position(node1,
 								    shared);
 		pos2 = isl_schedule_node_get_ancestor_child_position(node2,
 								    shared);
+		if (pos1 < 0 || pos2 < 0) {
+			isl_schedule_node_free(shared);
+			return -1;
+		}
 		before = pos1 < pos2;
 	}
 
@@ -2965,16 +2993,16 @@ static int before_node(void *first, void *second)
 }
 
 /* Check if the given two accesses may be coscheduled.
- * If so, return 1.  Otherwise return 0.
+ * If so, return isl_bool_true.  Otherwise return isl_bool_false.
  *
  * Two accesses may only be coscheduled if they appear in the same leaf.
  */
-static int coscheduled_node(void *first, void *second)
+static isl_bool coscheduled_node(void *first, void *second)
 {
 	isl_schedule_node *node1 = first;
 	isl_schedule_node *node2 = second;
 
-	return node1 == node2;
+	return isl_bool_ok(node1 == node2);
 }
 
 /* Add the scheduled sources from "data" that access
@@ -3212,14 +3240,15 @@ __isl_give isl_printer *isl_printer_print_union_flow(
 
 	p = isl_printer_yaml_start_mapping(p);
 	umap = isl_union_flow_get_full_must_dependence(flow);
-	p = print_union_map_field(p, "must_dependence", umap);
+	p = print_yaml_field_union_map(p, "must_dependence", umap);
 	isl_union_map_free(umap);
 	umap = isl_union_flow_get_full_may_dependence(flow);
-	p = print_union_map_field(p, "may_dependence", umap);
+	p = print_yaml_field_union_map(p, "may_dependence", umap);
 	isl_union_map_free(umap);
-	p = print_union_map_field(p, "must_no_source", flow->must_no_source);
+	p = print_yaml_field_union_map(p, "must_no_source",
+					flow->must_no_source);
 	umap = isl_union_flow_get_may_no_source(flow);
-	p = print_union_map_field(p, "may_no_source", umap);
+	p = print_yaml_field_union_map(p, "may_no_source", umap);
 	isl_union_map_free(umap);
 	p = isl_printer_yaml_end_mapping(p);
 

diff  --git a/polly/lib/External/isl/isl_fold.c b/polly/lib/External/isl/isl_fold.c
index 9e1196ac5e5f..44d70c061b73 100644
--- a/polly/lib/External/isl/isl_fold.c
+++ b/polly/lib/External/isl/isl_fold.c
@@ -20,14 +20,16 @@
 #include <isl_vec_private.h>
 #include <isl_config.h>
 
-#undef BASE
-#define BASE pw_qpolynomial_fold
+#undef EL_BASE
+#define EL_BASE pw_qpolynomial_fold
 
 #include <isl_list_templ.c>
 
 enum isl_fold isl_fold_type_negate(enum isl_fold type)
 {
 	switch (type) {
+	case isl_fold_error:
+		return isl_fold_error;
 	case isl_fold_min:
 		return isl_fold_max;
 	case isl_fold_max:
@@ -40,15 +42,15 @@ enum isl_fold isl_fold_type_negate(enum isl_fold type)
 }
 
 static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
-	enum isl_fold type, __isl_take isl_space *dim, int n)
+	enum isl_fold type, __isl_take isl_space *space, int n)
 {
 	isl_qpolynomial_fold *fold;
 
-	if (!dim)
+	if (!space)
 		goto error;
 
-	isl_assert(dim->ctx, n >= 0, goto error);
-	fold = isl_calloc(dim->ctx, struct isl_qpolynomial_fold,
+	isl_assert(space->ctx, n >= 0, goto error);
+	fold = isl_calloc(space->ctx, struct isl_qpolynomial_fold,
 			sizeof(struct isl_qpolynomial_fold) +
 			(n - 1) * sizeof(struct isl_qpolynomial *));
 	if (!fold)
@@ -58,11 +60,11 @@ static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
 	fold->size = n;
 	fold->n = 0;
 	fold->type = type;
-	fold->dim = dim;
+	fold->dim = space;
 
 	return fold;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -259,12 +261,12 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_insert_dims(
  */
 static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial *qp)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
 	if (isl_qpolynomial_is_nan(qp))
 		return 0;
 
-	cst = isl_upoly_as_cst(qp->upoly);
+	cst = isl_poly_as_cst(qp->poly);
 	if (!cst)
 		return 0;
 
@@ -329,10 +331,10 @@ static int isl_qpolynomial_aff_sign(__isl_keep isl_set *set,
 static int isl_qpolynomial_sign(__isl_keep isl_set *set,
 	__isl_keep isl_qpolynomial *qp)
 {
-	int d;
+	isl_size d;
 	int i;
-	int is;
-	struct isl_upoly_rec *rec;
+	isl_bool is;
+	isl_poly_rec *rec;
 	isl_vec *v;
 	isl_int l;
 	enum isl_lp_result res;
@@ -353,18 +355,20 @@ static int isl_qpolynomial_sign(__isl_keep isl_set *set,
 	if (qp->div->n_row > 0)
 		return 0;
 
-	rec = isl_upoly_as_rec(qp->upoly);
+	rec = isl_poly_as_rec(qp->poly);
 	if (!rec)
 		return 0;
 
 	d = isl_space_dim(qp->dim, isl_dim_all);
+	if (d < 0)
+		return 0;
 	v = isl_vec_alloc(set->ctx, 2 + d);
 	if (!v)
 		return 0;
 
 	isl_seq_clr(v->el + 1, 1 + d);
 	isl_int_set_si(v->el[0], 1);
-	isl_int_set_si(v->el[2 + qp->upoly->var], 1);
+	isl_int_set_si(v->el[2 + qp->poly->var], 1);
 
 	isl_int_init(l);
 
@@ -377,16 +381,16 @@ static int isl_qpolynomial_sign(__isl_keep isl_set *set,
 
 		min = isl_qpolynomial_cst_on_domain(isl_space_copy(qp->dim), l);
 		base = isl_qpolynomial_var_pow_on_domain(isl_space_copy(qp->dim),
-						qp->upoly->var, 1);
+						qp->poly->var, 1);
 
 		r = isl_qpolynomial_alloc(isl_space_copy(qp->dim), 0,
-					  isl_upoly_copy(rec->p[rec->n - 1]));
+					  isl_poly_copy(rec->p[rec->n - 1]));
 		q = isl_qpolynomial_copy(r);
 
 		for (i = rec->n - 2; i >= 0; --i) {
 			r = isl_qpolynomial_mul(r, isl_qpolynomial_copy(min));
 			t = isl_qpolynomial_alloc(isl_space_copy(qp->dim), 0,
-						  isl_upoly_copy(rec->p[i]));
+						  isl_poly_copy(rec->p[i]));
 			r = isl_qpolynomial_add(r, t);
 			if (i == 0)
 				break;
@@ -665,14 +669,25 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
 	return isl_qpolynomial_fold_gist(fold, dom_context);
 }
 
+/* Return a zero (i.e., empty) isl_qpolynomial_fold in the given space.
+ *
+ * This is a helper function for isl_pw_*_as_* that ensures a uniform
+ * interface over all piecewise types.
+ */
+static __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_zero_in_space(
+	__isl_take isl_space *space, enum isl_fold type)
+{
+	return isl_qpolynomial_fold_empty(type, isl_space_domain(space));
+}
+
 #define isl_qpolynomial_fold_involves_nan isl_qpolynomial_fold_is_nan
 
 #define HAS_TYPE
 
 #undef PW
 #define PW isl_pw_qpolynomial_fold
-#undef EL
-#define EL isl_qpolynomial_fold
+#undef BASE
+#define BASE qpolynomial_fold
 #undef EL_IS_ZERO
 #define EL_IS_ZERO is_empty
 #undef ZERO
@@ -684,12 +699,13 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
 #undef DEFAULT_IS_ZERO
 #define DEFAULT_IS_ZERO 1
 
-#define NO_NEG
-#define NO_SUB
-#define NO_PULLBACK
-
 #include <isl_pw_templ.c>
 #include <isl_pw_eval.c>
+#include <isl_pw_insert_dims_templ.c>
+#include <isl_pw_lift_templ.c>
+#include <isl_pw_morph_templ.c>
+#include <isl_pw_move_dims_templ.c>
+#include <isl_pw_opt_templ.c>
 
 #undef BASE
 #define BASE pw_qpolynomial_fold
@@ -775,27 +791,30 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_cow(
 	return isl_qpolynomial_fold_dup(fold);
 }
 
-void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
+__isl_null isl_qpolynomial_fold *isl_qpolynomial_fold_free(
+	__isl_take isl_qpolynomial_fold *fold)
 {
 	int i;
 
 	if (!fold)
-		return;
+		return NULL;
 	if (--fold->ref > 0)
-		return;
+		return NULL;
 
 	for (i = 0; i < fold->n; ++i)
 		isl_qpolynomial_free(fold->qp[i]);
 	isl_space_free(fold->dim);
 	free(fold);
+
+	return NULL;
 }
 
-int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
+isl_bool isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
 {
 	if (!fold)
-		return -1;
+		return isl_bool_error;
 
-	return fold->n == 0;
+	return isl_bool_ok(fold->n == 0);
 }
 
 /* Does "fold" represent max(NaN) or min(NaN)?
@@ -1178,7 +1197,7 @@ __isl_give isl_val *isl_qpolynomial_fold_opt_on_domain(
 /* Check whether for each quasi-polynomial in "fold2" there is
  * a quasi-polynomial in "fold1" that dominates it on "set".
  */
-static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
+static isl_bool qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
 	__isl_keep isl_qpolynomial_fold *fold1,
 	__isl_keep isl_qpolynomial_fold *fold2)
 {
@@ -1186,7 +1205,7 @@ static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
 	int covers;
 
 	if (!set || !fold1 || !fold2)
-		return -1;
+		return isl_bool_error;
 
 	covers = fold1->type == isl_fold_max ? 1 : -1;
 
@@ -1204,30 +1223,31 @@ static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
 				break;
 		}
 		if (j >= fold1->n)
-			return 0;
+			return isl_bool_false;
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 /* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
  * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
  * that of pwf2.
  */
-int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
+isl_bool isl_pw_qpolynomial_fold_covers(
+	__isl_keep isl_pw_qpolynomial_fold *pwf1,
 	__isl_keep isl_pw_qpolynomial_fold *pwf2)
 {
 	int i, j;
 	isl_set *dom1, *dom2;
-	int is_subset;
+	isl_bool is_subset;
 
 	if (!pwf1 || !pwf2)
-		return -1;
+		return isl_bool_error;
 
 	if (pwf2->n == 0)
-		return 1;
+		return isl_bool_true;
 	if (pwf1->n == 0)
-		return 0;
+		return isl_bool_false;
 
 	dom1 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1));
 	dom2 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2));
@@ -1240,9 +1260,9 @@ int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
 
 	for (i = 0; i < pwf2->n; ++i) {
 		for (j = 0; j < pwf1->n; ++j) {
-			int is_empty;
+			isl_bool is_empty;
 			isl_set *common;
-			int covers;
+			isl_bool covers;
 
 			common = isl_set_intersect(isl_set_copy(pwf1->p[j].set),
 						   isl_set_copy(pwf2->p[i].set));
@@ -1250,7 +1270,7 @@ int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
 			if (is_empty < 0 || is_empty) {
 				isl_set_free(common);
 				if (is_empty < 0)
-					return -1;
+					return isl_bool_error;
 				continue;
 			}
 			covers = qpolynomial_fold_covers_on_domain(common,
@@ -1261,7 +1281,7 @@ int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
 		}
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_morph_domain(
@@ -1304,15 +1324,25 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_morph_domain(
 enum isl_fold isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold *fold)
 {
 	if (!fold)
-		return isl_fold_list;
+		return isl_fold_error;
 	return fold->type;
 }
 
+/* Return the type of this piecewise quasipolynomial reduction.
+ */
+enum isl_fold isl_pw_qpolynomial_fold_get_type(
+	__isl_keep isl_pw_qpolynomial_fold *pwf)
+{
+	if (!pwf)
+		return isl_fold_error;
+	return pwf->type;
+}
+
 enum isl_fold isl_union_pw_qpolynomial_fold_get_type(
 	__isl_keep isl_union_pw_qpolynomial_fold *upwf)
 {
 	if (!upwf)
-		return isl_fold_list;
+		return isl_fold_error;
 	return upwf->type;
 }
 
@@ -1515,24 +1545,24 @@ static isl_bool join_compatible(__isl_keep isl_space *space1,
  */
 __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_bool *tight)
 {
 	isl_ctx *ctx;
 	isl_set *dom;
-	isl_space *map_dim;
-	isl_space *pwf_dim;
-	unsigned n_in;
+	isl_space *map_space;
+	isl_space *pwf_space;
+	isl_size n_in;
 	isl_bool ok;
 
 	ctx = isl_map_get_ctx(map);
 	if (!ctx)
 		goto error;
 
-	map_dim = isl_map_get_space(map);
-	pwf_dim = isl_pw_qpolynomial_fold_get_space(pwf);
-	ok = join_compatible(map_dim, pwf_dim);
-	isl_space_free(map_dim);
-	isl_space_free(pwf_dim);
+	map_space = isl_map_get_space(map);
+	pwf_space = isl_pw_qpolynomial_fold_get_space(pwf);
+	ok = join_compatible(map_space, pwf_space);
+	isl_space_free(map_space);
+	isl_space_free(pwf_space);
 	if (ok < 0)
 		goto error;
 	if (!ok)
@@ -1540,6 +1570,8 @@ __isl_give isl_pw_qpolynomial_fold *isl_map_apply_pw_qpolynomial_fold(
 			goto error);
 
 	n_in = isl_map_dim(map, isl_dim_in);
+	if (n_in < 0)
+		goto error;
 	pwf = isl_pw_qpolynomial_fold_insert_dims(pwf, isl_dim_in, 0, n_in);
 
 	dom = isl_map_wrap(map);
@@ -1558,7 +1590,7 @@ __isl_give isl_pw_qpolynomial_fold *isl_map_apply_pw_qpolynomial_fold(
 
 __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_bool *tight)
 {
 	return isl_map_apply_pw_qpolynomial_fold(set, pwf, tight);
 }
@@ -1567,7 +1599,7 @@ struct isl_apply_fold_data {
 	isl_union_pw_qpolynomial_fold *upwf;
 	isl_union_pw_qpolynomial_fold *res;
 	isl_map *map;
-	int tight;
+	isl_bool tight;
 };
 
 static isl_stat pw_qpolynomial_fold_apply(
@@ -1612,7 +1644,7 @@ static isl_stat map_apply(__isl_take isl_map *map, void *user)
 
 __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_take isl_union_pw_qpolynomial_fold *upwf, isl_bool *tight)
 {
 	isl_space *dim;
 	enum isl_fold type;
@@ -1624,7 +1656,7 @@ __isl_give isl_union_pw_qpolynomial_fold *isl_union_map_apply_union_pw_qpolynomi
 				isl_union_pw_qpolynomial_fold_get_space(upwf));
 
 	data.upwf = upwf;
-	data.tight = tight ? 1 : 0;
+	data.tight = tight ? isl_bool_true : isl_bool_false;
 	dim = isl_union_pw_qpolynomial_fold_get_space(upwf);
 	type = isl_union_pw_qpolynomial_fold_get_type(upwf);
 	data.res = isl_union_pw_qpolynomial_fold_zero(dim, type);
@@ -1647,7 +1679,7 @@ __isl_give isl_union_pw_qpolynomial_fold *isl_union_map_apply_union_pw_qpolynomi
 
 __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_take isl_union_pw_qpolynomial_fold *upwf, isl_bool *tight)
 {
 	return isl_union_map_apply_union_pw_qpolynomial_fold(uset, upwf, tight);
 }

diff  --git a/polly/lib/External/isl/isl_hash.c b/polly/lib/External/isl/isl_hash.c
index ca25d0d5851d..59cb06e85edd 100644
--- a/polly/lib/External/isl/isl_hash.c
+++ b/polly/lib/External/isl/isl_hash.c
@@ -8,7 +8,7 @@
  */
 
 #include <stdlib.h>
-#include <isl_hash_private.h>
+#include <isl/hash.h>
 #include <isl/ctx.h>
 #include "isl_config.h"
 
@@ -63,9 +63,9 @@ int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table,
 
 /* Dummy comparison function that always returns false.
  */
-static int no(const void *entry, const void *val)
+static isl_bool no(const void *entry, const void *val)
 {
-	return 0;
+	return isl_bool_false;
 }
 
 /* Extend "table" to twice its size.
@@ -148,31 +148,37 @@ void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table)
 	free(table);
 }
 
-/* A dummy entry that can be used to make a distinction between
- * a missing entry and an error condition.
- * It is used by isl_union_*_find_part_entry.
+/* A dummy entry that is used by isl_hash_table_find
+ * to make a distinction between a missing entry and an error condition.
  */
 static struct isl_hash_table_entry none = { 0, NULL };
 struct isl_hash_table_entry *isl_hash_table_entry_none = &none;
 
 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)
+			    struct isl_hash_table *table,
+			    uint32_t key_hash,
+			    isl_bool (*eq)(const void *entry, const void *val),
+			    const void *val, int reserve)
 {
 	size_t size;
 	uint32_t h, key_bits;
 
 	key_bits = isl_hash_bits(key_hash, table->bits);
 	size = 1 << table->bits;
-	for (h = key_bits; table->entries[h].data; h = (h+1) % size)
-		if (table->entries[h].hash == key_hash &&
-		    eq(table->entries[h].data, val))
+	for (h = key_bits; table->entries[h].data; h = (h+1) % size) {
+		isl_bool equal;
+
+		if (table->entries[h].hash != key_hash)
+			continue;
+		equal = eq(table->entries[h].data, val);
+		if (equal < 0)
+			return NULL;
+		if (equal)
 			return &table->entries[h];
+	}
 
 	if (!reserve)
-		return NULL;
+		return isl_hash_table_entry_none;
 
 	if (4 * table->n >= 3 * size) {
 		if (grow_table(ctx, table) < 0)

diff  --git a/polly/lib/External/isl/isl_hash_private.h b/polly/lib/External/isl/isl_hash_private.h
deleted file mode 100644
index c6b272ae49cd..000000000000
--- a/polly/lib/External/isl/isl_hash_private.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ISL_HASH_PRIVATE
-#define ISL_HASH_PRIVATE
-
-#include <isl/hash.h>
-
-extern struct isl_hash_table_entry *isl_hash_table_entry_none;
-
-#endif

diff  --git a/polly/lib/External/isl/isl_id.c b/polly/lib/External/isl/isl_id.c
index d5c7c7115792..982d9ebb547b 100644
--- a/polly/lib/External/isl/isl_id.c
+++ b/polly/lib/External/isl/isl_id.c
@@ -11,8 +11,8 @@
 #include <isl_ctx_private.h>
 #include <isl_id_private.h>
 
-#undef BASE
-#define BASE id
+#undef EL_BASE
+#define EL_BASE id
 
 #include <isl_list_templ.c>
 
@@ -81,19 +81,19 @@ struct isl_name_and_user {
 	void *user;
 };
 
-static int isl_id_has_name_and_user(const void *entry, const void *val)
+static isl_bool isl_id_has_name_and_user(const void *entry, const void *val)
 {
 	isl_id *id = (isl_id *)entry;
 	struct isl_name_and_user *nu = (struct isl_name_and_user *) val;
 
 	if (id->user != nu->user)
-		return 0;
+		return isl_bool_false;
 	if (id->name == nu->name)
-		return 1;
+		return isl_bool_true;
 	if (!id->name || !nu->name)
-		return 0;
+		return isl_bool_false;
 
-	return !strcmp(id->name, nu->name);
+	return isl_bool_ok(!strcmp(id->name, nu->name));
 }
 
 __isl_give isl_id *isl_id_alloc(isl_ctx *ctx, const char *name, void *user)
@@ -164,9 +164,9 @@ int isl_id_cmp(__isl_keep isl_id *id1, __isl_keep isl_id *id2)
 		return 1;
 }
 
-static int isl_id_eq(const void *entry, const void *name)
+static isl_bool isl_id_eq(const void *entry, const void *name)
 {
-	return entry == name;
+	return isl_bool_ok(entry == name);
 }
 
 uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id)
@@ -209,6 +209,8 @@ __isl_null isl_id *isl_id_free(__isl_take isl_id *id)
 	entry = isl_hash_table_find(id->ctx, &id->ctx->id_table, id->hash,
 					isl_id_eq, id, 0);
 	if (!entry)
+		return NULL;
+	if (entry == isl_hash_table_entry_none)
 		isl_die(id->ctx, isl_error_unknown,
 			"unable to find id", (void)0);
 	else
@@ -242,3 +244,63 @@ __isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p,
 	isl_printer_free(p);
 	return NULL;
 }
+
+/* Read an isl_id from "s" based on its name.
+ */
+__isl_give isl_id *isl_stream_read_id(__isl_keep isl_stream *s)
+{
+	struct isl_token *tok;
+	char *str;
+	isl_ctx *ctx;
+	isl_id *id;
+
+	if (!s)
+		return NULL;
+	tok = isl_stream_next_token(s);
+	if (!tok) {
+		isl_stream_error(s, NULL, "unexpected EOF");
+		return NULL;
+	}
+	ctx = isl_stream_get_ctx(s);
+	str = isl_token_get_str(ctx, tok);
+	isl_token_free(tok);
+	if (!str)
+		return NULL;
+	id = isl_id_alloc(ctx, str, NULL);
+	free(str);
+
+	return id;
+}
+
+/* Read an isl_id object from the string "str".
+ */
+__isl_give isl_id *isl_id_read_from_str(isl_ctx *ctx, const char *str)
+{
+	isl_id *id;
+	isl_stream *s = isl_stream_new_str(ctx, str);
+	if (!s)
+		return NULL;
+	id = isl_stream_read_id(s);
+	isl_stream_free(s);
+	return id;
+}
+
+/* Is "id1" (obviously) equal to "id2"?
+ *
+ * isl_id objects can be compared by pointer value, but
+ * isl_multi_*_plain_is_equal needs an isl_*_plain_is_equal.
+ */
+static isl_bool isl_id_plain_is_equal(__isl_keep isl_id *id1,
+	__isl_keep isl_id *id2)
+{
+	if (!id1 || !id2)
+		return isl_bool_error;
+	return id1 == id2;
+}
+
+#undef BASE
+#define BASE id
+
+#include <isl_multi_no_domain_templ.c>
+#include <isl_multi_no_explicit_domain.c>
+#include <isl_multi_templ.c>

diff  --git a/polly/lib/External/isl/isl_id_private.h b/polly/lib/External/isl/isl_id_private.h
index 1d903c8e59e8..3b053e87c202 100644
--- a/polly/lib/External/isl/isl_id_private.h
+++ b/polly/lib/External/isl/isl_id_private.h
@@ -11,6 +11,7 @@
 #define ISL_ID_PRIVATE_H
 
 #include <isl/id.h>
+#include <isl/stream.h>
 
 /* Represent a name and/or user pointer.
  *
@@ -35,7 +36,13 @@ struct isl_id {
 
 uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id);
 int isl_id_cmp(__isl_keep isl_id *id1, __isl_keep isl_id *id2);
+__isl_give isl_id *isl_stream_read_id(__isl_keep isl_stream *s);
 
 extern isl_id isl_id_none;
 
+#undef BASE
+#define BASE id
+
+#include <isl_multi_templ.h>
+
 #endif

diff  --git a/polly/lib/External/isl/isl_id_to_ast_expr.c b/polly/lib/External/isl/isl_id_to_ast_expr.c
index 1f1bbe3357a2..4bfa9530ab04 100644
--- a/polly/lib/External/isl/isl_id_to_ast_expr.c
+++ b/polly/lib/External/isl/isl_id_to_ast_expr.c
@@ -2,7 +2,7 @@
 #include <isl/id.h>
 #include <isl/ast.h>
 
-#define isl_id_is_equal(id1,id2)	id1 == id2
+#define isl_id_is_equal(id1,id2)	isl_bool_ok(id1 == id2)
 
 #define ISL_KEY		isl_id
 #define ISL_VAL		isl_ast_expr

diff  --git a/polly/lib/External/isl/isl_id_to_id.c b/polly/lib/External/isl/isl_id_to_id.c
index 95b2e81ecf3f..e92e8f63835c 100644
--- a/polly/lib/External/isl/isl_id_to_id.c
+++ b/polly/lib/External/isl/isl_id_to_id.c
@@ -1,7 +1,8 @@
+#include <isl/ctx.h>
 #include <isl/id_to_id.h>
 #include <isl/id.h>
 
-#define isl_id_is_equal(id1,id2)	id1 == id2
+#define isl_id_is_equal(id1,id2)	isl_bool_ok(id1 == id2)
 
 #define ISL_KEY		isl_id
 #define ISL_VAL		isl_id

diff  --git a/polly/lib/External/isl/isl_id_to_pw_aff.c b/polly/lib/External/isl/isl_id_to_pw_aff.c
index 927a044a8212..1ef27b5eaa79 100644
--- a/polly/lib/External/isl/isl_id_to_pw_aff.c
+++ b/polly/lib/External/isl/isl_id_to_pw_aff.c
@@ -2,7 +2,7 @@
 #include <isl/id.h>
 #include <isl/aff.h>
 
-#define isl_id_is_equal(id1,id2)	id1 == id2
+#define isl_id_is_equal(id1,id2)	isl_bool_ok(id1 == id2)
 
 #define ISL_KEY		isl_id
 #define ISL_VAL		isl_pw_aff

diff  --git a/polly/lib/External/isl/isl_ilp.c b/polly/lib/External/isl/isl_ilp.c
index fb2cda144333..bad23fbe6081 100644
--- a/polly/lib/External/isl/isl_ilp.c
+++ b/polly/lib/External/isl/isl_ilp.c
@@ -36,7 +36,7 @@ static __isl_give isl_basic_set *unit_box_base_points(
 {
 	int i, j, k;
 	struct isl_basic_set *unit_box = NULL;
-	unsigned total;
+	isl_size total;
 
 	if (!bset)
 		goto error;
@@ -47,7 +47,9 @@ static __isl_give isl_basic_set *unit_box_base_points(
 		return isl_basic_set_empty(space);
 	}
 
-	total = isl_basic_set_total_dim(bset);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
+		goto error;
 	unit_box = isl_basic_set_alloc_space(isl_basic_set_get_space(bset),
 					0, 0, bset->n_ineq);
 
@@ -107,9 +109,11 @@ static __isl_give isl_basic_set *add_bounds(__isl_take isl_basic_set *bset,
 	isl_int *f, isl_int l, isl_int u)
 {
 	int k;
-	unsigned total;
+	isl_size total;
 
-	total = isl_basic_set_total_dim(bset);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
+		return isl_basic_set_free(bset);
 	bset = isl_basic_set_extend_constraints(bset, 0, 2);
 
 	k = isl_basic_set_alloc_inequality(bset);
@@ -263,13 +267,15 @@ static enum isl_lp_result solve_ilp(__isl_keep isl_basic_set *bset,
 static enum isl_lp_result solve_ilp_with_eq(__isl_keep isl_basic_set *bset,
 	int max, isl_int *f, isl_int *opt, __isl_give isl_vec **sol_p)
 {
-	unsigned dim;
+	isl_size dim;
 	enum isl_lp_result res;
 	struct isl_mat *T = NULL;
 	struct isl_vec *v;
 
 	bset = isl_basic_set_copy(bset);
-	dim = isl_basic_set_total_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0)
+		goto error;
 	v = isl_vec_alloc(bset->ctx, 1 + dim);
 	if (!v)
 		goto error;
@@ -305,16 +311,14 @@ static enum isl_lp_result solve_ilp_with_eq(__isl_keep isl_basic_set *bset,
 enum isl_lp_result isl_basic_set_solve_ilp(__isl_keep isl_basic_set *bset,
 	int max, isl_int *f, isl_int *opt, __isl_give isl_vec **sol_p)
 {
-	unsigned dim;
+	isl_size dim;
 	enum isl_lp_result res;
 
-	if (!bset)
-		return isl_lp_error;
 	if (sol_p)
 		*sol_p = NULL;
 
-	isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0,
-		return isl_lp_error);
+	if (isl_basic_set_check_no_params(bset) < 0)
+		return isl_lp_error;
 
 	if (isl_basic_set_plain_is_empty(bset))
 		return isl_lp_empty;
@@ -322,7 +326,9 @@ enum isl_lp_result isl_basic_set_solve_ilp(__isl_keep isl_basic_set *bset,
 	if (bset->n_eq)
 		return solve_ilp_with_eq(bset, max, f, opt, sol_p);
 
-	dim = isl_basic_set_total_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0)
+		return isl_lp_error;
 
 	if (max)
 		isl_seq_neg(f, f, 1 + dim);
@@ -351,23 +357,6 @@ static enum isl_lp_result basic_set_opt(__isl_keep isl_basic_set *bset, int max,
 	return res;
 }
 
-static __isl_give isl_mat *extract_divs(__isl_keep isl_basic_set *bset)
-{
-	int i;
-	isl_ctx *ctx = isl_basic_set_get_ctx(bset);
-	isl_mat *div;
-
-	div = isl_mat_alloc(ctx, bset->n_div,
-			    1 + 1 + isl_basic_set_total_dim(bset));
-	if (!div)
-		return NULL;
-
-	for (i = 0; i < bset->n_div; ++i)
-		isl_seq_cpy(div->row[i], bset->div[i], div->n_col);
-
-	return div;
-}
-
 enum isl_lp_result isl_basic_set_opt(__isl_keep isl_basic_set *bset, int max,
 	__isl_keep isl_aff *obj, isl_int *opt)
 {
@@ -377,7 +366,7 @@ enum isl_lp_result isl_basic_set_opt(__isl_keep isl_basic_set *bset, int max,
 	isl_mat *bset_div = NULL;
 	isl_mat *div = NULL;
 	enum isl_lp_result res;
-	int bset_n_div, obj_n_div;
+	isl_size bset_n_div, obj_n_div;
 
 	if (!bset || !obj)
 		return isl_lp_error;
@@ -393,13 +382,15 @@ enum isl_lp_result isl_basic_set_opt(__isl_keep isl_basic_set *bset, int max,
 
 	bset_n_div = isl_basic_set_dim(bset, isl_dim_div);
 	obj_n_div = isl_aff_dim(obj, isl_dim_div);
+	if (bset_n_div < 0 || obj_n_div < 0)
+		return isl_lp_error;
 	if (bset_n_div == 0 && obj_n_div == 0)
 		return basic_set_opt(bset, max, obj, opt);
 
 	bset = isl_basic_set_copy(bset);
 	obj = isl_aff_copy(obj);
 
-	bset_div = extract_divs(bset);
+	bset_div = isl_basic_set_get_divs(bset);
 	exp1 = isl_alloc_array(ctx, int, bset_n_div);
 	exp2 = isl_alloc_array(ctx, int, obj_n_div);
 	if (!bset_div || (bset_n_div && !exp1) || (obj_n_div && !exp2))
@@ -787,13 +778,16 @@ __isl_give isl_val *isl_union_pw_aff_max_val(__isl_take isl_union_pw_aff *upa)
 static __isl_give isl_multi_val *isl_multi_union_pw_aff_opt_multi_val(
 	__isl_take isl_multi_union_pw_aff *mupa, int max)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_multi_val *mv;
 
+	n = isl_multi_union_pw_aff_size(mupa);
+	if (n < 0)
+		mupa = isl_multi_union_pw_aff_free(mupa);
 	if (!mupa)
 		return NULL;
 
-	n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
 	mv = isl_multi_val_zero(isl_multi_union_pw_aff_get_space(mupa));
 
 	for (i = 0; i < n; ++i) {
@@ -880,11 +874,8 @@ __isl_give isl_val *isl_basic_set_dim_max_val(__isl_take isl_basic_set *bset,
 	isl_aff *obj;
 	isl_val *v;
 
-	if (!bset)
-		return NULL;
-	if (pos < 0 || pos >= isl_basic_set_dim(bset, isl_dim_set))
-		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
-			"position out of bounds", goto error);
+	if (isl_basic_set_check_range(bset, isl_dim_set, pos, 1) < 0)
+		goto error;
 	ls = isl_local_space_from_space(isl_basic_set_get_space(bset));
 	obj = isl_aff_var_on_domain(ls, isl_dim_set, pos);
 	v = isl_basic_set_max_val(bset, obj);

diff  --git a/polly/lib/External/isl/isl_input.c b/polly/lib/External/isl/isl_input.c
index 950b40e83131..f9a95775035e 100644
--- a/polly/lib/External/isl/isl_input.c
+++ b/polly/lib/External/isl/isl_input.c
@@ -2,6 +2,7 @@
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  * Copyright 2010      INRIA Saclay
  * Copyright 2012-2013 Ecole Normale Superieure
+ * Copyright 2019      Cerebras Systems
  *
  * Use of this software is governed by the MIT license
  *
@@ -10,6 +11,7 @@
  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
  */
 
 #include <ctype.h>
@@ -17,6 +19,7 @@
 #include <string.h>
 #include <isl_ctx_private.h>
 #include <isl_map_private.h>
+#include <isl_id_private.h>
 #include <isl/set.h>
 #include <isl_seq.h>
 #include <isl_stream_private.h>
@@ -251,7 +254,30 @@ struct isl_val *isl_val_read_from_str(struct isl_ctx *ctx,
 	return val;
 }
 
-static int accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
+/* Perform an integer division on *f and
+ * an integer value read from the stream.
+ */
+static isl_stat int_div_by_cst(__isl_keep isl_stream *s, isl_int *f)
+{
+	struct isl_token *tok;
+
+	tok = next_token(s);
+	if (!tok || tok->type != ISL_TOKEN_VALUE) {
+		isl_stream_error(s, tok, "expecting constant value");
+		goto error;
+	}
+
+	isl_int_fdiv_q(*f, *f, tok->u.v);
+
+	isl_token_free(tok);
+
+	return isl_stat_ok;
+error:
+	isl_token_free(tok);
+	return isl_stat_error;
+}
+
+static isl_stat accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
 {
 	struct isl_token *tok;
 
@@ -268,10 +294,10 @@ static int accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
 	if (isl_stream_eat_if_available(s, '*'))
 		return accept_cst_factor(s, f);
 
-	return 0;
+	return isl_stat_ok;
 error:
 	isl_token_free(tok);
-	return -1;
+	return isl_stat_error;
 }
 
 /* Given an affine expression aff, return an affine expression
@@ -437,8 +463,24 @@ static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s,
 	return NULL;
 }
 
+/* Divide "pa" by an integer constant read from the stream.
+ */
+static __isl_give isl_pw_aff *pw_aff_div_by_cst(__isl_keep isl_stream *s,
+	__isl_take isl_pw_aff *pa)
+{
+	isl_int f;
+	isl_int_init(f);
+	isl_int_set_si(f, 1);
+	if (accept_cst_factor(s, &f) < 0)
+		pa = isl_pw_aff_free(pa);
+	pa = isl_pw_aff_scale_down(pa, f);
+	isl_int_clear(f);
+
+	return pa;
+}
+
 static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
-	__isl_take isl_space *dim, struct vars *v)
+	__isl_take isl_space *space, struct vars *v)
 {
 	struct isl_token *tok = NULL;
 	isl_pw_aff *res = NULL;
@@ -465,7 +507,7 @@ static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
 			goto error;
 		}
 
-		aff = isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(dim)));
+		aff = isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(space)));
 		if (!aff)
 			goto error;
 		isl_int_set_si(aff->v->el[2 + pos], 1);
@@ -473,12 +515,12 @@ static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
 		isl_token_free(tok);
 	} else if (tok->type == ISL_TOKEN_VALUE) {
 		if (isl_stream_eat_if_available(s, '*')) {
-			res = accept_affine_factor(s, isl_space_copy(dim), v);
+			res = accept_affine_factor(s, isl_space_copy(space), v);
 			res = isl_pw_aff_scale(res, tok->u.v);
 		} else {
 			isl_local_space *ls;
 			isl_aff *aff;
-			ls = isl_local_space_from_space(isl_space_copy(dim));
+			ls = isl_local_space_from_space(isl_space_copy(space));
 			aff = isl_aff_zero_on_domain(ls);
 			aff = isl_aff_add_constant(aff, tok->u.v);
 			res = isl_pw_aff_from_aff(aff);
@@ -487,7 +529,7 @@ static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
 	} else if (tok->type == '(') {
 		isl_token_free(tok);
 		tok = NULL;
-		res = accept_affine(s, isl_space_copy(dim), v);
+		res = accept_affine(s, isl_space_copy(space), v);
 		if (!res)
 			goto error;
 		if (isl_stream_eat(s, ')'))
@@ -495,18 +537,18 @@ static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
 	} else if (is_start_of_div(tok)) {
 		isl_stream_push_token(s, tok);
 		tok = NULL;
-		res = accept_div(s, isl_space_copy(dim), v);
+		res = accept_div(s, isl_space_copy(space), v);
 	} else if (tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX) {
 		isl_stream_push_token(s, tok);
 		tok = NULL;
-		res = accept_minmax(s, isl_space_copy(dim), v);
+		res = accept_minmax(s, isl_space_copy(space), v);
 	} else {
 		isl_stream_error(s, tok, "expecting factor");
 		goto error;
 	}
 	if (isl_stream_eat_if_available(s, '%') ||
 	    isl_stream_eat_if_available(s, ISL_TOKEN_MOD)) {
-		isl_space_free(dim);
+		isl_space_free(space);
 		return affine_mod(s, v, res);
 	}
 	if (isl_stream_eat_if_available(s, '*')) {
@@ -520,25 +562,18 @@ static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
 		res = isl_pw_aff_scale(res, f);
 		isl_int_clear(f);
 	}
-	if (isl_stream_eat_if_available(s, '/')) {
-		isl_int f;
-		isl_int_init(f);
-		isl_int_set_si(f, 1);
-		if (accept_cst_factor(s, &f) < 0) {
-			isl_int_clear(f);
-			goto error2;
-		}
-		res = isl_pw_aff_scale_down(res, f);
-		isl_int_clear(f);
-	}
+	if (isl_stream_eat_if_available(s, '/'))
+		res = pw_aff_div_by_cst(s, res);
+	if (isl_stream_eat_if_available(s, ISL_TOKEN_INT_DIV))
+		res = isl_pw_aff_floor(pw_aff_div_by_cst(s, res));
 
-	isl_space_free(dim);
+	isl_space_free(space);
 	return res;
 error:
 	isl_token_free(tok);
 error2:
 	isl_pw_aff_free(res);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -618,6 +653,10 @@ static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
 				if (!res)
 					goto error;
 			} else {
+				if (isl_stream_eat_if_available(s,
+							ISL_TOKEN_INT_DIV) &&
+				    int_div_by_cst(s, &tok->u.v) < 0)
+					goto error;
 				res = add_cst(res, tok->u.v);
 			}
 			sign = 1;
@@ -704,7 +743,7 @@ static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
 static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s,
 	__isl_take isl_map *cond, struct vars *v, int rational)
 {
-	isl_space *dim;
+	isl_space *space;
 	isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL, *pa_cond;
 
 	if (!cond)
@@ -713,17 +752,17 @@ static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s,
 	if (isl_stream_eat(s, '?'))
 		goto error;
 
-	dim = isl_space_wrap(isl_map_get_space(cond));
-	pwaff1 = accept_extended_affine(s, dim, v, rational);
+	space = isl_space_wrap(isl_map_get_space(cond));
+	pwaff1 = accept_extended_affine(s, space, v, rational);
 	if (!pwaff1)
 		goto error;
 
 	if (isl_stream_eat(s, ':'))
 		goto error;
 
-	dim = isl_pw_aff_get_domain_space(pwaff1);
-	pwaff2 = accept_extended_affine(s, dim, v, rational);
-	if (!pwaff1)
+	space = isl_pw_aff_get_domain_space(pwaff1);
+	pwaff2 = accept_extended_affine(s, space, v, rational);
+	if (!pwaff2)
 		goto error;
 
 	pa_cond = isl_set_indicator_function(isl_map_wrap(cond));
@@ -753,7 +792,7 @@ static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col)
 /* Push a token encapsulating "pa" onto "s", with the given
  * line and column.
  */
-static int push_aff(__isl_keep isl_stream *s, int line, int col,
+static isl_stat push_aff(__isl_keep isl_stream *s, int line, int col,
 	__isl_take isl_pw_aff *pa)
 {
 	struct isl_token *tok;
@@ -765,10 +804,27 @@ static int push_aff(__isl_keep isl_stream *s, int line, int col,
 	tok->u.pwaff = pa;
 	isl_stream_push_token(s, tok);
 
-	return 0;
+	return isl_stat_ok;
 error:
 	isl_pw_aff_free(pa);
-	return -1;
+	return isl_stat_error;
+}
+
+/* Is the next token a comparison operator?
+ */
+static int next_is_comparator(__isl_keep isl_stream *s)
+{
+	int is_comp;
+	struct isl_token *tok;
+
+	tok = isl_stream_next_token(s);
+	if (!tok)
+		return 0;
+
+	is_comp = is_comparator(tok);
+	isl_stream_push_token(s, tok);
+
+	return is_comp;
 }
 
 /* Accept an affine expression that may involve ternary operators.
@@ -783,9 +839,7 @@ static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
 	isl_space *space;
 	isl_map *cond;
 	isl_pw_aff *pwaff;
-	struct isl_token *tok;
 	int line = -1, col = -1;
-	int is_comp;
 
 	set_current_line_col(s, &line, &col);
 
@@ -794,14 +848,7 @@ static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
 		pwaff = isl_pw_aff_set_rational(pwaff);
 	if (!pwaff)
 		return NULL;
-
-	tok = isl_stream_next_token(s);
-	if (!tok)
-		return isl_pw_aff_free(pwaff);
-
-	is_comp = is_comparator(tok);
-	isl_stream_push_token(s, tok);
-	if (!is_comp)
+	if (!next_is_comparator(s))
 		return pwaff;
 
 	space = isl_pw_aff_get_domain_space(pwaff);
@@ -822,17 +869,23 @@ static __isl_give isl_map *read_var_def(__isl_keep isl_stream *s,
 	int rational)
 {
 	isl_pw_aff *def;
-	int pos;
+	isl_size pos;
 	isl_map *def_map;
 
 	if (type == isl_dim_param)
 		pos = isl_map_dim(map, isl_dim_param);
 	else {
 		pos = isl_map_dim(map, isl_dim_in);
-		if (type == isl_dim_out)
-			pos += isl_map_dim(map, isl_dim_out);
+		if (type == isl_dim_out) {
+			isl_size n_out = isl_map_dim(map, isl_dim_out);
+			if (pos < 0 || n_out < 0)
+				return isl_map_free(map);
+			pos += n_out;
+		}
 		type = isl_dim_in;
 	}
+	if (pos < 0)
+		return isl_map_free(map);
 	--pos;
 
 	def = accept_extended_affine(s, isl_space_wrap(isl_map_get_space(map)),
@@ -954,6 +1007,25 @@ static int next_is_tuple(__isl_keep isl_stream *s)
 	return is_tuple;
 }
 
+/* Does the next token mark the end of a tuple element?
+ */
+static int next_is_end_tuple_element(__isl_keep isl_stream *s)
+{
+	return isl_stream_next_token_is(s, ',') ||
+	    isl_stream_next_token_is(s, ']');
+}
+
+/* Is the next token one that necessarily forms the start of a condition?
+ */
+static int next_is_condition_start(__isl_keep isl_stream *s)
+{
+	return isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) ||
+	    isl_stream_next_token_is(s, ISL_TOKEN_NOT) ||
+	    isl_stream_next_token_is(s, ISL_TOKEN_TRUE) ||
+	    isl_stream_next_token_is(s, ISL_TOKEN_FALSE) ||
+	    isl_stream_next_token_is(s, ISL_TOKEN_MAP);
+}
+
 /* Is "pa" an expression in term of earlier dimensions?
  * The alternative is that the dimension is defined to be equal to itself,
  * meaning that it has a universe domain and an expression that depends
@@ -961,35 +1033,36 @@ static int next_is_tuple(__isl_keep isl_stream *s)
  * of "n" expressions.  The final dimensions of "pa" correspond to
  * these "n" expressions.
  */
-static int pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n)
+static isl_bool pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n)
 {
 	isl_aff *aff;
 
 	if (!pa)
-		return -1;
+		return isl_bool_error;
 	if (pa->n != 1)
-		return 1;
+		return isl_bool_true;
 	if (!isl_set_plain_is_universe(pa->p[0].set))
-		return 1;
+		return isl_bool_true;
 
 	aff = pa->p[0].aff;
 	if (isl_int_is_zero(aff->v->el[aff->v->size - n + i]))
-		return 1;
-	return 0;
+		return isl_bool_true;
+	return isl_bool_false;
 }
 
 /* Does the tuple contain any dimensions that are defined
  * in terms of earlier dimensions?
  */
-static int tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple)
+static isl_bool tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple)
 {
-	int i, n;
-	int has_expr = 0;
+	int i;
+	isl_size n;
+	isl_bool has_expr = isl_bool_false;
 	isl_pw_aff *pa;
 
-	if (!tuple)
-		return -1;
 	n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
+	if (n < 0)
+		return isl_bool_error;
 	for (i = 0; i < n; ++i) {
 		pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
 		has_expr = pw_aff_is_expr(pa, i, n);
@@ -1024,18 +1097,221 @@ static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space,
 	return space;
 }
 
+/* Construct an isl_pw_aff defined on a "space" (with v->n variables)
+ * that is equal to the last of those variables.
+ */
+static __isl_give isl_pw_aff *identity_tuple_el_on_space(
+	__isl_take isl_space *space, struct vars *v)
+{
+	isl_aff *aff;
+
+	aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n - 1, 1);
+	return isl_pw_aff_from_aff(aff);
+}
+
+/* Construct an isl_pw_aff defined on the domain space of "pa"
+ * that is equal to the last variable in "v".
+ *
+ * That is, if D is the domain space of "pa", then construct
+ *
+ *	D[..., i] -> i.
+ */
+static __isl_give isl_pw_aff *init_range(__isl_keep isl_pw_aff *pa,
+	struct vars *v)
+{
+	isl_space *space;
+
+	space = isl_pw_aff_get_domain_space(pa);
+	return identity_tuple_el_on_space(space, v);
+}
+
+/* Impose the lower bound "lower" on the variable represented by "range_pa".
+ *
+ * In particular, "range_pa" is of the form
+ *
+ *	D[..., i] -> i : C
+ *
+ * with D also the domains space of "lower' and "C" some constraints.
+ *
+ * Return the expression
+ *
+ *	D[..., i] -> i : C and i >= lower
+ */
+static __isl_give isl_pw_aff *set_lower(__isl_take isl_pw_aff *range_pa,
+	__isl_take isl_pw_aff *lower)
+{
+	isl_set *range;
+
+	range = isl_pw_aff_ge_set(isl_pw_aff_copy(range_pa), lower);
+	return isl_pw_aff_intersect_domain(range_pa, range);
+}
+
+/* Impose the upper bound "upper" on the variable represented by "range_pa".
+ *
+ * In particular, "range_pa" is of the form
+ *
+ *	D[..., i] -> i : C
+ *
+ * with D also the domains space of "upper' and "C" some constraints.
+ *
+ * Return the expression
+ *
+ *	D[..., i] -> i : C and i <= upper
+ */
+static __isl_give isl_pw_aff *set_upper(__isl_take isl_pw_aff *range_pa,
+	__isl_take isl_pw_aff *upper)
+{
+	isl_set *range;
+
+	range = isl_pw_aff_le_set(isl_pw_aff_copy(range_pa), upper);
+	return isl_pw_aff_intersect_domain(range_pa, range);
+}
+
+/* Construct a piecewise affine expression corresponding
+ * to the last variable in "v" that is greater than or equal to "pa".
+ *
+ * In particular, if D is the domain space of "pa",
+ * then construct the expression
+ *
+ *	D[..., i] -> i,
+ *
+ * impose lower bound "pa" and return
+ *
+ *	D[..., i] -> i : i >= pa
+ */
+static __isl_give isl_pw_aff *construct_lower(__isl_take isl_pw_aff *pa,
+	struct vars *v)
+{
+	return set_lower(init_range(pa, v), pa);
+}
+
+/* Construct a piecewise affine expression corresponding
+ * to the last variable in "v" that is smaller than or equal to "pa".
+ *
+ * In particular, if D is the domain space of "pa",
+ * then construct the expression
+ *
+ *	D[..., i] -> i,
+ *
+ * impose lower bound "pa" and return
+ *
+ *	D[..., i] -> i : i <= pa
+ */
+static __isl_give isl_pw_aff *construct_upper(__isl_take isl_pw_aff *pa,
+	struct vars *v)
+{
+	return set_upper(init_range(pa, v), pa);
+}
+
+/* Construct a piecewise affine expression corresponding
+ * to the last variable in "v" that ranges between "pa" and "pa2".
+ *
+ * In particular, if D is the domain space of "pa" (and "pa2"),
+ * then construct the expression
+ *
+ *	D[..., i] -> i,
+ *
+ * impose lower bound "pa" and upper bound "pa2" and return
+ *
+ *	D[..., i] -> i : pa <= i <= pa2
+ */
+static __isl_give isl_pw_aff *construct_range(__isl_take isl_pw_aff *pa,
+	__isl_take isl_pw_aff *pa2, struct vars *v)
+{
+	return set_upper(set_lower(init_range(pa, v), pa), pa2);
+}
+
+static int resolve_paren_expr(__isl_keep isl_stream *s,
+	struct vars *v, __isl_take isl_map *map, int rational);
+
+/* Given that the (piecewise) affine expression "pa"
+ * has just been parsed, followed by a colon,
+ * continue parsing as part of a piecewise affine expression.
+ *
+ * In particular, check if the colon is followed by a condition.
+ * If so, parse the conditions(a) on "pa" and include them in the domain.
+ * Otherwise, if the colon is followed by another (piecewise) affine expression
+ * then consider the two expressions as endpoints of a range of values and
+ * return a piecewise affine expression that takes values in that range.
+ * Note that an affine expression followed by a comparison operator
+ * is considered to be part of a condition.
+ * If the colon is not followed by anything (inside the tuple element),
+ * then consider "pa" as a lower bound on a range of values without upper bound
+ * and return a piecewise affine expression that takes values in that range.
+ */
+static __isl_give isl_pw_aff *update_piecewise_affine_colon(
+	__isl_take isl_pw_aff *pa, __isl_keep isl_stream *s,
+	struct vars *v, int rational)
+{
+	isl_space *dom_space;
+	isl_map *map;
+
+	dom_space = isl_pw_aff_get_domain_space(pa);
+	map = isl_map_universe(isl_space_from_domain(dom_space));
+
+	if (isl_stream_next_token_is(s, '('))
+		if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
+			goto error;
+	if (next_is_end_tuple_element(s)) {
+		isl_map_free(map);
+		return construct_lower(pa, v);
+	}
+	if (!next_is_condition_start(s)) {
+		int line = -1, col = -1;
+		isl_space *space;
+		isl_pw_aff *pa2;
+
+		set_current_line_col(s, &line, &col);
+		space = isl_space_wrap(isl_map_get_space(map));
+		pa2 = accept_affine(s, space, v);
+		if (rational)
+			pa2 = isl_pw_aff_set_rational(pa2);
+		if (!next_is_comparator(s)) {
+			isl_map_free(map);
+			pa2 = isl_pw_aff_domain_factor_domain(pa2);
+			return construct_range(pa, pa2, v);
+		}
+		if (push_aff(s, line, col, pa2) < 0)
+			goto error;
+	}
+
+	map = read_formula(s, v, map, rational);
+	pa = isl_pw_aff_intersect_domain(pa, isl_map_domain(map));
+
+	return pa;
+error:
+	isl_map_free(map);
+	isl_pw_aff_free(pa);
+	return NULL;
+}
+
 /* Accept a piecewise affine expression.
  *
  * At the outer level, the piecewise affine expression may be of the form
  *
  *	aff1 : condition1; aff2 : conditions2; ...
  *
+ * or one of
+ *
+ *	aff :
+ *	aff1 : aff2
+ *	: aff
+ *	:
+ *
  * or simply
  *
  *	aff
  *
  * each of the affine expressions may in turn include ternary operators.
  *
+ * If the first token is a colon, then the expression must be
+ * ":" or ": aff2", depending on whether anything follows the colon
+ * inside the tuple element.
+ * The first is considered to represent an arbitrary value.
+ * The second is considered to represent a range of values
+ * with the given upper bound and no lower bound.
+ *
  * There may be parentheses around some subexpression of "aff1"
  * around "aff1" itself, around "aff1 : condition1" and/or
  * around the entire piecewise affine expression.
@@ -1051,6 +1327,13 @@ static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s,
 	isl_pw_aff *res;
 	isl_space *res_space;
 
+	if (isl_stream_eat_if_available(s, ':')) {
+		if (next_is_end_tuple_element(s))
+			return identity_tuple_el_on_space(space, v);
+		else
+			return construct_upper(accept_affine(s, space, v), v);
+	}
+
 	res_space = isl_space_from_domain(isl_space_copy(space));
 	res_space = isl_space_add_dims(res_space, isl_dim_out, 1);
 	res = isl_pw_aff_empty(res_space);
@@ -1074,15 +1357,8 @@ static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s,
 			pa = accept_extended_affine(s, isl_space_copy(space),
 							v, rational);
 		}
-		if (isl_stream_eat_if_available(s, ':')) {
-			isl_space *dom_space;
-			isl_set *dom;
-
-			dom_space = isl_pw_aff_get_domain_space(pa);
-			dom = isl_set_universe(dom_space);
-			dom = read_formula(s, v, dom, rational);
-			pa = isl_pw_aff_intersect_domain(pa, dom);
-		}
+		if (isl_stream_eat_if_available(s, ':'))
+			pa = update_piecewise_affine_colon(pa, s, v, rational);
 
 		res = isl_pw_aff_union_add(res, pa);
 
@@ -1114,9 +1390,7 @@ static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s,
 	space = isl_space_wrap(isl_space_alloc(s->ctx, 0, v->n, 0));
 
 	def = accept_piecewise_affine(s, space, v, rational);
-
-	space = isl_space_set_alloc(s->ctx, 0, v->n);
-	def = isl_pw_aff_reset_domain_space(def, space);
+	def = isl_pw_aff_domain_factor_domain(def);
 
 	return def;
 }
@@ -1229,12 +1503,9 @@ static __isl_give isl_space *read_tuple_space(__isl_keep isl_stream *s,
 static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v)
 {
 	isl_space *space;
-	isl_aff *aff;
 
 	space = isl_space_set_alloc(v->ctx, 0, v->n);
-	aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
-	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n - 1, 1);
-	return isl_pw_aff_from_aff(aff);
+	return identity_tuple_el_on_space(space, v);
 }
 
 /* This function is called for each element in a tuple inside read_tuple.
@@ -1275,7 +1546,10 @@ static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s,
 		isl_token_free(tok);
 		pa = identity_tuple_el(v);
 	} else if (new_name) {
-		int pos = isl_space_dim(space, isl_dim_out) - 1;
+		isl_size pos = isl_space_dim(space, isl_dim_out);
+		if (pos < 0)
+			goto error;
+		pos -= 1;
 		space = space_set_dim_name(space, pos, v->v->name);
 		isl_token_free(tok);
 		if (isl_stream_eat_if_available(s, '='))
@@ -1318,7 +1592,8 @@ static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s,
 static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s,
 	struct vars *v, int rational, int comma)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_pw_aff_list *list;
 
@@ -1327,6 +1602,8 @@ static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s,
 	space = read_tuple_space(s, v, space, rational, comma,
 				&read_tuple_pw_aff_el, &list);
 	n = isl_space_dim(space, isl_dim_set);
+	if (n < 0)
+		space = isl_space_free(space);
 	for (i = 0; i + 1 < n; ++i) {
 		isl_pw_aff *pa;
 
@@ -1350,14 +1627,15 @@ static __isl_give isl_map *map_from_tuple(__isl_take isl_multi_pw_aff *tuple,
 	__isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
 	int rational)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_space *space = NULL;
 
-	if (!map || !tuple)
+	n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
+	if (!map || n < 0)
 		goto error;
 	ctx = isl_multi_pw_aff_get_ctx(tuple);
-	n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
 	space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
 	if (!space)
 		goto error;
@@ -1463,14 +1741,14 @@ static __isl_give isl_set *list_cmp(__isl_keep isl_set *set, int type,
 	__isl_take isl_pw_aff_list *left, __isl_take isl_pw_aff_list *right)
 {
 	isl_space *space;
-	int n;
+	isl_size n;
 	isl_multi_pw_aff *mpa1, *mpa2;
 
-	if (!set || !left || !right)
+	n = isl_pw_aff_list_n_pw_aff(left);
+	if (!set || n < 0 || !right)
 		goto error;
 
 	space = isl_set_get_space(set);
-	n = isl_pw_aff_list_n_pw_aff(left);
 	space = isl_space_from_domain(space);
 	space = isl_space_add_dims(space, isl_dim_out, n);
 	mpa1 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), left);
@@ -1575,7 +1853,7 @@ static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
 	struct isl_token *tok;
 	int type;
 	isl_pw_aff_list *list1 = NULL, *list2 = NULL;
-	int n1, n2;
+	isl_size n1, n2;
 	isl_set *set;
 
 	set = isl_map_wrap(map);
@@ -1593,10 +1871,10 @@ static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
 	isl_token_free(tok);
 	for (;;) {
 		list2 = accept_affine_list(s, isl_set_get_space(set), v);
-		if (!list2)
-			goto error;
 		n1 = isl_pw_aff_list_n_pw_aff(list1);
 		n2 = isl_pw_aff_list_n_pw_aff(list2);
+		if (n1 < 0 || n2 < 0)
+			goto error;
 		if (is_list_comparator_type(type) && n1 != n2) {
 			isl_stream_error(s, NULL,
 					"list arguments not of same size");
@@ -1607,12 +1885,9 @@ static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
 		isl_pw_aff_list_free(list1);
 		list1 = list2;
 
-		tok = isl_stream_next_token(s);
-		if (!is_comparator(tok)) {
-			if (tok)
-				isl_stream_push_token(s, tok);
+		if (!next_is_comparator(s))
 			break;
-		}
+		tok = isl_stream_next_token(s);
 		type = tok->type;
 		isl_token_free(tok);
 	}
@@ -1670,6 +1945,7 @@ static int resolve_paren_expr(__isl_keep isl_stream *s,
 	struct vars *v, __isl_take isl_map *map, int rational)
 {
 	struct isl_token *tok, *tok2;
+	int has_paren;
 	int line, col;
 	isl_pw_aff *pwaff;
 
@@ -1681,11 +1957,7 @@ static int resolve_paren_expr(__isl_keep isl_stream *s,
 		if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
 			goto error;
 
-	if (isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) ||
-	    isl_stream_next_token_is(s, ISL_TOKEN_NOT) ||
-	    isl_stream_next_token_is(s, ISL_TOKEN_TRUE) ||
-	    isl_stream_next_token_is(s, ISL_TOKEN_FALSE) ||
-	    isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
+	if (next_is_condition_start(s)) {
 		map = read_formula(s, v, map, rational);
 		if (isl_stream_eat(s, ')'))
 			goto error;
@@ -1706,21 +1978,17 @@ static int resolve_paren_expr(__isl_keep isl_stream *s,
 	if (!pwaff)
 		goto error;
 
-	tok2 = isl_token_new(s->ctx, line, col, 0);
-	if (!tok2)
-		goto error2;
-	tok2->type = ISL_TOKEN_AFF;
-	tok2->u.pwaff = pwaff;
+	has_paren = isl_stream_eat_if_available(s, ')');
 
-	if (isl_stream_eat_if_available(s, ')')) {
-		isl_stream_push_token(s, tok2);
+	if (push_aff(s, line, col, pwaff) < 0)
+		goto error;
+
+	if (has_paren) {
 		isl_token_free(tok);
 		isl_map_free(map);
 		return 0;
 	}
 
-	isl_stream_push_token(s, tok2);
-
 	map = read_formula(s, v, map, rational);
 	if (isl_stream_eat(s, ')'))
 		goto error;
@@ -1730,8 +1998,6 @@ static int resolve_paren_expr(__isl_keep isl_stream *s,
 	isl_stream_push_token(s, tok);
 
 	return 0;
-error2:
-	isl_pw_aff_free(pwaff);
 error:
 	isl_token_free(tok);
 	isl_map_free(map);
@@ -1860,24 +2126,30 @@ static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
 	return res;
 }
 
-static int polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
+static isl_size polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
 {
-	if (pos < isl_basic_map_dim(bmap, isl_dim_out))
-		return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
-			   isl_basic_map_dim(bmap, isl_dim_in) + pos;
-	pos -= isl_basic_map_dim(bmap, isl_dim_out);
+	isl_size n_out, n_in, n_param, n_div;
+
+	n_param = isl_basic_map_dim(bmap, isl_dim_param);
+	n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
+		return isl_size_error;
 
-	if (pos < isl_basic_map_dim(bmap, isl_dim_in))
-		return 1 + isl_basic_map_dim(bmap, isl_dim_param) + pos;
-	pos -= isl_basic_map_dim(bmap, isl_dim_in);
+	if (pos < n_out)
+		return 1 + n_param + n_in + pos;
+	pos -= n_out;
 
-	if (pos < isl_basic_map_dim(bmap, isl_dim_div))
-		return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
-			   isl_basic_map_dim(bmap, isl_dim_in) +
-			   isl_basic_map_dim(bmap, isl_dim_out) + pos;
-	pos -= isl_basic_map_dim(bmap, isl_dim_div);
+	if (pos < n_in)
+		return 1 + n_param + pos;
+	pos -= n_in;
 
-	if (pos < isl_basic_map_dim(bmap, isl_dim_param))
+	if (pos < n_div)
+		return 1 + n_param + n_in + n_out + pos;
+	pos -= n_div;
+
+	if (pos < n_param)
 		return 1 + pos;
 
 	return 0;
@@ -1891,6 +2163,7 @@ static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
 	int type;
 	int k;
 	isl_int *c;
+	isl_size total;
 
 	if (!bmap)
 		return NULL;
@@ -1922,8 +2195,11 @@ static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
 	if (k < 0)
 		goto error;
 
-	for (j = 0; j < 1 + isl_basic_map_total_dim(bmap); ++j) {
-		int pos;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
+	for (j = 0; j < 1 + total; ++j) {
+		isl_size pos;
 		tok = isl_stream_next_token(s);
 		if (!tok || tok->type != ISL_TOKEN_VALUE) {
 			isl_stream_error(s, tok, "expecting coefficient");
@@ -1938,8 +2214,11 @@ static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
 			goto error;
 		}
 		pos = polylib_pos_to_isl_pos(bmap, j);
-		isl_int_set(c[pos], tok->u.v);
+		if (pos >= 0)
+			isl_int_set(c[pos], tok->u.v);
 		isl_token_free(tok);
+		if (pos < 0)
+			return isl_basic_map_free(bmap);
 	}
 
 	return bmap;
@@ -3179,11 +3458,13 @@ __isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s)
 {
 	isl_aff *aff;
 	isl_multi_aff *ma;
+	isl_size dim;
 
 	ma = isl_stream_read_multi_aff(s);
-	if (!ma)
-		return NULL;
-	if (isl_multi_aff_dim(ma, isl_dim_out) != 1)
+	dim = isl_multi_aff_dim(ma, isl_dim_out);
+	if (dim < 0)
+		goto error;
+	if (dim != 1)
 		isl_die(s->ctx, isl_error_invalid,
 			"expecting single affine expression",
 			goto error);
@@ -3314,12 +3595,15 @@ __isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
 static __isl_give isl_multi_pw_aff *extract_mpa_from_tuple(
 	__isl_take isl_space *dom_space, __isl_keep isl_multi_pw_aff *tuple)
 {
-	int dim, i, n;
+	int i;
+	isl_size dim, n;
 	isl_space *space;
 	isl_multi_pw_aff *mpa;
 
 	n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
 	dim = isl_space_dim(dom_space, isl_dim_all);
+	if (n < 0 || dim < 0)
+		dom_space = isl_space_free(dom_space);
 	space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
 	space = isl_space_align_params(space, isl_space_copy(dom_space));
 	if (!isl_space_is_params(dom_space))
@@ -3380,13 +3664,15 @@ static __isl_give isl_pw_multi_aff *read_conditional_multi_aff(
 		if (!tuple)
 			goto error;
 	}
+	mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
+	isl_multi_pw_aff_free(tuple);
+	if (!mpa)
+		dom = isl_set_free(dom);
 
 	dom = read_optional_formula(s, dom, v, 0);
 
 	vars_drop(v, v->n - n);
 
-	mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
-	isl_multi_pw_aff_free(tuple);
 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
 	pma = isl_pw_multi_aff_intersect_domain(pma, dom);
 
@@ -3396,18 +3682,18 @@ static __isl_give isl_pw_multi_aff *read_conditional_multi_aff(
 	return NULL;
 }
 
-/* Read an isl_pw_multi_aff from "s".
+/* Read an isl_union_pw_multi_aff from "s".
  *
  * In particular, first read the parameters and then read a sequence
- * of one or more tuples of affine expressions with optional conditions and
+ * of zero or more tuples of affine expressions with optional conditions and
  * add them up.
  */
-__isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
+__isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
 	__isl_keep isl_stream *s)
 {
 	struct vars *v;
 	isl_set *dom;
-	isl_pw_multi_aff *pma = NULL;
+	isl_union_pw_multi_aff *upma = NULL;
 
 	v = vars_new(s->ctx);
 	if (!v)
@@ -3422,30 +3708,57 @@ __isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
 	if (isl_stream_eat(s, '{'))
 		goto error;
 
-	pma = read_conditional_multi_aff(s, isl_set_copy(dom), v);
+	upma = isl_union_pw_multi_aff_empty(isl_set_get_space(dom));
 
-	while (isl_stream_eat_if_available(s, ';')) {
-		isl_pw_multi_aff *pma2;
+	do {
+		isl_pw_multi_aff *pma;
+		isl_union_pw_multi_aff *upma2;
+
+		if (isl_stream_next_token_is(s, '}'))
+			break;
 
-		pma2 = read_conditional_multi_aff(s, isl_set_copy(dom), v);
-		pma = isl_pw_multi_aff_union_add(pma, pma2);
-		if (!pma)
+		pma = read_conditional_multi_aff(s, isl_set_copy(dom), v);
+		upma2 = isl_union_pw_multi_aff_from_pw_multi_aff(pma);
+		upma = isl_union_pw_multi_aff_union_add(upma, upma2);
+		if (!upma)
 			goto error;
-	}
+	} while (isl_stream_eat_if_available(s, ';'));
 
 	if (isl_stream_eat(s, '}'))
 		goto error;
 
 	isl_set_free(dom);
 	vars_free(v);
-	return pma;
+	return upma;
 error:
-	isl_pw_multi_aff_free(pma);
+	isl_union_pw_multi_aff_free(upma);
 	isl_set_free(dom);
 	vars_free(v);
 	return NULL;
 }
 
+/* Read an isl_pw_multi_aff from "s".
+ *
+ * Read a more generic isl_union_pw_multi_aff first and
+ * then check that the result lives in a single space.
+ */
+__isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
+	__isl_keep isl_stream *s)
+{
+	isl_bool single_space;
+	isl_union_pw_multi_aff *upma;
+
+	upma = isl_stream_read_union_pw_multi_aff(s);
+	single_space = isl_union_pw_multi_aff_isa_pw_multi_aff(upma);
+	if (single_space < 0)
+		upma = isl_union_pw_multi_aff_free(upma);
+	else if (!single_space)
+		isl_die(s->ctx, isl_error_invalid,
+			"expecting expression in single space",
+			upma = isl_union_pw_multi_aff_free(upma));
+	return isl_union_pw_multi_aff_as_pw_multi_aff(upma);
+}
+
 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
 	const char *str)
 {
@@ -3458,33 +3771,6 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
 	return pma;
 }
 
-/* Read an isl_union_pw_multi_aff from "s".
- * We currently read a generic object and if it turns out to be a set or
- * a map, we convert that to an isl_union_pw_multi_aff.
- * It would be more efficient if we were to construct
- * the isl_union_pw_multi_aff directly.
- */
-__isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
-	__isl_keep isl_stream *s)
-{
-	struct isl_obj obj;
-
-	obj = obj_read(s);
-	if (!obj.v)
-		return NULL;
-
-	if (obj.type == isl_obj_map || obj.type == isl_obj_set)
-		obj = to_union(s->ctx, obj);
-	if (obj.type == isl_obj_union_map)
-		return isl_union_pw_multi_aff_from_union_map(obj.v);
-	if (obj.type == isl_obj_union_set)
-		return isl_union_pw_multi_aff_from_union_set(obj.v);
-
-	obj.type->free(obj.v);
-	isl_die(s->ctx, isl_error_invalid, "unexpected object type",
-		return NULL);
-}
-
 /* Read an isl_union_pw_multi_aff from "str".
  */
 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
@@ -3525,85 +3811,15 @@ static __isl_give isl_aff *aff_from_pw_aff(__isl_take isl_pw_aff *pa)
 	return NULL;
 }
 
-/* This function is called for each element in a tuple inside
- * isl_stream_read_multi_val.
- * Read an isl_val from "s" and add it to *list.
- */
-static __isl_give isl_space *read_val_el(__isl_keep isl_stream *s,
-	struct vars *v, __isl_take isl_space *space, int rational, void *user)
-{
-	isl_val_list **list = (isl_val_list **) user;
-	isl_val *val;
-
-	val = isl_stream_read_val(s);
-	*list = isl_val_list_add(*list, val);
-	if (!*list)
-		return isl_space_free(space);
-
-	return space;
-}
-
-/* Read an isl_multi_val from "s".
- *
- * We first read a tuple space, collecting the element values in a list.
- * Then we create an isl_multi_val from the space and the isl_val_list.
- */
-__isl_give isl_multi_val *isl_stream_read_multi_val(__isl_keep isl_stream *s)
-{
-	struct vars *v;
-	isl_set *dom = NULL;
-	isl_space *space;
-	isl_multi_val *mv = NULL;
-	isl_val_list *list;
-
-	v = vars_new(s->ctx);
-	if (!v)
-		return NULL;
-
-	dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
-	if (next_is_tuple(s)) {
-		dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
-		if (isl_stream_eat(s, ISL_TOKEN_TO))
-			goto error;
-	}
-	if (!isl_set_plain_is_universe(dom))
-		isl_die(s->ctx, isl_error_invalid,
-			"expecting universe parameter domain", goto error);
-	if (isl_stream_eat(s, '{'))
-		goto error;
-
-	space = isl_set_get_space(dom);
+#undef BASE
+#define BASE val
 
-	list = isl_val_list_alloc(s->ctx, 0);
-	space = read_tuple_space(s, v, space, 1, 0, &read_val_el, &list);
-	mv = isl_multi_val_from_val_list(space, list);
+#include <isl_multi_read_no_explicit_domain_templ.c>
 
-	if (isl_stream_eat(s, '}'))
-		goto error;
+#undef BASE
+#define BASE id
 
-	vars_free(v);
-	isl_set_free(dom);
-	return mv;
-error:
-	vars_free(v);
-	isl_set_free(dom);
-	isl_multi_val_free(mv);
-	return NULL;
-}
-
-/* Read an isl_multi_val from "str".
- */
-__isl_give isl_multi_val *isl_multi_val_read_from_str(isl_ctx *ctx,
-	const char *str)
-{
-	isl_multi_val *mv;
-	isl_stream *s = isl_stream_new_str(ctx, str);
-	if (!s)
-		return NULL;
-	mv = isl_stream_read_multi_val(s);
-	isl_stream_free(s);
-	return mv;
-}
+#include <isl_multi_read_no_explicit_domain_templ.c>
 
 /* Read a multi-affine expression from "s".
  * If the multi-affine expression has a domain, then the tuple
@@ -3618,7 +3834,8 @@ __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
 	struct vars *v;
 	isl_set *dom = NULL;
 	isl_multi_pw_aff *tuple = NULL;
-	int dim, i, n;
+	int i;
+	isl_size dim, n;
 	isl_space *space, *dom_space;
 	isl_multi_aff *ma = NULL;
 
@@ -3644,7 +3861,7 @@ __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
 	if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
 		isl_set *set;
 		isl_space *space;
-		int has_expr;
+		isl_bool has_expr;
 
 		has_expr = tuple_has_expr(tuple);
 		if (has_expr < 0)
@@ -3666,6 +3883,8 @@ __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
 
 	n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
 	dim = isl_set_dim(dom, isl_dim_all);
+	if (n < 0 || dim < 0)
+		goto error;
 	dom_space = isl_set_get_space(dom);
 	space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
 	space = isl_space_align_params(space, isl_space_copy(dom_space));

diff  --git a/polly/lib/External/isl/isl_list_macro.h b/polly/lib/External/isl/isl_list_macro.h
new file mode 100644
index 000000000000..72f258a298da
--- /dev/null
+++ b/polly/lib/External/isl/isl_list_macro.h
@@ -0,0 +1,8 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef EL
+#define EL CAT(isl_,EL_BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xLIST(EL) EL ## _list
+#define LIST(EL) xLIST(EL)

diff  --git a/polly/lib/External/isl/isl_list_templ.c b/polly/lib/External/isl/isl_list_templ.c
index edd62415fd7d..7a3c424f4b92 100644
--- a/polly/lib/External/isl/isl_list_templ.c
+++ b/polly/lib/External/isl/isl_list_templ.c
@@ -17,14 +17,8 @@
 #include <isl_tarjan.h>
 #include <isl/printer.h>
 
-#define xCAT(A,B) A ## B
-#define CAT(A,B) xCAT(A,B)
-#undef EL
-#define EL CAT(isl_,BASE)
-#define xFN(TYPE,NAME) TYPE ## _ ## NAME
-#define FN(TYPE,NAME) xFN(TYPE,NAME)
-#define xLIST(EL) EL ## _list
-#define LIST(EL) xLIST(EL)
+#include <isl_list_macro.h>
+
 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
 #define S(TYPE,NAME) xS(TYPE,NAME)
 
@@ -184,6 +178,15 @@ __isl_give LIST(EL) *FN(LIST(EL),drop)(__isl_take LIST(EL) *list,
 	return list;
 }
 
+/* Remove all elements from "list".
+ */
+__isl_give LIST(EL) *FN(LIST(EL),clear)(__isl_take LIST(EL) *list)
+{
+	if (!list)
+		return NULL;
+	return FN(LIST(EL),drop)(list, 0, list->n);
+}
+
 /* Insert "el" at position "pos" in "list".
  *
  * If there is only one reference to "list" and if it already has space
@@ -248,14 +251,14 @@ __isl_null LIST(EL) *FN(LIST(EL),free)(__isl_take LIST(EL) *list)
 
 /* Return the number of elements in "list".
  */
-int FN(LIST(EL),size)(__isl_keep LIST(EL) *list)
+isl_size FN(LIST(EL),size)(__isl_keep LIST(EL) *list)
 {
-	return list ? list->n : 0;
+	return list ? list->n : isl_size_error;
 }
 
 /* This is an alternative name for the function above.
  */
-int FN(FN(LIST(EL),n),BASE)(__isl_keep LIST(EL) *list)
+isl_size FN(FN(LIST(EL),n),EL_BASE)(__isl_keep LIST(EL) *list)
 {
 	return FN(LIST(EL),size)(list);
 }
@@ -278,14 +281,15 @@ __isl_give EL *FN(LIST(EL),get_at)(__isl_keep LIST(EL) *list, int index)
 
 /* This is an alternative name for the function above.
  */
-__isl_give EL *FN(FN(LIST(EL),get),BASE)(__isl_keep LIST(EL) *list, int index)
+__isl_give EL *FN(FN(LIST(EL),get),EL_BASE)(__isl_keep LIST(EL) *list,
+	int index)
 {
 	return FN(LIST(EL),get_at)(list, index);
 }
 
 /* Replace the element at position "index" in "list" by "el".
  */
-__isl_give LIST(EL) *FN(FN(LIST(EL),set),BASE)(__isl_take LIST(EL) *list,
+__isl_give LIST(EL) *FN(FN(LIST(EL),set),EL_BASE)(__isl_take LIST(EL) *list,
 	int index, __isl_take EL *el)
 {
 	if (!list || !el)
@@ -318,7 +322,7 @@ __isl_give LIST(EL) *FN(FN(LIST(EL),set),BASE)(__isl_take LIST(EL) *list,
  * to isl_list_*_restore_*.
  * The only exception is that isl_list_*_free can be called instead.
  */
-static __isl_give EL *FN(FN(LIST(EL),take),BASE)(__isl_keep LIST(EL) *list,
+static __isl_give EL *FN(FN(LIST(EL),take),EL_BASE)(__isl_keep LIST(EL) *list,
 	int index)
 {
 	EL *el;
@@ -326,7 +330,7 @@ static __isl_give EL *FN(FN(LIST(EL),take),BASE)(__isl_keep LIST(EL) *list,
 	if (FN(LIST(EL),check_index)(list, index) < 0)
 		return NULL;
 	if (list->ref != 1)
-		return FN(FN(LIST(EL),get),BASE)(list, index);
+		return FN(FN(LIST(EL),get),EL_BASE)(list, index);
 	el = list->p[index];
 	list->p[index] = NULL;
 	return el;
@@ -336,10 +340,10 @@ static __isl_give EL *FN(FN(LIST(EL),take),BASE)(__isl_keep LIST(EL) *list,
  * where the position may be empty due to a previous call
  * to isl_list_*_take_*.
  */
-static __isl_give LIST(EL) *FN(FN(LIST(EL),restore),BASE)(
+static __isl_give LIST(EL) *FN(FN(LIST(EL),restore),EL_BASE)(
 	__isl_take LIST(EL) *list, int index, __isl_take EL *el)
 {
-	return FN(FN(LIST(EL),set),BASE)(list, index, el);
+	return FN(FN(LIST(EL),set),EL_BASE)(list, index, el);
 }
 
 /* Swap the elements of "list" in positions "pos1" and "pos2".
@@ -351,10 +355,10 @@ __isl_give LIST(EL) *FN(LIST(EL),swap)(__isl_take LIST(EL) *list,
 
 	if (pos1 == pos2)
 		return list;
-	el1 = FN(FN(LIST(EL),take),BASE)(list, pos1);
-	el2 = FN(FN(LIST(EL),take),BASE)(list, pos2);
-	list = FN(FN(LIST(EL),restore),BASE)(list, pos1, el2);
-	list = FN(FN(LIST(EL),restore),BASE)(list, pos2, el1);
+	el1 = FN(FN(LIST(EL),take),EL_BASE)(list, pos1);
+	el2 = FN(FN(LIST(EL),take),EL_BASE)(list, pos2);
+	list = FN(FN(LIST(EL),restore),EL_BASE)(list, pos1, el2);
+	list = FN(FN(LIST(EL),restore),EL_BASE)(list, pos2, el1);
 	return list;
 }
 
@@ -402,11 +406,11 @@ __isl_give LIST(EL) *FN(LIST(EL),map)(__isl_keep LIST(EL) *list,
 
 	n = list->n;
 	for (i = 0; i < n; ++i) {
-		EL *el = FN(FN(LIST(EL),take),BASE)(list, i);
+		EL *el = FN(FN(LIST(EL),take),EL_BASE)(list, i);
 		if (!el)
 			return FN(LIST(EL),free)(list);
 		el = fn(el, user);
-		list = FN(FN(LIST(EL),restore),BASE)(list, i, el);
+		list = FN(FN(LIST(EL),restore),EL_BASE)(list, i, el);
 	}
 
 	return list;
@@ -563,7 +567,7 @@ isl_stat FN(LIST(EL),foreach_scc)(__isl_keep LIST(EL) *list,
 	return n > 0 ? isl_stat_error : isl_stat_ok;
 }
 
-__isl_give LIST(EL) *FN(FN(LIST(EL),from),BASE)(__isl_take EL *el)
+__isl_give LIST(EL) *FN(FN(LIST(EL),from),EL_BASE)(__isl_take EL *el)
 {
 	isl_ctx *ctx;
 	LIST(EL) *list;
@@ -630,7 +634,7 @@ __isl_give LIST(EL) *FN(LIST(EL),concat)(__isl_take LIST(EL) *list1,
 	return NULL;
 }
 
-__isl_give isl_printer *CAT(isl_printer_print_,LIST(BASE))(
+__isl_give isl_printer *CAT(isl_printer_print_,LIST(EL_BASE))(
 	__isl_take isl_printer *p, __isl_keep LIST(EL) *list)
 {
 	int i;
@@ -641,7 +645,7 @@ __isl_give isl_printer *CAT(isl_printer_print_,LIST(BASE))(
 	for (i = 0; i < list->n; ++i) {
 		if (i)
 			p = isl_printer_print_str(p, ",");
-		p = CAT(isl_printer_print_,BASE)(p, list->p[i]);
+		p = CAT(isl_printer_print_,EL_BASE)(p, list->p[i]);
 	}
 	p = isl_printer_print_str(p, ")");
 	return p;
@@ -650,16 +654,9 @@ __isl_give isl_printer *CAT(isl_printer_print_,LIST(BASE))(
 	return NULL;
 }
 
-void FN(LIST(EL),dump)(__isl_keep LIST(EL) *list)
-{
-	isl_printer *printer;
-
-	if (!list)
-		return;
-
-	printer = isl_printer_to_file(FN(LIST(EL),get_ctx)(list), stderr);
-	printer = CAT(isl_printer_print_,LIST(BASE))(printer, list);
-	printer = isl_printer_end_line(printer);
+#undef BASE
+#define BASE LIST(EL_BASE)
 
-	isl_printer_free(printer);
-}
+#define PRINT_DUMP_DEFAULT	0
+#include "print_templ.c"
+#undef PRINT_DUMP_DEFAULT

diff  --git a/polly/lib/External/isl/isl_local.c b/polly/lib/External/isl/isl_local.c
index 4fb42bb3b52b..e409359d28da 100644
--- a/polly/lib/External/isl/isl_local.c
+++ b/polly/lib/External/isl/isl_local.c
@@ -15,7 +15,7 @@
 #include <isl_mat_private.h>
 #include <isl_reordering.h>
 #include <isl_seq.h>
-#include <isl_local.h>
+#include <isl_local_private.h>
 
 /* Return the isl_ctx to which "local" belongs.
  */
@@ -52,33 +52,43 @@ __isl_null isl_local *isl_local_free(__isl_take isl_local *local)
  *
  * Other types do not have any meaning for an isl_local object.
  */
-int isl_local_dim(__isl_keep isl_local *local, enum isl_dim_type type)
+isl_size isl_local_dim(__isl_keep isl_local *local, enum isl_dim_type type)
 {
 	isl_mat *mat = local;
 
 	if (!local)
-		return 0;
+		return isl_size_error;
 	if (type == isl_dim_div)
 		return isl_mat_rows(mat);
-	if (type == isl_dim_all)
-		return isl_mat_cols(mat) - 2;
-	if (type == isl_dim_set)
-		return isl_local_dim(local, isl_dim_all) -
-			isl_local_dim(local, isl_dim_div);
+	if (type == isl_dim_all) {
+		isl_size cols = isl_mat_cols(mat);
+		if (cols < 0)
+			return isl_size_error;
+		return cols - 2;
+	}
+	if (type == isl_dim_set) {
+		isl_size total, n_div;
+
+		total = isl_local_dim(local, isl_dim_all);
+		n_div = isl_local_dim(local, isl_dim_div);
+		if (total < 0 || n_div < 0)
+			return isl_size_error;
+		return total - n_div;
+	}
 	isl_die(isl_local_get_ctx(local), isl_error_unsupported,
-		"unsupported dimension type", return 0);
+		"unsupported dimension type", return isl_size_error);
 }
 
+#undef TYPE
+#define TYPE	isl_local
+static
+#include "check_type_range_templ.c"
+
 /* Check that "pos" is a valid position for a variable in "local".
  */
 static isl_stat isl_local_check_pos(__isl_keep isl_local *local, int pos)
 {
-	if (!local)
-		return isl_stat_error;
-	if (pos < 0 || pos >= isl_local_dim(local, isl_dim_div))
-		isl_die(isl_local_get_ctx(local), isl_error_invalid,
-			"position out of bounds", return isl_stat_error);
-	return isl_stat_ok;
+	return isl_local_check_range(local, isl_dim_div, pos, 1);
 }
 
 /* Given local variables "local",
@@ -95,7 +105,7 @@ isl_bool isl_local_div_is_marked_unknown(__isl_keep isl_local *local, int pos)
 
 	if (isl_local_check_pos(local, pos) < 0)
 		return isl_bool_error;
-	return isl_int_is_zero(mat->row[pos][0]);
+	return isl_bool_ok(isl_int_is_zero(mat->row[pos][0]));
 }
 
 /* Given local variables "local",
@@ -108,7 +118,8 @@ isl_bool isl_local_div_is_marked_unknown(__isl_keep isl_local *local, int pos)
 isl_bool isl_local_div_is_known(__isl_keep isl_local *local, int pos)
 {
 	isl_bool marked;
-	int i, n, off;
+	int i, off;
+	isl_size n, cols;
 	isl_mat *mat = local;
 
 	if (isl_local_check_pos(local, pos) < 0)
@@ -119,7 +130,10 @@ isl_bool isl_local_div_is_known(__isl_keep isl_local *local, int pos)
 		return isl_bool_not(marked);
 
 	n = isl_local_dim(local, isl_dim_div);
-	off = isl_mat_cols(mat) - n;
+	cols = isl_mat_cols(mat);
+	if (n < 0 || cols < 0)
+		return isl_bool_error;
+	off = cols - n;
 
 	for (i = n - 1; i >= 0; --i) {
 		isl_bool known;
@@ -138,12 +152,13 @@ isl_bool isl_local_div_is_known(__isl_keep isl_local *local, int pos)
  */
 isl_bool isl_local_divs_known(__isl_keep isl_local *local)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!local)
+	n = isl_local_dim(local, isl_dim_div);
+	if (n < 0)
 		return isl_bool_error;
 
-	n = isl_local_dim(local, isl_dim_div);
 	for (i = 0; i < n; ++i) {
 		isl_bool unknown = isl_local_div_is_marked_unknown(local, i);
 		if (unknown < 0 || unknown)
@@ -169,7 +184,7 @@ int isl_local_cmp(__isl_keep isl_local *local1, __isl_keep isl_local *local2)
 	int cmp;
 	isl_bool unknown1, unknown2;
 	int last1, last2;
-	int n_col;
+	isl_size n_col;
 	isl_mat *mat1 = local1;
 	isl_mat *mat2 = local2;
 
@@ -184,6 +199,8 @@ int isl_local_cmp(__isl_keep isl_local *local1, __isl_keep isl_local *local2)
 		return mat1->n_row - mat2->n_row;
 
 	n_col = isl_mat_cols(mat1);
+	if (n_col < 0)
+		return -1;
 	for (i = 0; i < mat1->n_row; ++i) {
 		unknown1 = isl_local_div_is_marked_unknown(local1, i);
 		unknown2 = isl_local_div_is_marked_unknown(local2, i);
@@ -214,6 +231,7 @@ __isl_give isl_local *isl_local_reorder(__isl_take isl_local *local,
 {
 	isl_mat *div = local;
 	int i, j;
+	isl_size dim;
 	isl_space *space;
 	isl_mat *mat;
 	int extra;
@@ -222,7 +240,10 @@ __isl_give isl_local *isl_local_reorder(__isl_take isl_local *local,
 		goto error;
 
 	space = isl_reordering_peek_space(r);
-	extra = isl_space_dim(space, isl_dim_all) + div->n_row - r->len;
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0)
+		goto error;
+	extra = dim + div->n_row - r->len;
 	mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra);
 	if (!mat)
 		goto error;
@@ -248,11 +269,13 @@ __isl_give isl_local *isl_local_reorder(__isl_take isl_local *local,
  * in the domain space of "local"
  * to one that also includes values for the local variables.
  * All local variables are required to have an explicit representation.
+ * If there are no local variables, then the point is not required
+ * to be integral.
  */
 __isl_give isl_vec *isl_local_extend_point_vec(__isl_keep isl_local *local,
 	__isl_take isl_vec *v)
 {
-	unsigned n_div;
+	isl_size dim, n_div, size;
 	isl_bool known;
 	isl_mat *mat = local;
 
@@ -264,16 +287,21 @@ __isl_give isl_vec *isl_local_extend_point_vec(__isl_keep isl_local *local,
 	if (!known)
 		isl_die(isl_local_get_ctx(local), isl_error_invalid,
 			"unknown local variables", return isl_vec_free(v));
-	if (isl_vec_size(v) != 1 + isl_local_dim(local, isl_dim_set))
+	dim = isl_local_dim(local, isl_dim_set);
+	n_div = isl_local_dim(local, isl_dim_div);
+	size = isl_vec_size(v);
+	if (dim < 0 || n_div < 0 || size < 0)
+		return isl_vec_free(v);
+	if (size != 1 + dim)
 		isl_die(isl_local_get_ctx(local), isl_error_invalid,
 			"incorrect size", return isl_vec_free(v));
+	if (n_div == 0)
+		return v;
 	if (!isl_int_is_one(v->el[0]))
 		isl_die(isl_local_get_ctx(local), isl_error_invalid,
 			"expecting integer point", return isl_vec_free(v));
-	n_div = isl_local_dim(local, isl_dim_div);
-	if (n_div != 0) {
+	{
 		int i;
-		unsigned dim = isl_local_dim(local, isl_dim_set);
 		v = isl_vec_add_els(v, n_div);
 		if (!v)
 			return NULL;

diff  --git a/polly/lib/External/isl/isl_local.h b/polly/lib/External/isl/isl_local.h
index 74138ee0251e..a52622e4a1da 100644
--- a/polly/lib/External/isl/isl_local.h
+++ b/polly/lib/External/isl/isl_local.h
@@ -6,6 +6,8 @@
 
 typedef isl_mat isl_local;
 
+__isl_null isl_local *isl_local_free(__isl_take isl_local *local);
+
 isl_bool isl_local_div_is_marked_unknown(__isl_keep isl_local *local, int pos);
 isl_bool isl_local_div_is_known(__isl_keep isl_local *local, int pos);
 isl_bool isl_local_divs_known(__isl_keep isl_local *local);

diff  --git a/polly/lib/External/isl/isl_local_private.h b/polly/lib/External/isl/isl_local_private.h
new file mode 100644
index 000000000000..bb44d36b83a3
--- /dev/null
+++ b/polly/lib/External/isl/isl_local_private.h
@@ -0,0 +1,8 @@
+#ifndef ISL_LOCAL_PRIVATE_H
+#define ISL_LOCAL_PRIVATE_H
+
+#include <isl_local.h>
+
+__isl_give isl_local *isl_local_alloc_from_mat(__isl_take isl_mat *mat);
+
+#endif

diff  --git a/polly/lib/External/isl/isl_local_space.c b/polly/lib/External/isl/isl_local_space.c
index 8bef0f53f293..eff3234f2a83 100644
--- a/polly/lib/External/isl/isl_local_space.c
+++ b/polly/lib/External/isl/isl_local_space.c
@@ -45,47 +45,49 @@ uint32_t isl_local_space_get_hash(__isl_keep isl_local_space *ls)
 	return hash;
 }
 
-__isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_space *dim,
-	__isl_take isl_mat *div)
+__isl_give isl_local_space *isl_local_space_alloc_div(
+	__isl_take isl_space *space, __isl_take isl_mat *div)
 {
 	isl_ctx *ctx;
 	isl_local_space *ls = NULL;
 
-	if (!dim || !div)
+	if (!space || !div)
 		goto error;
 
-	ctx = isl_space_get_ctx(dim);
+	ctx = isl_space_get_ctx(space);
 	ls = isl_calloc_type(ctx, struct isl_local_space);
 	if (!ls)
 		goto error;
 
 	ls->ref = 1;
-	ls->dim = dim;
+	ls->dim = space;
 	ls->div = div;
 
 	return ls;
 error:
 	isl_mat_free(div);
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_local_space_free(ls);
 	return NULL;
 }
 
-__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *dim,
+__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *space,
 	unsigned n_div)
 {
 	isl_ctx *ctx;
 	isl_mat *div;
-	unsigned total;
+	isl_size total;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	total = isl_space_dim(dim, isl_dim_all);
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0)
+		return isl_local_space_from_space(isl_space_free(space));
 
-	ctx = isl_space_get_ctx(dim);
+	ctx = isl_space_get_ctx(space);
 	div = isl_mat_alloc(ctx, n_div, 1 + 1 + total + n_div);
-	return isl_local_space_alloc_div(dim, div);
+	return isl_local_space_alloc_div(space, div);
 }
 
 __isl_give isl_local_space *isl_local_space_from_space(__isl_take isl_space *dim)
@@ -156,16 +158,10 @@ isl_bool isl_local_space_is_set(__isl_keep isl_local_space *ls)
 	return ls ? isl_space_is_set(ls->dim) : isl_bool_error;
 }
 
-/* Do "ls1" and "ls2" have the same space?
- */
-isl_bool isl_local_space_has_equal_space(__isl_keep isl_local_space *ls1,
-	__isl_keep isl_local_space *ls2)
-{
-	if (!ls1 || !ls2)
-		return isl_bool_error;
+#undef TYPE
+#define TYPE	isl_local_space
 
-	return isl_space_is_equal(ls1->dim, ls2->dim);
-}
+#include "isl_type_has_equal_space_bin_templ.c"
 
 /* Is the space of "ls" equal to "space"?
  */
@@ -235,33 +231,42 @@ int isl_local_space_cmp(__isl_keep isl_local_space *ls1,
 	return isl_local_cmp(ls1->div, ls2->div);
 }
 
-int isl_local_space_dim(__isl_keep isl_local_space *ls,
+isl_size isl_local_space_dim(__isl_keep isl_local_space *ls,
 	enum isl_dim_type type)
 {
 	if (!ls)
-		return 0;
+		return isl_size_error;
 	if (type == isl_dim_div)
 		return ls->div->n_row;
-	if (type == isl_dim_all)
-		return isl_space_dim(ls->dim, isl_dim_all) + ls->div->n_row;
+	if (type == isl_dim_all) {
+		isl_size dim = isl_space_dim(ls->dim, isl_dim_all);
+		if (dim < 0)
+			return isl_size_error;
+		return dim + ls->div->n_row;
+	}
 	return isl_space_dim(ls->dim, type);
 }
 
+#undef TYPE
+#define TYPE	isl_local_space
+#include "check_type_range_templ.c"
+
 unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
 	enum isl_dim_type type)
 {
-	isl_space *dim;
+	isl_space *space;
 
 	if (!ls)
 		return 0;
 
-	dim = ls->dim;
+	space = ls->dim;
 	switch (type) {
 	case isl_dim_cst:	return 0;
 	case isl_dim_param:	return 1;
-	case isl_dim_in:	return 1 + dim->nparam;
-	case isl_dim_out:	return 1 + dim->nparam + dim->n_in;
-	case isl_dim_div:	return 1 + dim->nparam + dim->n_in + dim->n_out;
+	case isl_dim_in:	return 1 + space->nparam;
+	case isl_dim_out:	return 1 + space->nparam + space->n_in;
+	case isl_dim_div:
+		return 1 + space->nparam + space->n_in + space->n_out;
 	default:		return 0;
 	}
 }
@@ -330,12 +335,15 @@ static __isl_give isl_aff *extract_div(__isl_keep isl_local_space *ls, int pos)
 static __isl_give isl_aff *drop_unknown_divs_and_extract_div(
 	__isl_keep isl_local_space *ls, int pos)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_bool unknown;
 	isl_aff *aff;
 
-	ls = isl_local_space_copy(ls);
 	n = isl_local_space_dim(ls, isl_dim_div);
+	if (n < 0)
+		return NULL;
+	ls = isl_local_space_copy(ls);
 	for (i = n - 1; i >= 0; --i) {
 		unknown = isl_local_space_div_is_marked_unknown(ls, i);
 		if (unknown < 0)
@@ -685,7 +693,7 @@ __isl_give isl_basic_map *isl_basic_map_sort_divs(
 	__isl_take isl_basic_map *bmap)
 {
 	int i, j;
-	unsigned total;
+	isl_size total;
 
 	bmap = isl_basic_map_order_divs(bmap);
 	if (!bmap)
@@ -693,12 +701,16 @@ __isl_give isl_basic_map *isl_basic_map_sort_divs(
 	if (bmap->n_div <= 1)
 		return bmap;
 
-	total = 2 + isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	for (i = 1; i < bmap->n_div; ++i) {
 		for (j = i - 1; j >= 0; --j) {
-			if (bmap_cmp_row(bmap, j, j + 1, total) <= 0)
+			if (bmap_cmp_row(bmap, j, j + 1, 2 + total) <= 0)
 				break;
-			isl_basic_map_swap_div(bmap, j, j + 1);
+			bmap = isl_basic_map_swap_div(bmap, j, j + 1);
+			if (!bmap)
+				return NULL;
 		}
 	}
 
@@ -888,8 +900,12 @@ isl_bool isl_local_space_divs_known(__isl_keep isl_local_space *ls)
 __isl_give isl_local_space *isl_local_space_domain(
 	__isl_take isl_local_space *ls)
 {
-	ls = isl_local_space_drop_dims(ls, isl_dim_out,
-					0, isl_local_space_dim(ls, isl_dim_out));
+	isl_size n_out;
+
+	n_out = isl_local_space_dim(ls, isl_dim_out);
+	if (n_out < 0)
+		return isl_local_space_free(ls);
+	ls = isl_local_space_drop_dims(ls, isl_dim_out, 0, n_out);
 	ls = isl_local_space_cow(ls);
 	if (!ls)
 		return NULL;
@@ -902,8 +918,12 @@ __isl_give isl_local_space *isl_local_space_domain(
 __isl_give isl_local_space *isl_local_space_range(
 	__isl_take isl_local_space *ls)
 {
-	ls = isl_local_space_drop_dims(ls, isl_dim_in,
-					0, isl_local_space_dim(ls, isl_dim_in));
+	isl_size n_in;
+
+	n_in = isl_local_space_dim(ls, isl_dim_in);
+	if (n_in < 0)
+		return isl_local_space_free(ls);
+	ls = isl_local_space_drop_dims(ls, isl_dim_in, 0, n_in);
 	ls = isl_local_space_cow(ls);
 	if (!ls)
 		return NULL;
@@ -932,17 +952,86 @@ __isl_give isl_local_space *isl_local_space_from_domain(
 __isl_give isl_local_space *isl_local_space_add_dims(
 	__isl_take isl_local_space *ls, enum isl_dim_type type, unsigned n)
 {
-	int pos;
+	isl_size pos;
 
-	if (!ls)
-		return NULL;
 	pos = isl_local_space_dim(ls, type);
+	if (pos < 0)
+		return isl_local_space_free(ls);
 	return isl_local_space_insert_dims(ls, type, pos, n);
 }
 
+/* Lift the basic set "bset", living in the space of "ls"
+ * to live in a space with extra coordinates corresponding
+ * to the local variables of "ls".
+ */
+__isl_give isl_basic_set *isl_local_space_lift_basic_set(
+	__isl_take isl_local_space *ls, __isl_take isl_basic_set *bset)
+{
+	isl_size n_local;
+	isl_space *space;
+	isl_basic_set *ls_bset;
+
+	n_local = isl_local_space_dim(ls, isl_dim_div);
+	space = isl_basic_set_peek_space(bset);
+	if (n_local < 0 ||
+	    isl_local_space_check_has_space(ls, space) < 0)
+		goto error;
+
+	if (n_local == 0) {
+		isl_local_space_free(ls);
+		return bset;
+	}
+
+	bset = isl_basic_set_add_dims(bset, isl_dim_set, n_local);
+	ls_bset = isl_basic_set_from_local_space(ls);
+	ls_bset = isl_basic_set_lift(ls_bset);
+	ls_bset = isl_basic_set_flatten(ls_bset);
+	bset = isl_basic_set_intersect(bset, ls_bset);
+
+	return bset;
+error:
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+/* Lift the set "set", living in the space of "ls"
+ * to live in a space with extra coordinates corresponding
+ * to the local variables of "ls".
+ */
+__isl_give isl_set *isl_local_space_lift_set(__isl_take isl_local_space *ls,
+	__isl_take isl_set *set)
+{
+	isl_size n_local;
+	isl_basic_set *bset;
+
+	n_local = isl_local_space_dim(ls, isl_dim_div);
+	if (n_local < 0 ||
+	    isl_local_space_check_has_space(ls, isl_set_peek_space(set)) < 0)
+		goto error;
+
+	if (n_local == 0) {
+		isl_local_space_free(ls);
+		return set;
+	}
+
+	set = isl_set_add_dims(set, isl_dim_set, n_local);
+	bset = isl_basic_set_from_local_space(ls);
+	bset = isl_basic_set_lift(bset);
+	bset = isl_basic_set_flatten(bset);
+	set = isl_set_intersect(set, isl_set_from_basic_set(bset));
+
+	return set;
+error:
+	isl_local_space_free(ls);
+	isl_set_free(set);
+	return NULL;
+}
+
 /* Remove common factor of non-constant terms and denominator.
  */
-static void normalize_div(__isl_keep isl_local_space *ls, int div)
+static __isl_give isl_local_space *normalize_div(
+	__isl_take isl_local_space *ls, int div)
 {
 	isl_ctx *ctx = ls->div->ctx;
 	unsigned total = ls->div->n_col - 2;
@@ -951,7 +1040,7 @@ static void normalize_div(__isl_keep isl_local_space *ls, int div)
 	isl_int_gcd(ctx->normalize_gcd,
 		    ctx->normalize_gcd, ls->div->row[div][0]);
 	if (isl_int_is_one(ctx->normalize_gcd))
-		return;
+		return ls;
 
 	isl_seq_scale_down(ls->div->row[div] + 2, ls->div->row[div] + 2,
 			    ctx->normalize_gcd, total);
@@ -959,6 +1048,8 @@ static void normalize_div(__isl_keep isl_local_space *ls, int div)
 			    ctx->normalize_gcd);
 	isl_int_fdiv_q(ls->div->row[div][1], ls->div->row[div][1],
 			    ctx->normalize_gcd);
+
+	return ls;
 }
 
 /* Exploit the equalities in "eq" to simplify the expressions of
@@ -970,14 +1061,17 @@ __isl_give isl_local_space *isl_local_space_substitute_equalities(
 	__isl_take isl_local_space *ls, __isl_take isl_basic_set *eq)
 {
 	int i, j, k;
-	unsigned total;
+	isl_size total, dim;
 	unsigned n_div;
 
 	if (!ls || !eq)
 		goto error;
 
 	total = isl_space_dim(eq->dim, isl_dim_all);
-	if (isl_local_space_dim(ls, isl_dim_all) != total)
+	dim = isl_local_space_dim(ls, isl_dim_all);
+	if (dim < 0 || total < 0)
+		goto error;
+	if (dim != total)
 		isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
 			"spaces don't match", goto error);
 	total++;
@@ -998,7 +1092,9 @@ __isl_give isl_local_space *isl_local_space_substitute_equalities(
 				goto error;
 			isl_seq_elim(ls->div->row[k] + 1, eq->eq[i], j, total,
 					&ls->div->row[k][0]);
-			normalize_div(ls, k);
+			ls = normalize_div(ls, k);
+			if (!ls)
+				goto error;
 		}
 	}
 
@@ -1055,7 +1151,9 @@ __isl_give isl_local_space *isl_local_space_substitute_seq(
 			continue;
 		isl_seq_substitute(ls->div->row[i], pos, subs,
 			ls->div->n_col, subs_len, v);
-		normalize_div(ls, i);
+		ls = normalize_div(ls, i);
+		if (!ls)
+			break;
 	}
 	isl_int_clear(v);
 
@@ -1081,6 +1179,8 @@ __isl_give isl_local_space *isl_local_space_substitute(
 	__isl_take isl_local_space *ls,
 	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
 {
+	isl_size n_div;
+
 	ls = isl_local_space_cow(ls);
 	if (!ls || !subs)
 		return isl_local_space_free(ls);
@@ -1088,7 +1188,10 @@ __isl_give isl_local_space *isl_local_space_substitute(
 	if (!isl_space_is_equal(ls->dim, subs->ls->dim))
 		isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
 			"spaces don't match", return isl_local_space_free(ls));
-	if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
+	n_div = isl_local_space_dim(subs->ls, isl_dim_div);
+	if (n_div < 0)
+		return isl_local_space_free(ls);
+	if (n_div != 0)
 		isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported,
 			"cannot handle divs yet",
 			return isl_local_space_free(ls));
@@ -1109,17 +1212,13 @@ __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_ctx *ctx;
-
 	if (!ls)
 		return NULL;
 	if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
 		return ls;
 
-	ctx = isl_local_space_get_ctx(ls);
-	if (first + n > isl_local_space_dim(ls, type))
-		isl_die(ctx, isl_error_invalid, "range out of bounds",
-			return isl_local_space_free(ls));
+	if (isl_local_space_check_range(ls, type, first, n) < 0)
+		return isl_local_space_free(ls);
 
 	ls = isl_local_space_cow(ls);
 	if (!ls)
@@ -1145,17 +1244,13 @@ __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_ctx *ctx;
-
 	if (!ls)
 		return NULL;
 	if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
 		return ls;
 
-	ctx = isl_local_space_get_ctx(ls);
-	if (first > isl_local_space_dim(ls, type))
-		isl_die(ctx, isl_error_invalid, "position out of bounds",
-			return isl_local_space_free(ls));
+	if (isl_local_space_check_range(ls, type, first, 0) < 0)
+		return isl_local_space_free(ls);
 
 	ls = isl_local_space_cow(ls);
 	if (!ls)
@@ -1286,7 +1381,7 @@ isl_bool isl_local_space_is_div_equality(__isl_keep isl_local_space *ls,
 	if (linear < 0 || !linear)
 		return linear;
 
-	return sign < 0;
+	return isl_bool_ok(sign < 0);
 }
 
 /*
@@ -1298,11 +1393,13 @@ int *isl_local_space_get_active(__isl_keep isl_local_space *ls, isl_int *l)
 	int i, j;
 	isl_ctx *ctx;
 	int *active = NULL;
-	unsigned total;
+	isl_size total;
 	unsigned offset;
 
 	ctx = isl_local_space_get_ctx(ls);
 	total = isl_local_space_dim(ls, isl_dim_all);
+	if (total < 0)
+		return NULL;
 	active = isl_calloc_array(ctx, int, total);
 	if (total && !active)
 		return NULL;
@@ -1392,7 +1489,7 @@ __isl_give isl_local_space *isl_local_space_preimage_multi_aff(
 	int i;
 	isl_space *space;
 	isl_local_space *res = NULL;
-	int n_div_ls, n_div_ma;
+	isl_size n_div_ls, n_div_ma;
 	isl_int f, c1, c2, g;
 
 	ma = isl_multi_aff_align_divs(ma);
@@ -1404,6 +1501,8 @@ __isl_give isl_local_space *isl_local_space_preimage_multi_aff(
 
 	n_div_ls = isl_local_space_dim(ls, isl_dim_div);
 	n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
+	if (n_div_ls < 0 || n_div_ma < 0)
+		goto error;
 
 	space = isl_space_domain(isl_multi_aff_get_space(ma));
 	res = isl_local_space_alloc(space, n_div_ma + n_div_ls);
@@ -1429,9 +1528,13 @@ __isl_give isl_local_space *isl_local_space_preimage_multi_aff(
 			isl_int_set_si(res->div->row[n_div_ma + i][0], 0);
 			continue;
 		}
-		isl_seq_preimage(res->div->row[n_div_ma + i], ls->div->row[i],
-				ma, 0, 0, n_div_ma, n_div_ls, f, c1, c2, g, 1);
-		normalize_div(res, n_div_ma + i);
+		if (isl_seq_preimage(res->div->row[n_div_ma + i],
+			    ls->div->row[i],
+			    ma, 0, 0, n_div_ma, n_div_ls, f, c1, c2, g, 1) < 0)
+			res = isl_local_space_free(res);
+		res = normalize_div(res, n_div_ma + i);
+		if (!res)
+			break;
 	}
 
 	isl_int_clear(f);
@@ -1470,13 +1573,10 @@ __isl_give isl_local_space *isl_local_space_move_dims(
 	    !isl_local_space_is_named_or_nested(ls, dst_type))
 		return ls;
 
-	if (src_pos + n > isl_local_space_dim(ls, src_type))
-		isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
-			"range out of bounds", return isl_local_space_free(ls));
-	if (dst_pos > isl_local_space_dim(ls, dst_type))
-		isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
-			"position out of bounds",
-			return isl_local_space_free(ls));
+	if (isl_local_space_check_range(ls, src_type, src_pos, n) < 0)
+		return isl_local_space_free(ls);
+	if (isl_local_space_check_range(ls, dst_type, dst_pos, 0) < 0)
+		return isl_local_space_free(ls);
 	if (src_type == isl_dim_div)
 		isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
 			"cannot move divs", return isl_local_space_free(ls));
@@ -1574,14 +1674,14 @@ __isl_give isl_local_space *isl_local_space_wrap(__isl_take isl_local_space *ls)
 	return ls;
 }
 
-/* Lift the point "pnt", living in the space of "ls"
+/* Lift the point "pnt", living in the (set) space of "ls"
  * to live in a space with extra coordinates corresponding
  * to the local variables of "ls".
  */
 __isl_give isl_point *isl_local_space_lift_point(__isl_take isl_local_space *ls,
 	__isl_take isl_point *pnt)
 {
-	unsigned n_local;
+	isl_size n_local;
 	isl_space *space;
 	isl_local *local;
 	isl_vec *vec;
@@ -1591,6 +1691,8 @@ __isl_give isl_point *isl_local_space_lift_point(__isl_take isl_local_space *ls,
 
 	local = isl_local_space_peek_local(ls);
 	n_local = isl_local_space_dim(ls, isl_dim_div);
+	if (n_local < 0)
+		goto error;
 
 	space = isl_point_take_space(pnt);
 	vec = isl_point_take_vec(pnt);

diff  --git a/polly/lib/External/isl/isl_local_space_private.h b/polly/lib/External/isl/isl_local_space_private.h
index c1c9c6166c66..bcca65088d59 100644
--- a/polly/lib/External/isl/isl_local_space_private.h
+++ b/polly/lib/External/isl/isl_local_space_private.h
@@ -12,12 +12,15 @@ struct isl_local_space {
 	isl_mat *div;
 };
 
+isl_stat isl_local_space_check_range(__isl_keep isl_local_space *ls,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
 uint32_t isl_local_space_get_hash(__isl_keep isl_local_space *ls);
 
-__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *dim,
+__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *space,
 	unsigned n_div);
-__isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_space *dim,
-	__isl_take isl_mat *div);
+__isl_give isl_local_space *isl_local_space_alloc_div(
+	__isl_take isl_space *space, __isl_take isl_mat *div);
 
 __isl_keep isl_space *isl_local_space_peek_space(
 	__isl_keep isl_local_space *ls);
@@ -41,6 +44,10 @@ isl_bool isl_local_space_div_is_marked_unknown(__isl_keep isl_local_space *ls,
 isl_bool isl_local_space_div_is_known(__isl_keep isl_local_space *ls, int div);
 isl_bool isl_local_space_divs_known(__isl_keep isl_local_space *ls);
 
+__isl_give isl_basic_set *isl_local_space_lift_basic_set(
+	__isl_take isl_local_space *ls, __isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_local_space_lift_set(__isl_take isl_local_space *ls,
+	__isl_take isl_set *set);
 __isl_give isl_local_space *isl_local_space_substitute_equalities(
 	__isl_take isl_local_space *ls, __isl_take isl_basic_set *eq);
 

diff  --git a/polly/lib/External/isl/isl_lp.c b/polly/lib/External/isl/isl_lp.c
index 0c2f5ff812b2..238935529588 100644
--- a/polly/lib/External/isl/isl_lp.c
+++ b/polly/lib/External/isl/isl_lp.c
@@ -28,8 +28,10 @@ enum isl_lp_result isl_tab_solve_lp(__isl_keep isl_basic_map *bmap,
 {
 	struct isl_tab *tab;
 	enum isl_lp_result res;
-	unsigned dim = isl_basic_map_total_dim(bmap);
+	isl_size dim = isl_basic_map_dim(bmap, isl_dim_all);
 
+	if (dim < 0)
+		return isl_lp_error;
 	if (maximize)
 		isl_seq_neg(f, f, 1 + dim);
 
@@ -107,7 +109,9 @@ enum isl_lp_result isl_map_solve_lp(__isl_keep isl_map *map, int max,
 		if (map->p[i]->n_div > max_div)
 			max_div = map->p[i]->n_div;
 	if (max_div > 0) {
-		unsigned total = isl_space_dim(map->dim, isl_dim_all);
+		isl_size total = isl_map_dim(map, isl_dim_all);
+		if (total < 0)
+			return isl_lp_error;
 		v = isl_vec_alloc(map->ctx, 1 + total + max_div);
 		if (!v)
 			return isl_lp_error;
@@ -259,7 +263,7 @@ static __isl_give isl_val *isl_basic_set_opt_lp_val_aligned(
 	isl_mat *bset_div = NULL;
 	isl_mat *div = NULL;
 	isl_val *res;
-	int bset_n_div, obj_n_div;
+	isl_size bset_n_div, obj_n_div;
 
 	if (!bset || !obj)
 		return NULL;
@@ -271,6 +275,8 @@ static __isl_give isl_val *isl_basic_set_opt_lp_val_aligned(
 
 	bset_n_div = isl_basic_set_dim(bset, isl_dim_div);
 	obj_n_div = isl_aff_dim(obj, isl_dim_div);
+	if (bset_n_div < 0 || obj_n_div < 0)
+		return NULL;
 	if (bset_n_div == 0 && obj_n_div == 0)
 		return basic_set_opt_lp(bset, max, obj);
 

diff  --git a/polly/lib/External/isl/isl_map.c b/polly/lib/External/isl/isl_map.c
index 592a20b93648..d3012ba9bf68 100644
--- a/polly/lib/External/isl/isl_map.c
+++ b/polly/lib/External/isl/isl_map.c
@@ -5,6 +5,7 @@
  * Copyright 2014      INRIA Rocquencourt
  * Copyright 2016      INRIA Paris
  * Copyright 2016      Sven Verdoolaege
+ * Copyright 2018-2019 Cerebras Systems
  *
  * Use of this software is governed by the MIT license
  *
@@ -17,13 +18,14 @@
  * B.P. 105 - 78153 Le Chesnay, France
  * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
  * CS 42112, 75589 Paris Cedex 12, France
+ * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
  */
 
 #include <string.h>
 #include <isl_ctx_private.h>
 #include <isl_map_private.h>
 #include <isl_blk.h>
-#include <isl/id.h>
+#include <isl_id_private.h>
 #include <isl/constraint.h>
 #include "isl_space_private.h"
 #include "isl_equalities.h"
@@ -44,23 +46,27 @@
 #include <isl_options_private.h>
 #include <isl_morph.h>
 #include <isl_val_private.h>
+#include <isl_printer_private.h>
 
 #include <bset_to_bmap.c>
 #include <bset_from_bmap.c>
 #include <set_to_map.c>
 #include <set_from_map.c>
 
-static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
+/* Treat "bset" as a basic map.
+ * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
+ * this function performs a redundant cast.
+ */
+static __isl_keep const isl_basic_map *const_bset_to_bmap(
+	__isl_keep const isl_basic_set *bset)
 {
-	switch (type) {
-	case isl_dim_param:	return dim->nparam;
-	case isl_dim_in:	return dim->n_in;
-	case isl_dim_out:	return dim->n_out;
-	case isl_dim_all:	return dim->nparam + dim->n_in + dim->n_out;
-	default:		return 0;
-	}
+	return (const isl_basic_map *) bset;
 }
 
+#undef TYPE
+#define TYPE	isl_basic_map
+#include "has_single_reference_templ.c"
+
 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
 {
 	switch (type) {
@@ -71,11 +77,11 @@ static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
 	}
 }
 
-unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
+isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
 				enum isl_dim_type type)
 {
 	if (!bmap)
-		return 0;
+		return isl_size_error;
 	switch (type) {
 	case isl_dim_cst:	return 1;
 	case isl_dim_param:
@@ -94,32 +100,68 @@ __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
 	return map ? map->dim : NULL;
 }
 
-unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
+/* Return the space of "set".
+ */
+__isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
+{
+	return isl_map_peek_space(set_to_map(set));
+}
+
+isl_size isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
 {
-	return map ? n(map->dim, type) : 0;
+	return isl_space_dim(isl_map_peek_space(map), type);
 }
 
-unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
+isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
 {
-	return set ? n(set->dim, type) : 0;
+	return isl_map_dim(set_to_map(set), type);
 }
 
-unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
-					enum isl_dim_type type)
+/* Return the position of the variables of the given type
+ * within the sequence of variables of "bmap".
+ */
+isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type)
 {
 	isl_space *space;
 
-	if (!bmap)
-		return 0;
+	space = isl_basic_map_peek_space(bmap);
+	if (!space)
+		return isl_size_error;
 
-	space = bmap->dim;
+	switch (type) {
+	case isl_dim_param:
+	case isl_dim_in:
+	case isl_dim_out:	return isl_space_offset(space, type);
+	case isl_dim_div:	return isl_space_dim(space, isl_dim_all);
+	case isl_dim_cst:
+	default:
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"invalid dimension type", return isl_size_error);
+	}
+}
+
+/* Return the position of the variables of the given type
+ * within the sequence of variables of "bset".
+ */
+isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type)
+{
+	return isl_basic_map_var_offset(bset_to_bmap(bset), type);
+}
+
+/* Return the position of the coefficients of the variables of the given type
+ * within the sequence of coefficients of "bmap".
+ */
+unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type)
+{
 	switch (type) {
 	case isl_dim_cst:	return 0;
-	case isl_dim_param:	return 1;
-	case isl_dim_in:	return 1 + space->nparam;
-	case isl_dim_out:	return 1 + space->nparam + space->n_in;
-	case isl_dim_div:	return 1 + space->nparam + space->n_in +
-								space->n_out;
+	case isl_dim_param:
+	case isl_dim_in:
+	case isl_dim_out:
+	case isl_dim_div:	return 1 + isl_basic_map_var_offset(bmap, type);
 	default:		return 0;
 	}
 }
@@ -135,77 +177,47 @@ static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
 	return pos(map->dim, type);
 }
 
-unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
+isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
 				enum isl_dim_type type)
 {
 	return isl_basic_map_dim(bset, type);
 }
 
-unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
+isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
 {
 	return isl_basic_set_dim(bset, isl_dim_set);
 }
 
-unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
+isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
 {
 	return isl_basic_set_dim(bset, isl_dim_param);
 }
 
-unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
+isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
 {
-	if (!bset)
-		return 0;
-	return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
+	return isl_basic_map_total_dim(const_bset_to_bmap(bset));
 }
 
-unsigned isl_set_n_dim(__isl_keep isl_set *set)
+isl_size isl_set_n_dim(__isl_keep isl_set *set)
 {
 	return isl_set_dim(set, isl_dim_set);
 }
 
-unsigned isl_set_n_param(__isl_keep isl_set *set)
+isl_size isl_set_n_param(__isl_keep isl_set *set)
 {
 	return isl_set_dim(set, isl_dim_param);
 }
 
-unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
-{
-	return bmap ? bmap->dim->n_in : 0;
-}
-
-unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
-{
-	return bmap ? bmap->dim->n_out : 0;
-}
-
-unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
-{
-	return bmap ? bmap->dim->nparam : 0;
-}
-
-unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
-{
-	return bmap ? bmap->n_div : 0;
-}
-
-unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
-{
-	return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
-}
-
-unsigned isl_map_n_in(__isl_keep const isl_map *map)
-{
-	return map ? map->dim->n_in : 0;
-}
-
-unsigned isl_map_n_out(__isl_keep const isl_map *map)
+isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
 {
-	return map ? map->dim->n_out : 0;
-}
+	isl_size dim;
 
-unsigned isl_map_n_param(__isl_keep const isl_map *map)
-{
-	return map ? map->dim->nparam : 0;
+	if (!bmap)
+		return isl_size_error;
+	dim = isl_space_dim(bmap->dim, isl_dim_all);
+	if (dim < 0)
+		return isl_size_error;
+	return dim + bmap->n_div;
 }
 
 /* Return the number of equality constraints in the description of "bmap".
@@ -373,6 +385,58 @@ __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
 	return isl_basic_map_get_space(bset_to_bmap(bset));
 }
 
+/* Return the space of "bmap".
+ * This may be either a copy or the space itself
+ * if there is only one reference to "bmap".
+ * This allows the space to be modified inplace
+ * if both the basic map and its space have only a single reference.
+ * The caller is not allowed to modify "bmap" between this call and
+ * a subsequent call to isl_basic_map_restore_space.
+ * The only exception is that isl_basic_map_free can be called instead.
+ */
+static __isl_give isl_space *isl_basic_map_take_space(
+	__isl_keep isl_basic_map *bmap)
+{
+	isl_space *space;
+
+	if (!bmap)
+		return NULL;
+	if (bmap->ref != 1)
+		return isl_basic_map_get_space(bmap);
+	space = bmap->dim;
+	bmap->dim = NULL;
+	return space;
+}
+
+/* Set the space of "bmap" to "space", where the space of "bmap" may be missing
+ * due to a preceding call to isl_basic_map_take_space.
+ * However, in this case, "bmap" only has a single reference and
+ * then the call to isl_basic_map_cow has no effect.
+ */
+static __isl_give isl_basic_map *isl_basic_map_restore_space(
+	__isl_take isl_basic_map *bmap, __isl_take isl_space *space)
+{
+	if (!bmap || !space)
+		goto error;
+
+	if (bmap->dim == space) {
+		isl_space_free(space);
+		return bmap;
+	}
+
+	bmap = isl_basic_map_cow(bmap);
+	if (!bmap)
+		goto error;
+	isl_space_free(bmap->dim);
+	bmap->dim = space;
+
+	return bmap;
+error:
+	isl_basic_map_free(bmap);
+	isl_space_free(space);
+	return NULL;
+}
+
 /* Extract the divs in "bmap" as a matrix.
  */
 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
@@ -380,15 +444,15 @@ __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
 	int i;
 	isl_ctx *ctx;
 	isl_mat *div;
-	unsigned total;
+	isl_size v_div;
 	unsigned cols;
 
-	if (!bmap)
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
 		return NULL;
 
 	ctx = isl_basic_map_get_ctx(bmap);
-	total = isl_space_dim(bmap->dim, isl_dim_all);
-	cols = 1 + 1 + total + bmap->n_div;
+	cols = 1 + 1 + v_div + bmap->n_div;
 	div = isl_mat_alloc(ctx, bmap->n_div, cols);
 	if (!div)
 		return NULL;
@@ -435,11 +499,11 @@ static __isl_give isl_basic_map *add_known_div_constraints(
 	__isl_take isl_basic_map *bmap)
 {
 	int i;
-	unsigned n_div;
+	isl_size n_div;
 
-	if (!bmap)
-		return NULL;
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_basic_map_free(bmap);
 	if (n_div == 0)
 		return bmap;
 	bmap = isl_basic_map_cow(bmap);
@@ -449,8 +513,7 @@ static __isl_give isl_basic_map *add_known_div_constraints(
 	for (i = 0; i < n_div; ++i) {
 		if (isl_int_is_zero(bmap->div[i][0]))
 			continue;
-		if (isl_basic_map_add_div_constraints(bmap, i) < 0)
-			return isl_basic_map_free(bmap);
+		bmap = isl_basic_map_add_div_constraints(bmap, i);
 	}
 
 	return bmap;
@@ -460,13 +523,15 @@ __isl_give isl_basic_map *isl_basic_map_from_local_space(
 	__isl_take isl_local_space *ls)
 {
 	int i;
-	int n_div;
+	isl_size n_div;
 	isl_basic_map *bmap;
 
+	n_div = isl_local_space_dim(ls, isl_dim_div);
+	if (n_div < 0)
+		ls = isl_local_space_free(ls);
 	if (!ls)
 		return NULL;
 
-	n_div = isl_local_space_dim(ls, isl_dim_div);
 	bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
 					n_div, 0, 2 * n_div);
 
@@ -504,22 +569,69 @@ __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
 	return isl_space_copy(set->dim);
 }
 
-__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)
+/* Return the space of "map".
+ * This may be either a copy or the space itself
+ * if there is only one reference to "map".
+ * This allows the space to be modified inplace
+ * if both the map and its space have only a single reference.
+ * The caller is not allowed to modify "map" between this call and
+ * a subsequent call to isl_map_restore_space.
+ * The only exception is that isl_map_free can be called instead.
+ */
+static __isl_give isl_space *isl_map_take_space(__isl_keep isl_map *map)
 {
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
+	isl_space *space;
+
+	if (!map)
 		return NULL;
-	bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
-	if (!bmap->dim)
+	if (map->ref != 1)
+		return isl_map_get_space(map);
+	space = map->dim;
+	map->dim = NULL;
+	return space;
+}
+
+/* Set the space of "map" to "space", where the space of "map" may be missing
+ * due to a preceding call to isl_map_take_space.
+ * However, in this case, "map" only has a single reference and
+ * then the call to isl_map_cow has no effect.
+ */
+static __isl_give isl_map *isl_map_restore_space(__isl_take isl_map *map,
+	__isl_take isl_space *space)
+{
+	if (!map || !space)
 		goto error;
-	bmap = isl_basic_map_finalize(bmap);
-	return bmap;
+
+	if (map->dim == space) {
+		isl_space_free(space);
+		return map;
+	}
+
+	map = isl_map_cow(map);
+	if (!map)
+		goto error;
+	isl_space_free(map->dim);
+	map->dim = space;
+
+	return map;
 error:
-	isl_basic_map_free(bmap);
+	isl_map_free(map);
+	isl_space_free(space);
 	return NULL;
 }
 
+__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)
+{
+	isl_space *space;
+
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_set_tuple_name(space, type, s);
+	bmap = isl_basic_map_restore_space(bmap, space);
+	bmap = isl_basic_map_finalize(bmap);
+	return bmap;
+}
+
 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
 	__isl_take isl_basic_set *bset, const char *s)
 {
@@ -536,21 +648,22 @@ __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
 	enum isl_dim_type type, const char *s)
 {
 	int i;
+	isl_space *space;
 
 	map = isl_map_cow(map);
 	if (!map)
 		return NULL;
 
-	map->dim = isl_space_set_tuple_name(map->dim, type, s);
-	if (!map->dim)
-		goto error;
-
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
 		if (!map->p[i])
 			goto error;
 	}
 
+	space = isl_map_take_space(map);
+	space = isl_space_set_tuple_name(space, type, s);
+	map = isl_map_restore_space(map, space);
+
 	return map;
 error:
 	isl_map_free(map);
@@ -563,17 +676,13 @@ __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)
 {
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		goto error;
-	bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
-	if (!bmap->dim)
-		return isl_basic_map_free(bmap);
+	isl_space *space;
+
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_set_tuple_id(space, type, id);
+	bmap = isl_basic_map_restore_space(bmap, space);
 	bmap = isl_basic_map_finalize(bmap);
 	return bmap;
-error:
-	isl_id_free(id);
-	return NULL;
 }
 
 /* Replace the identifier of the tuple by "id".
@@ -607,16 +716,13 @@ __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
 	enum isl_dim_type type, __isl_take isl_id *id)
 {
-	map = isl_map_cow(map);
-	if (!map)
-		goto error;
+	isl_space *space;
 
-	map->dim = isl_space_set_tuple_id(map->dim, type, id);
+	space = isl_map_take_space(map);
+	space = isl_space_set_tuple_id(space, type, id);
+	map = isl_map_restore_space(map, space);
 
-	return isl_map_reset_space(map, isl_space_copy(map->dim));
-error:
-	isl_id_free(id);
-	return NULL;
+	return isl_map_reset_space(map, isl_map_get_space(map));
 }
 
 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
@@ -628,13 +734,13 @@ __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
 	enum isl_dim_type type)
 {
-	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
+	isl_space *space;
 
-	map->dim = isl_space_reset_tuple_id(map->dim, type);
+	space = isl_map_take_space(map);
+	space = isl_space_reset_tuple_id(space, type);
+	map = isl_map_restore_space(map, space);
 
-	return isl_map_reset_space(map, isl_space_copy(map->dim));
+	return isl_map_reset_space(map, isl_map_get_space(map));
 }
 
 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
@@ -731,37 +837,34 @@ __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)
 {
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
-	bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
-	if (!bmap->dim)
-		goto error;
+	isl_space *space;
+
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_set_dim_name(space, type, pos, s);
+	bmap = isl_basic_map_restore_space(bmap, space);
 	return isl_basic_map_finalize(bmap);
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
 	enum isl_dim_type type, unsigned pos, const char *s)
 {
 	int i;
+	isl_space *space;
 
 	map = isl_map_cow(map);
 	if (!map)
 		return NULL;
 
-	map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
-	if (!map->dim)
-		goto error;
-
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
 		if (!map->p[i])
 			goto error;
 	}
 
+	space = isl_map_take_space(map);
+	space = isl_space_set_dim_name(space, type, pos, s);
+	map = isl_map_restore_space(map, space);
+
 	return map;
 error:
 	isl_map_free(map);
@@ -824,16 +927,13 @@ __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
 __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)
 {
-	map = isl_map_cow(map);
-	if (!map)
-		goto error;
+	isl_space *space;
 
-	map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
+	space = isl_map_take_space(map);
+	space = isl_space_set_dim_id(space, type, pos, id);
+	map = isl_map_restore_space(map, space);
 
-	return isl_map_reset_space(map, isl_space_copy(map->dim));
-error:
-	isl_id_free(id);
-	return NULL;
+	return isl_map_reset_space(map, isl_map_get_space(map));
 }
 
 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
@@ -891,22 +991,21 @@ int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
  */
 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
 {
-	unsigned nparam;
-	unsigned d;
-	unsigned n_div;
+	isl_size nparam;
+	isl_size d;
+	isl_size n_div;
 	int pos1;
 	int pos2;
 
-	if (!bset)
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	d = isl_basic_set_dim(bset, isl_dim_set);
+	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	if (nparam < 0 || d < 0 || n_div < 0)
 		return isl_bool_error;
 
 	if (!isl_int_is_zero(bset->eq[i][0]))
 		return isl_bool_false;
 
-	nparam = isl_basic_set_dim(bset, isl_dim_param);
-	d = isl_basic_set_dim(bset, isl_dim_set);
-	n_div = isl_basic_set_dim(bset, isl_dim_div);
-
 	if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
 		return isl_bool_false;
 	pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
@@ -1016,7 +1115,7 @@ int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
 {
 	isl_bool has_rational = isl_bool_true;
-	unsigned total;
+	isl_size total;
 
 	if (!bmap)
 		return isl_bool_error;
@@ -1026,9 +1125,9 @@ isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
 		return isl_bool_false;
 	bmap = isl_basic_map_copy(bmap);
 	bmap = isl_basic_map_implicit_equalities(bmap);
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return isl_bool_error;
-	total = isl_basic_map_total_dim(bmap);
 	if (bmap->n_eq == total) {
 		int i, j;
 		for (i = 0; i < bmap->n_eq; ++i) {
@@ -1104,16 +1203,21 @@ isl_bool isl_map_is_params(__isl_keep isl_map *map)
 	return isl_space_is_params(map->dim);
 }
 
-static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
-		struct isl_basic_map *bmap, unsigned extra,
-		unsigned n_eq, unsigned n_ineq)
+static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
+	__isl_take isl_basic_map *bmap, unsigned extra,
+	unsigned n_eq, unsigned n_ineq)
 {
 	int i;
-	size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
+	isl_space *space = isl_basic_map_peek_space(bmap);
+	isl_size n_var = isl_space_dim(space, isl_dim_all);
+	size_t row_size = 1 + n_var + extra;
 
 	bmap->ctx = ctx;
 	isl_ctx_ref(ctx);
 
+	if (n_var < 0)
+		return isl_basic_map_free(bmap);
+
 	bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
 	if (isl_blk_is_error(bmap->block))
 		goto error;
@@ -1186,21 +1290,21 @@ __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
 	return NULL;
 }
 
-struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
+__isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
 		unsigned extra, unsigned n_eq, unsigned n_ineq)
 {
 	struct isl_basic_map *bmap;
 
-	if (!dim)
+	if (!space)
 		return NULL;
-	bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
+	bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
 	if (!bmap)
 		goto error;
-	bmap->dim = dim;
+	bmap->dim = space;
 
-	return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
+	return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -1219,27 +1323,37 @@ struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
 	return bmap;
 }
 
-static void dup_constraints(
-		struct isl_basic_map *dst, struct isl_basic_map *src)
+static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
+	__isl_keep isl_basic_map *src)
 {
 	int i;
-	unsigned total = isl_basic_map_total_dim(src);
+	isl_size total = isl_basic_map_dim(src, isl_dim_all);
+
+	if (!dst || total < 0)
+		return isl_basic_map_free(dst);
 
 	for (i = 0; i < src->n_eq; ++i) {
 		int j = isl_basic_map_alloc_equality(dst);
+		if (j < 0)
+			return isl_basic_map_free(dst);
 		isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
 	}
 
 	for (i = 0; i < src->n_ineq; ++i) {
 		int j = isl_basic_map_alloc_inequality(dst);
+		if (j < 0)
+			return isl_basic_map_free(dst);
 		isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
 	}
 
 	for (i = 0; i < src->n_div; ++i) {
 		int j = isl_basic_map_alloc_div(dst);
+		if (j < 0)
+			return isl_basic_map_free(dst);
 		isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
 	}
 	ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
+	return dst;
 }
 
 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
@@ -1250,9 +1364,9 @@ __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
 		return NULL;
 	dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
+	dup = dup_constraints(dup, bmap);
 	if (!dup)
 		return NULL;
-	dup_constraints(dup, bmap);
 	dup->flags = bmap->flags;
 	dup->sample = isl_vec_copy(bmap->sample);
 	return dup;
@@ -1341,22 +1455,49 @@ static int room_for_con(struct isl_basic_map *bmap, unsigned n)
 	return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
 }
 
-/* Check that "map" has only named parameters, reporting an error
- * if it does not.
+/* Check that "bset" does not involve any parameters.
  */
-isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
+isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
 {
-	return isl_space_check_named_params(isl_map_peek_space(map));
+	isl_size nparam;
+
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (nparam < 0)
+		return isl_stat_error;
+	if (nparam != 0)
+		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
+			"basic set should not have any parameters",
+			return isl_stat_error);
+	return isl_stat_ok;
 }
 
-/* Check that "bmap" has only named parameters, reporting an error
- * if it does not.
+/* Check that "bset" does not involve any local variables.
  */
-static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
+isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
 {
-	return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
+	isl_size n_div;
+
+	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	if (n_div < 0)
+		return isl_stat_error;
+	if (n_div != 0)
+		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
+			"basic set should not have any local variables",
+			return isl_stat_error);
+	return isl_stat_ok;
 }
 
+#undef TYPE
+#define TYPE isl_map
+
+#include "isl_check_named_params_templ.c"
+
+#undef TYPE
+#define TYPE isl_basic_map
+
+static
+#include "isl_check_named_params_templ.c"
+
 /* Check that "bmap1" and "bmap2" have the same parameters,
  * reporting an error if they do not.
  */
@@ -1374,40 +1515,32 @@ static isl_stat isl_basic_map_check_equal_params(
 	return isl_stat_ok;
 }
 
-__isl_give isl_map *isl_map_align_params_map_map_and(
-	__isl_take isl_map *map1, __isl_take isl_map *map2,
-	__isl_give isl_map *(*fn)(__isl_take isl_map *map1,
-				    __isl_take isl_map *map2))
+#undef TYPE
+#define TYPE	isl_map
+
+#include "isl_align_params_bin_templ.c"
+
+#undef SUFFIX
+#define SUFFIX	set
+#undef ARG1
+#define ARG1	isl_map
+#undef ARG2
+#define ARG2	isl_set
+
+#include "isl_align_params_templ.c"
+
+isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
+	__isl_keep isl_map *map2,
+	isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
 {
+	isl_bool r;
+
 	if (!map1 || !map2)
-		goto error;
+		return isl_bool_error;
 	if (isl_map_has_equal_params(map1, map2))
 		return fn(map1, map2);
 	if (isl_map_check_named_params(map1) < 0)
-		goto error;
-	if (isl_map_check_named_params(map2) < 0)
-		goto error;
-	map1 = isl_map_align_params(map1, isl_map_get_space(map2));
-	map2 = isl_map_align_params(map2, isl_map_get_space(map1));
-	return fn(map1, map2);
-error:
-	isl_map_free(map1);
-	isl_map_free(map2);
-	return NULL;
-}
-
-isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
-	__isl_keep isl_map *map2,
-	isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
-{
-	isl_bool r;
-
-	if (!map1 || !map2)
-		return isl_bool_error;
-	if (isl_map_has_equal_params(map1, map2))
-		return fn(map1, map2);
-	if (isl_map_check_named_params(map1) < 0)
-		return isl_bool_error;
+		return isl_bool_error;
 	if (isl_map_check_named_params(map2) < 0)
 		return isl_bool_error;
 	map1 = isl_map_copy(map1);
@@ -1422,14 +1555,16 @@ isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
 
 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
 {
+	isl_size total;
 	struct isl_ctx *ctx;
-	if (!bmap)
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return -1;
 	ctx = bmap->ctx;
 	isl_assert(ctx, room_for_con(bmap, 1), return -1);
 	isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
 			return -1);
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
@@ -1448,7 +1583,7 @@ int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
 		bmap->eq--;
 		return 0;
 	}
-	isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
+	isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,
 		      bmap->extra - bmap->n_div);
 	return bmap->n_eq++;
 }
@@ -1458,33 +1593,44 @@ int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
 	return isl_basic_map_alloc_equality(bset_to_bmap(bset));
 }
 
-int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
+__isl_give isl_basic_map *isl_basic_map_free_equality(
+	__isl_take isl_basic_map *bmap, unsigned n)
 {
 	if (!bmap)
-		return -1;
-	isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
+		return NULL;
+	if (n > bmap->n_eq)
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"invalid number of equalities",
+			isl_basic_map_free(bmap));
 	bmap->n_eq -= n;
-	return 0;
+	return bmap;
 }
 
-int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
+__isl_give isl_basic_set *isl_basic_set_free_equality(
+	__isl_take isl_basic_set *bset, unsigned n)
 {
-	return isl_basic_map_free_equality(bset_to_bmap(bset), n);
+	return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),
+							    n));
 }
 
+/* Drop the equality constraint at position "pos",
+ * preserving the order of the other equality constraints.
+ */
 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
 {
 	isl_int *t;
+	int r;
+
 	if (!bmap)
 		return -1;
 	isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
 
-	if (pos != bmap->n_eq - 1) {
-		t = bmap->eq[pos];
-		bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
-		bmap->eq[bmap->n_eq - 1] = t;
-	}
+	t = bmap->eq[pos];
 	bmap->n_eq--;
+	for (r = pos; r < bmap->n_eq; ++r)
+		bmap->eq[r] = bmap->eq[r + 1];
+	bmap->eq[bmap->n_eq] = t;
+
 	return 0;
 }
 
@@ -1508,7 +1654,7 @@ void isl_basic_map_inequality_to_equality(
 	bmap->n_ineq--;
 	bmap->eq--;
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
 }
@@ -1520,17 +1666,19 @@ static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
 
 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
 {
+	isl_size total;
 	struct isl_ctx *ctx;
-	if (!bmap)
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return -1;
 	ctx = bmap->ctx;
 	isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
-	isl_seq_clr(bmap->ineq[bmap->n_ineq] +
-		      1 + isl_basic_map_total_dim(bmap),
+	isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,
 		      bmap->extra - bmap->n_div);
 	return bmap->n_ineq++;
 }
@@ -1540,18 +1688,24 @@ int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
 	return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
 }
 
-int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
+__isl_give isl_basic_map *isl_basic_map_free_inequality(
+	__isl_take isl_basic_map *bmap, unsigned n)
 {
 	if (!bmap)
-		return -1;
-	isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
+		return NULL;
+	if (n > bmap->n_ineq)
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"invalid number of inequalities",
+			return isl_basic_map_free(bmap));
 	bmap->n_ineq -= n;
-	return 0;
+	return bmap;
 }
 
-int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
+__isl_give isl_basic_set *isl_basic_set_free_inequality(
+	__isl_take isl_basic_set *bset, unsigned n)
 {
-	return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
+	return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),
+							    n));
 }
 
 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
@@ -1565,7 +1719,7 @@ int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
 		t = bmap->ineq[pos];
 		bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
 		bmap->ineq[bmap->n_ineq - 1] = t;
-		ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+		ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
 	}
 	bmap->n_ineq--;
 	return 0;
@@ -1579,15 +1733,25 @@ int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
 	isl_int *eq)
 {
+	isl_bool empty;
+	isl_size total;
 	int k;
 
+	empty = isl_basic_map_plain_is_empty(bmap);
+	if (empty < 0)
+		return isl_basic_map_free(bmap);
+	if (empty)
+		return bmap;
+
+	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
-	if (!bmap)
-		return NULL;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	k = isl_basic_map_alloc_equality(bmap);
 	if (k < 0)
 		goto error;
-	isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_cpy(bmap->eq[k], eq, 1 + total);
 	return bmap;
 error:
 	isl_basic_map_free(bmap);
@@ -1603,15 +1767,18 @@ __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
 	isl_int *ineq)
 {
+	isl_size total;
 	int k;
 
+	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
-	if (!bmap)
-		return NULL;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	k = isl_basic_map_alloc_inequality(bmap);
 	if (k < 0)
 		goto error;
-	isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);
 	return bmap;
 error:
 	isl_basic_map_free(bmap);
@@ -1626,11 +1793,13 @@ __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
 
 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
 {
-	if (!bmap)
+	isl_size total;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return -1;
 	isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
-	isl_seq_clr(bmap->div[bmap->n_div] +
-		      1 + 1 + isl_basic_map_total_dim(bmap),
+	isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,
 		      bmap->extra - bmap->n_div);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
 	return bmap->n_div++;
@@ -1641,22 +1810,18 @@ int isl_basic_set_alloc_div(struct isl_basic_set *bset)
 	return isl_basic_map_alloc_div(bset_to_bmap(bset));
 }
 
+#undef TYPE
+#define TYPE	isl_basic_map
+#include "check_type_range_templ.c"
+
 /* Check that there are "n" dimensions of type "type" starting at "first"
- * in "bmap".
+ * in "bset".
  */
-static isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
+isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
-	unsigned dim;
-
-	if (!bmap)
-		return isl_stat_error;
-	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,
-			"position or range out of bounds",
-			return isl_stat_error);
-	return isl_stat_ok;
+	return isl_basic_map_check_range(bset_to_bmap(bset),
+					type, first, n);
 }
 
 /* Insert an extra integer division, prescribed by "div", to "bmap"
@@ -1669,19 +1834,20 @@ __isl_give isl_basic_map *isl_basic_map_insert_div(
 	__isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
 {
 	int i, k;
+	isl_size total;
 
 	bmap = isl_basic_map_cow(bmap);
-	if (!bmap || !div)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0 || !div)
 		return isl_basic_map_free(bmap);
 
-	if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
+	if (div->size != 1 + 1 + total)
 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
 			"unexpected size", return isl_basic_map_free(bmap));
 	if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
 		return isl_basic_map_free(bmap);
 
-	bmap = isl_basic_map_extend_space(bmap,
-					isl_basic_map_get_space(bmap), 1, 0, 2);
+	bmap = isl_basic_map_extend(bmap, 1, 0, 2);
 	k = isl_basic_map_alloc_div(bmap);
 	if (k < 0)
 		return isl_basic_map_free(bmap);
@@ -1689,7 +1855,7 @@ __isl_give isl_basic_map *isl_basic_map_insert_div(
 	isl_int_set_si(bmap->div[k][div->size], 0);
 
 	for (i = k; i > pos; --i)
-		isl_basic_map_swap_div(bmap, i, i - 1);
+		bmap = isl_basic_map_swap_div(bmap, i, i - 1);
 
 	return bmap;
 }
@@ -1703,143 +1869,66 @@ isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
 	return isl_stat_ok;
 }
 
-/* Copy constraint from src to dst, putting the vars of src at offset
- * dim_off in dst and the divs of src at offset div_off in dst.
- * If both sets are actually map, then dim_off applies to the input
- * variables.
- */
-static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
-			    struct isl_basic_map *src_map, isl_int *src,
-			    unsigned in_off, unsigned out_off, unsigned div_off)
-{
-	unsigned src_nparam = isl_basic_map_dim(src_map, isl_dim_param);
-	unsigned dst_nparam = isl_basic_map_dim(dst_map, isl_dim_param);
-	unsigned src_in = isl_basic_map_dim(src_map, isl_dim_in);
-	unsigned dst_in = isl_basic_map_dim(dst_map, isl_dim_in);
-	unsigned src_out = isl_basic_map_dim(src_map, isl_dim_out);
-	unsigned dst_out = isl_basic_map_dim(dst_map, isl_dim_out);
-	isl_int_set(dst[0], src[0]);
-	isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
-	if (dst_nparam > src_nparam)
-		isl_seq_clr(dst+1+src_nparam,
-				dst_nparam - src_nparam);
-	isl_seq_clr(dst+1+dst_nparam, in_off);
-	isl_seq_cpy(dst+1+dst_nparam+in_off,
-		    src+1+src_nparam,
-		    isl_min(dst_in-in_off, src_in));
-	if (dst_in-in_off > src_in)
-		isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
-				dst_in - in_off - src_in);
-	isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
-	isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
-		    src+1+src_nparam+src_in,
-		    isl_min(dst_out-out_off, src_out));
-	if (dst_out-out_off > src_out)
-		isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
-				dst_out - out_off - src_out);
-	isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
-	isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
-		    src+1+src_nparam+src_in+src_out,
-		    isl_min(dst_map->extra-div_off, src_map->n_div));
-	if (dst_map->n_div-div_off > src_map->n_div)
-		isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
-				div_off+src_map->n_div,
-				dst_map->n_div - div_off - src_map->n_div);
-}
-
-static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
-		     struct isl_basic_map *src_map, isl_int *src,
-		     unsigned in_off, unsigned out_off, unsigned div_off)
-{
-	isl_int_set(dst[0], src[0]);
-	copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
-}
-
 static __isl_give isl_basic_map *add_constraints(
 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
 	unsigned i_pos, unsigned o_pos)
 {
-	int i;
-	unsigned div_off;
+	isl_size total, n_param, n_in, n_out, n_div;
+	unsigned o_in, o_out;
+	isl_ctx *ctx;
+	isl_space *space;
+	struct isl_dim_map *dim_map;
 
-	if (!bmap1 || !bmap2)
+	space = isl_basic_map_peek_space(bmap2);
+	if (!bmap1 || !space)
 		goto error;
 
-	div_off = bmap1->n_div;
-
-	for (i = 0; i < bmap2->n_eq; ++i) {
-		int i1 = isl_basic_map_alloc_equality(bmap1);
-		if (i1 < 0)
-			goto error;
-		copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
-				i_pos, o_pos, div_off);
-	}
-
-	for (i = 0; i < bmap2->n_ineq; ++i) {
-		int i1 = isl_basic_map_alloc_inequality(bmap1);
-		if (i1 < 0)
-			goto error;
-		copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
-				i_pos, o_pos, div_off);
-	}
-
-	for (i = 0; i < bmap2->n_div; ++i) {
-		int i1 = isl_basic_map_alloc_div(bmap1);
-		if (i1 < 0)
-			goto error;
-		copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
-			 i_pos, o_pos, div_off);
-	}
-
-	isl_basic_map_free(bmap2);
-
-	return bmap1;
+	total = isl_basic_map_dim(bmap1, isl_dim_all);
+	n_param = isl_basic_map_dim(bmap2, isl_dim_param);
+	n_in = isl_basic_map_dim(bmap2, isl_dim_in);
+	o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
+	n_out = isl_basic_map_dim(bmap2, isl_dim_out);
+	o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
+	n_div = isl_basic_map_dim(bmap2, isl_dim_div);
+	if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
+		goto error;
+	ctx = isl_basic_map_get_ctx(bmap1);
+	dim_map = isl_dim_map_alloc(ctx, total + n_div);
+	isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
+	isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
+	isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
+	isl_dim_map_div(dim_map, bmap2, total);
 
+	return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
 error:
 	isl_basic_map_free(bmap1);
 	isl_basic_map_free(bmap2);
 	return NULL;
 }
 
-struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
-		struct isl_basic_set *bset2, unsigned pos)
-{
-	return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
-						bset_to_bmap(bset2), 0, pos));
-}
-
-__isl_give isl_basic_map *isl_basic_map_extend_space(
-	__isl_take isl_basic_map *base, __isl_take isl_space *dim,
+__isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
 	unsigned extra, unsigned n_eq, unsigned n_ineq)
 {
+	isl_space *space;
 	struct isl_basic_map *ext;
 	unsigned flags;
 	int dims_ok;
 
-	if (!dim)
-		goto error;
-
 	if (!base)
 		goto error;
 
-	dims_ok = isl_space_is_equal(base->dim, dim) &&
-		  base->extra >= base->n_div + extra;
+	dims_ok = base->extra >= base->n_div + extra;
 
 	if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
-		       room_for_ineq(base, n_ineq)) {
-		isl_space_free(dim);
+		       room_for_ineq(base, n_ineq))
 		return base;
-	}
 
-	isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
-	isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
-	isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
 	extra += base->extra;
 	n_eq += base->n_eq;
 	n_ineq += base->n_ineq;
 
-	ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
-	dim = NULL;
+	space = isl_basic_map_get_space(base);
+	ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
 	if (!ext)
 		goto error;
 
@@ -1855,55 +1944,21 @@ __isl_give isl_basic_map *isl_basic_map_extend_space(
 	return ext;
 
 error:
-	isl_space_free(dim);
 	isl_basic_map_free(base);
 	return NULL;
 }
 
-__isl_give isl_basic_set *isl_basic_set_extend_space(
-	__isl_take isl_basic_set *base,
-		__isl_take isl_space *dim, unsigned extra,
-		unsigned n_eq, unsigned n_ineq)
+__isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
+	unsigned extra, unsigned n_eq, unsigned n_ineq)
 {
-	return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
-						    dim, extra, n_eq, n_ineq));
+	return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
+						    extra, n_eq, n_ineq));
 }
 
 struct isl_basic_map *isl_basic_map_extend_constraints(
 		struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
 {
-	if (!base)
-		return NULL;
-	return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
-					0, n_eq, n_ineq);
-}
-
-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 *bmap;
-	isl_space *dim;
-
-	if (!base)
-		return NULL;
-	dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
-	if (!dim)
-		goto error;
-
-	bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
-	return bmap;
-error:
-	isl_basic_map_free(base);
-	return NULL;
-}
-
-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)
-{
-	return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
-					nparam, 0, dim, extra, n_eq, n_ineq));
+	return isl_basic_map_extend(base, 0, n_eq, n_ineq);
 }
 
 struct isl_basic_set *isl_basic_set_extend_constraints(
@@ -1989,12 +2044,9 @@ static __isl_give isl_basic_map *isl_basic_map_swap_vars(
 	int i;
 	struct isl_blk blk;
 
-	if (!bmap)
+	if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
 		goto error;
 
-	isl_assert(bmap->ctx,
-		pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
-
 	if (n1 == 0 || n2 == 0)
 		return bmap;
 
@@ -2020,7 +2072,7 @@ static __isl_give isl_basic_map *isl_basic_map_swap_vars(
 
 	isl_blk_free(bmap->ctx, blk);
 
-	ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
+	ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
 	bmap = isl_basic_map_gauss(bmap, NULL);
 	return isl_basic_map_finalize(bmap);
 error:
@@ -2032,16 +2084,21 @@ __isl_give isl_basic_map *isl_basic_map_set_to_empty(
 	__isl_take isl_basic_map *bmap)
 {
 	int i = 0;
-	unsigned total;
-	if (!bmap)
-		goto error;
-	total = isl_basic_map_total_dim(bmap);
+	isl_size total;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
 		return isl_basic_map_free(bmap);
-	isl_basic_map_free_inequality(bmap, bmap->n_ineq);
-	if (bmap->n_eq > 0)
-		isl_basic_map_free_equality(bmap, bmap->n_eq-1);
-	else {
+	bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
+	if (!bmap)
+		return NULL;
+	if (bmap->n_eq > 0) {
+		bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);
+		if (!bmap)
+			return NULL;
+	} else {
 		i = isl_basic_map_alloc_equality(bmap);
 		if (i < 0)
 			goto error;
@@ -2141,10 +2198,15 @@ static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
  * div definitions accordingly.
  */
-void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
+__isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
+	int a, int b)
 {
 	int i;
-	unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
+	isl_size off;
+
+	off = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (off < 0)
+		return isl_basic_map_free(bmap);
 
 	swap_div(bmap, a, b);
 
@@ -2156,15 +2218,9 @@ void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
 
 	for (i = 0; i < bmap->n_div; ++i)
 		isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
-}
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
 
-/* Swap divs "a" and "b" in "bset" and adjust the constraints and
- * div definitions accordingly.
- */
-void isl_basic_set_swap_div(__isl_keep isl_basic_set *bset, int a, int b)
-{
-	isl_basic_map_swap_div(bset, a, b);
+	return bmap;
 }
 
 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
@@ -2213,51 +2269,47 @@ static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
 	return NULL;
 }
 
+#undef TYPE
+#define TYPE	isl_map
+static
+#include "check_type_range_templ.c"
+
 /* Check that there are "n" dimensions of type "type" starting at "first"
- * in "map".
+ * in "set".
  */
-static isl_stat isl_map_check_range(__isl_keep isl_map *map,
+static isl_stat isl_set_check_range(__isl_keep isl_set *set,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
-	if (!map)
-		return isl_stat_error;
-	if (first + n > isl_map_dim(map, type) || first + n < first)
-		isl_die(isl_map_get_ctx(map), isl_error_invalid,
-			"position or range out of bounds",
-			return isl_stat_error);
-	return isl_stat_ok;
+	return isl_map_check_range(set_to_map(set), type, first, n);
 }
 
 /* Drop "n" dimensions of type "type" starting at "first".
+ * Perform the core computation, without cowing or
+ * simplifying and finalizing the result.
  *
  * In principle, this frees up some extra variables as the number
  * of columns remains constant, but we would have to extend
  * the div array too as the number of rows in this array is assumed
  * to be equal to extra.
  */
-__isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
-	enum isl_dim_type type, unsigned first, unsigned n)
+__isl_give isl_basic_map *isl_basic_map_drop_core(
+	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
+	unsigned first, unsigned n)
 {
 	int i;
-	unsigned dim;
 	unsigned offset;
 	unsigned left;
+	isl_size total;
 
-	if (!bmap)
-		goto error;
-
-	dim = isl_basic_map_dim(bmap, type);
-	isl_assert(bmap->ctx, first + n <= dim, goto error);
-
-	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
-		return bmap;
+	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
+		return isl_basic_map_free(bmap);
 
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 
 	offset = isl_basic_map_offset(bmap, type) + first;
-	left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
+	left = total - (offset - 1) - n;
 	for (i = 0; i < bmap->n_eq; ++i)
 		constraint_drop_vars(bmap->eq[i]+offset, n, left);
 
@@ -2270,20 +2322,42 @@ __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
 	if (type == isl_dim_div) {
 		bmap = move_divs_last(bmap, first, n);
 		if (!bmap)
-			goto error;
+			return NULL;
 		if (isl_basic_map_free_div(bmap, n) < 0)
 			return isl_basic_map_free(bmap);
 	} else
 		bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
 	if (!bmap->dim)
-		goto error;
+		return isl_basic_map_free(bmap);
+
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
+	return bmap;
+}
+
+/* Drop "n" dimensions of type "type" starting at "first".
+ *
+ * In principle, this frees up some extra variables as the number
+ * of columns remains constant, but we would have to extend
+ * the div array too as the number of rows in this array is assumed
+ * to be equal to extra.
+ */
+__isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	if (!bmap)
+		return NULL;
+	if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
+		return bmap;
+
+	bmap = isl_basic_map_cow(bmap);
+	if (!bmap)
+		return NULL;
+
+	bmap = isl_basic_map_drop_core(bmap, type, first, n);
 
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
 	bmap = isl_basic_map_simplify(bmap);
 	return isl_basic_map_finalize(bmap);
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
@@ -2307,6 +2381,7 @@ __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
 	int i;
+	isl_space *space;
 
 	if (isl_map_check_range(map, type, first, n) < 0)
 		return isl_map_free(map);
@@ -2316,9 +2391,6 @@ __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
 	map = isl_map_cow(map);
 	if (!map)
 		goto error;
-	map->dim = isl_space_drop_dims(map->dim, type, first, n);
-	if (!map->dim)
-		goto error;
 
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
@@ -2327,6 +2399,10 @@ __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
 	}
 	map = isl_map_unmark_normalized(map);
 
+	space = isl_map_take_space(map);
+	space = isl_space_drop_dims(space, type, first, n);
+	map = isl_map_restore_space(map, space);
+
 	return map;
 error:
 	isl_map_free(map);
@@ -2339,54 +2415,16 @@ __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
 	return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
 }
 
-/*
- * We don't cow, as the div is assumed to be redundant.
+/* Drop the integer division at position "div", which is assumed
+ * not to appear in any of the constraints or
+ * in any of the other integer divisions.
+ *
+ * Since the integer division is redundant, there is no need to cow.
  */
 __isl_give isl_basic_map *isl_basic_map_drop_div(
 	__isl_take isl_basic_map *bmap, unsigned div)
 {
-	int i;
-	unsigned pos;
-
-	if (!bmap)
-		goto error;
-
-	pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
-
-	isl_assert(bmap->ctx, div < bmap->n_div, goto error);
-
-	for (i = 0; i < bmap->n_eq; ++i)
-		constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
-
-	for (i = 0; i < bmap->n_ineq; ++i) {
-		if (!isl_int_is_zero(bmap->ineq[i][pos])) {
-			isl_basic_map_drop_inequality(bmap, i);
-			--i;
-			continue;
-		}
-		constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
-	}
-
-	for (i = 0; i < bmap->n_div; ++i)
-		constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
-
-	if (div != bmap->n_div - 1) {
-		int j;
-		isl_int *t = bmap->div[div];
-
-		for (j = div; j < bmap->n_div - 1; ++j)
-			bmap->div[j] = bmap->div[j+1];
-
-		bmap->div[bmap->n_div - 1] = t;
-	}
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
-	if (isl_basic_map_free_div(bmap, 1) < 0)
-		return isl_basic_map_free(bmap);
-
-	return bmap;
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
+	return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
 }
 
 /* Eliminate the specified n dimensions starting at first from the
@@ -2442,10 +2480,12 @@ __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
 __isl_give isl_basic_map *isl_basic_map_remove_divs(
 	__isl_take isl_basic_map *bmap)
 {
-	if (!bmap)
-		return NULL;
-	bmap = isl_basic_map_eliminate_vars(bmap,
-			    isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
+	isl_size v_div;
+
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(bmap);
+	bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
 	if (!bmap)
 		return NULL;
 	bmap->n_div = 0;
@@ -2628,7 +2668,6 @@ static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
 		isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
 	}
 
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
 	return bmap;
 error:
 	isl_basic_map_free(bmap);
@@ -2686,7 +2725,7 @@ static __isl_give isl_basic_map *insert_bounds_on_div(
 	int i;
 	int check_lb, check_ub;
 	isl_int v;
-	unsigned total;
+	isl_size v_div;
 
 	if (!bmap)
 		return NULL;
@@ -2694,12 +2733,14 @@ static __isl_give isl_basic_map *insert_bounds_on_div(
 	if (isl_int_is_zero(bmap->div[div][0]))
 		return bmap;
 
-	total = isl_space_dim(bmap->dim, isl_dim_all);
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(bmap);
 
 	check_lb = 0;
 	check_ub = 0;
 	for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
-		int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
+		int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
 		if (s > 0)
 			check_ub = 1;
 		if (s < 0)
@@ -2712,10 +2753,10 @@ static __isl_give isl_basic_map *insert_bounds_on_div(
 	isl_int_init(v);
 
 	for (i = 0; bmap && i < bmap->n_ineq; ++i) {
-		if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
+		if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
 			continue;
 
-		bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
+		bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
 							check_lb, check_ub);
 	}
 
@@ -2858,8 +2899,12 @@ isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
 
 /* Drop all constraints in bmap that involve any of the dimensions
  * first to first+n-1.
+ * This function only performs the actual removal of constraints.
+ *
+ * This function should not call finalize since it is used by
+ * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
  */
-static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
+__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
 	__isl_take isl_basic_map *bmap, unsigned first, unsigned n)
 {
 	int i;
@@ -2875,21 +2920,23 @@ static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
 	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);
+		if (isl_basic_map_drop_equality(bmap, i) < 0)
+			return isl_basic_map_free(bmap);
 	}
 
 	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);
+		if (isl_basic_map_drop_inequality(bmap, i) < 0)
+			return isl_basic_map_free(bmap);
 	}
 
-	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.
+ * This function only performs the actual removal of constraints.
  */
 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
 	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
@@ -2923,13 +2970,15 @@ __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
 	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);
+		if (isl_basic_map_drop_equality(bmap, i) < 0)
+			return isl_basic_map_free(bmap);
 	}
 
 	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);
+		if (isl_basic_map_drop_inequality(bmap, i) < 0)
+			return isl_basic_map_free(bmap);
 	}
 
 	bmap = isl_basic_map_add_known_div_constraints(bmap);
@@ -2964,7 +3013,9 @@ __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
 
 	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);
+	bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
+	bmap = isl_basic_map_add_known_div_constraints(bmap);
+	return bmap;
 }
 
 /* Drop all constraints in bset that involve any of the dimensions
@@ -3191,125 +3242,11 @@ struct isl_map *isl_map_remove_inputs(struct isl_map *map,
 	return isl_map_remove_dims(map, isl_dim_in, first, n);
 }
 
-static void dump_term(struct isl_basic_map *bmap,
-			isl_int c, int pos, FILE *out)
+void isl_basic_set_print_internal(struct isl_basic_set *bset,
+	FILE *out, int indent)
 {
-	const char *name;
-	unsigned in = isl_basic_map_dim(bmap, isl_dim_in);
-	unsigned dim = in + isl_basic_map_dim(bmap, isl_dim_out);
-	unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
-	if (!pos)
-		isl_int_print(out, c, 0);
-	else {
-		if (!isl_int_is_one(c))
-			isl_int_print(out, c, 0);
-		if (pos < 1 + nparam) {
-			name = isl_space_get_dim_name(bmap->dim,
-						isl_dim_param, pos - 1);
-			if (name)
-				fprintf(out, "%s", name);
-			else
-				fprintf(out, "p%d", pos - 1);
-		} else if (pos < 1 + nparam + in)
-			fprintf(out, "i%d", pos - 1 - nparam);
-		else if (pos < 1 + nparam + dim)
-			fprintf(out, "o%d", pos - 1 - nparam - in);
-		else
-			fprintf(out, "e%d", pos - 1 - nparam - dim);
-	}
-}
+	isl_printer *p;
 
-static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
-				int sign, FILE *out)
-{
-	int i;
-	int first;
-	unsigned len = 1 + isl_basic_map_total_dim(bmap);
-	isl_int v;
-
-	isl_int_init(v);
-	for (i = 0, first = 1; i < len; ++i) {
-		if (isl_int_sgn(c[i]) * sign <= 0)
-			continue;
-		if (!first)
-			fprintf(out, " + ");
-		first = 0;
-		isl_int_abs(v, c[i]);
-		dump_term(bmap, v, i, out);
-	}
-	isl_int_clear(v);
-	if (first)
-		fprintf(out, "0");
-}
-
-static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
-				const char *op, FILE *out, int indent)
-{
-	int i;
-
-	fprintf(out, "%*s", indent, "");
-
-	dump_constraint_sign(bmap, c, 1, out);
-	fprintf(out, " %s ", op);
-	dump_constraint_sign(bmap, c, -1, out);
-
-	fprintf(out, "\n");
-
-	for (i = bmap->n_div; i < bmap->extra; ++i) {
-		if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
-			continue;
-		fprintf(out, "%*s", indent, "");
-		fprintf(out, "ERROR: unused div coefficient not zero\n");
-		abort();
-	}
-}
-
-static void dump_constraints(struct isl_basic_map *bmap,
-				isl_int **c, unsigned n,
-				const char *op, FILE *out, int indent)
-{
-	int i;
-
-	for (i = 0; i < n; ++i)
-		dump_constraint(bmap, c[i], op, out, indent);
-}
-
-static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
-{
-	int j;
-	int first = 1;
-	unsigned total = isl_basic_map_total_dim(bmap);
-
-	for (j = 0; j < 1 + total; ++j) {
-		if (isl_int_is_zero(exp[j]))
-			continue;
-		if (!first && isl_int_is_pos(exp[j]))
-			fprintf(out, "+");
-		dump_term(bmap, exp[j], j, out);
-		first = 0;
-	}
-}
-
-static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
-{
-	int i;
-
-	dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
-	dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
-
-	for (i = 0; i < bmap->n_div; ++i) {
-		fprintf(out, "%*s", indent, "");
-		fprintf(out, "e%d = [(", i);
-		dump_affine(bmap, bmap->div[i]+1, out);
-		fprintf(out, ")/");
-		isl_int_print(out, bmap->div[i][0], 0);
-		fprintf(out, "]\n");
-	}
-}
-
-void isl_basic_set_print_internal(struct isl_basic_set *bset,
-	FILE *out, int indent)
-{
 	if (!bset) {
 		fprintf(out, "null basic set\n");
 		return;
@@ -3319,12 +3256,21 @@ void isl_basic_set_print_internal(struct isl_basic_set *bset,
 	fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
 			bset->ref, bset->dim->nparam, bset->dim->n_out,
 			bset->extra, bset->flags);
-	dump(bset_to_bmap(bset), out, indent);
+
+	p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
+	p = isl_printer_set_dump(p, 1);
+	p = isl_printer_set_indent(p, indent);
+	p = isl_printer_start_line(p);
+	p = isl_printer_print_basic_set(p, bset);
+	p = isl_printer_end_line(p);
+	isl_printer_free(p);
 }
 
 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
 	FILE *out, int indent)
 {
+	isl_printer *p;
+
 	if (!bmap) {
 		fprintf(out, "null basic map\n");
 		return;
@@ -3336,30 +3282,39 @@ void isl_basic_map_print_internal(struct isl_basic_map *bmap,
 		bmap->ref,
 		bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
 		bmap->extra, bmap->flags, bmap->dim->n_id);
-	dump(bmap, out, indent);
+
+	p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
+	p = isl_printer_set_dump(p, 1);
+	p = isl_printer_set_indent(p, indent);
+	p = isl_printer_start_line(p);
+	p = isl_printer_print_basic_map(p, bmap);
+	p = isl_printer_end_line(p);
+	isl_printer_free(p);
 }
 
-int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
+__isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
+	unsigned pos)
 {
-	unsigned total;
-	if (!bmap)
-		return -1;
-	total = isl_basic_map_total_dim(bmap);
-	isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
+	isl_size total;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
+	if (pos >= bmap->n_ineq)
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"invalid position", return isl_basic_map_free(bmap));
 	isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
 	isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
-	return 0;
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
+	return bmap;
 }
 
 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
 	unsigned flags)
 {
-	if (!space)
-		return NULL;
-	if (isl_space_dim(space, isl_dim_in) != 0)
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"set cannot have input dimensions", goto error);
+	if (isl_space_check_is_set(space) < 0)
+		goto error;
 	return isl_map_alloc_space(space, n, flags);
 error:
 	isl_space_free(space);
@@ -3471,22 +3426,43 @@ void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
 	}
 }
 
+/* Check that the space of "bset" is the same as that of the domain of "bmap".
+ */
+static isl_stat isl_basic_map_check_compatible_domain(
+	__isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
+{
+	isl_bool ok;
+
+	ok = isl_basic_map_compatible_domain(bmap, bset);
+	if (ok < 0)
+		return isl_stat_error;
+	if (!ok)
+		isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
+			"incompatible spaces", return isl_stat_error);
+
+	return isl_stat_ok;
+}
+
 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
 {
 	struct isl_basic_map *bmap_domain;
+	isl_size dim;
 
 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
 		goto error;
 
-	if (isl_space_dim(bset->dim, isl_dim_set) != 0)
-		isl_assert(bset->ctx,
-		    isl_basic_map_compatible_domain(bmap, bset), goto error);
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		goto error;
+	if (dim != 0 &&
+	    isl_basic_map_check_compatible_domain(bmap, bset) < 0)
+		goto error;
 
 	bmap = isl_basic_map_cow(bmap);
 	if (!bmap)
 		goto error;
-	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+	bmap = isl_basic_map_extend(bmap,
 			bset->n_div, bset->n_eq, bset->n_ineq);
 	bmap_domain = isl_basic_map_from_domain(bset);
 	bmap = add_constraints(bmap, bmap_domain, 0, 0);
@@ -3520,12 +3496,15 @@ __isl_give isl_basic_map *isl_basic_map_intersect_range(
 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
 {
 	struct isl_basic_map *bmap_range;
+	isl_size dim;
 
 	if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
 		goto error;
 
-	if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
-	    isl_basic_map_check_compatible_range(bmap, bset) < 0)
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		goto error;
+	if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)
 		goto error;
 
 	if (isl_basic_set_plain_is_universe(bset)) {
@@ -3536,7 +3515,7 @@ __isl_give isl_basic_map *isl_basic_map_intersect_range(
 	bmap = isl_basic_map_cow(bmap);
 	if (!bmap)
 		goto error;
-	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+	bmap = isl_basic_map_extend(bmap,
 			bset->n_div, bset->n_eq, bset->n_ineq);
 	bmap_range = bset_to_bmap(bset);
 	bmap = add_constraints(bmap, bmap_range, 0, 0);
@@ -3553,20 +3532,20 @@ isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
 	__isl_keep isl_vec *vec)
 {
 	int i;
-	unsigned total;
+	isl_size total;
 	isl_int s;
 
-	if (!bmap || !vec)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0 || !vec)
 		return isl_bool_error;
 
-	total = 1 + isl_basic_map_total_dim(bmap);
-	if (total != vec->size)
+	if (1 + total != vec->size)
 		return isl_bool_false;
 
 	isl_int_init(s);
 
 	for (i = 0; i < bmap->n_eq; ++i) {
-		isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
+		isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);
 		if (!isl_int_is_zero(s)) {
 			isl_int_clear(s);
 			return isl_bool_false;
@@ -3574,7 +3553,7 @@ isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
 	}
 
 	for (i = 0; i < bmap->n_ineq; ++i) {
-		isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
+		isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);
 		if (isl_int_is_neg(s)) {
 			isl_int_clear(s);
 			return isl_bool_false;
@@ -3596,19 +3575,25 @@ __isl_give isl_basic_map *isl_basic_map_intersect(
 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
 {
 	struct isl_vec *sample = NULL;
+	isl_space *space1, *space2;
+	isl_size dim1, dim2, nparam1, nparam2;
 
 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
 		goto error;
-	if (isl_space_dim(bmap1->dim, isl_dim_all) ==
-				isl_space_dim(bmap1->dim, isl_dim_param) &&
-	    isl_space_dim(bmap2->dim, isl_dim_all) !=
-				isl_space_dim(bmap2->dim, isl_dim_param))
+	space1 = isl_basic_map_peek_space(bmap1);
+	space2 = isl_basic_map_peek_space(bmap2);
+	dim1 = isl_space_dim(space1, isl_dim_all);
+	dim2 = isl_space_dim(space2, isl_dim_all);
+	nparam1 = isl_space_dim(space1, isl_dim_param);
+	nparam2 = isl_space_dim(space2, isl_dim_param);
+	if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)
+		goto error;
+	if (dim1 == nparam1 && dim2 != nparam2)
 		return isl_basic_map_intersect(bmap2, bmap1);
 
-	if (isl_space_dim(bmap2->dim, isl_dim_all) !=
-					isl_space_dim(bmap2->dim, isl_dim_param))
-		isl_assert(bmap1->ctx,
-			    isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
+	if (dim2 != nparam2 &&
+	    isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
+		goto error;
 
 	if (isl_basic_map_plain_is_empty(bmap1)) {
 		isl_basic_map_free(bmap2);
@@ -3631,7 +3616,7 @@ __isl_give isl_basic_map *isl_basic_map_intersect(
 	bmap1 = isl_basic_map_cow(bmap1);
 	if (!bmap1)
 		goto error;
-	bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
+	bmap1 = isl_basic_map_extend(bmap1,
 			bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
 	bmap1 = add_constraints(bmap1, bmap2, 0, 0);
 
@@ -3688,7 +3673,6 @@ static __isl_give isl_map *map_intersect_add_constraint(
 		isl_map_free(map2);
 		return map1;
 	}
-	map1->p[0] = isl_basic_map_cow(map1->p[0]);
 	if (map2->p[0]->n_eq == 1)
 		map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
 	else
@@ -3725,6 +3709,7 @@ static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
 	isl_bool equal;
 	isl_map *result;
 	int i, j;
+	isl_size dim2, nparam2;
 
 	if (!map1 || !map2)
 		goto error;
@@ -3757,8 +3742,11 @@ static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
 		return map1;
 	}
 
-	if (isl_space_dim(map2->dim, isl_dim_all) !=
-				isl_space_dim(map2->dim, isl_dim_param))
+	dim2 = isl_map_dim(map2, isl_dim_all);
+	nparam2 = isl_map_dim(map2, isl_dim_param);
+	if (dim2 < 0 || nparam2 < 0)
+		goto error;
+	if (dim2 != nparam2)
 		isl_assert(map1->ctx,
 			    isl_space_is_equal(map1->dim, map2->dim), goto error);
 
@@ -3794,11 +3782,8 @@ static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
-	if (!map1 || !map2)
+	if (isl_map_check_equal_space(map1, map2) < 0)
 		goto error;
-	if (!isl_space_is_equal(map1->dim, map2->dim))
-		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
-			"spaces don't match", goto error);
 	return map_intersect_internal(map1, map2);
 error:
 	isl_map_free(map1);
@@ -3809,7 +3794,8 @@ static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
-	return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
+	isl_map_align_params_bin(&map1, &map2);
+	return map_intersect(map1, map2);
 }
 
 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
@@ -3821,18 +3807,13 @@ struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
 /* map_intersect_internal accepts intersections
  * with parameter domains, so we can just call that function.
  */
-static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
-		__isl_take isl_set *params)
+__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
+	__isl_take isl_set *params)
 {
+	isl_map_align_params_set(&map, &params);
 	return map_intersect_internal(map, params);
 }
 
-__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
-}
-
 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
 		__isl_take isl_set *params)
 {
@@ -3842,7 +3823,8 @@ __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
 {
 	isl_space *space;
-	unsigned pos, n1, n2;
+	unsigned pos;
+	isl_size n1, n2;
 
 	if (!bmap)
 		return NULL;
@@ -3853,10 +3835,39 @@ __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
 	pos = isl_basic_map_offset(bmap, isl_dim_in);
 	n1 = isl_basic_map_dim(bmap, isl_dim_in);
 	n2 = isl_basic_map_dim(bmap, isl_dim_out);
+	if (n1 < 0 || n2 < 0)
+		bmap = isl_basic_map_free(bmap);
 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
 	return isl_basic_map_reset_space(bmap, space);
 }
 
+/* Given a basic map A -> (B -> C), return the corresponding basic map
+ * A -> (C -> B).
+ */
+static __isl_give isl_basic_map *isl_basic_map_range_reverse(
+	__isl_take isl_basic_map *bmap)
+{
+	isl_space *space;
+	isl_size offset, n1, n2;
+
+	space = isl_basic_map_peek_space(bmap);
+	if (isl_space_check_range_is_wrapping(space) < 0)
+		return isl_basic_map_free(bmap);
+	offset = isl_basic_map_var_offset(bmap, isl_dim_out);
+	n1 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_in);
+	n2 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_out);
+	if (offset < 0 || n1 < 0 || n2 < 0)
+		return isl_basic_map_free(bmap);
+
+	bmap = isl_basic_map_swap_vars(bmap, 1 + offset, n1, n2);
+
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_range_reverse(space);
+	bmap = isl_basic_map_restore_space(bmap, space);
+
+	return bmap;
+}
+
 static __isl_give isl_basic_map *basic_map_space_reset(
 	__isl_take isl_basic_map *bmap, enum isl_dim_type type)
 {
@@ -3877,35 +3888,50 @@ __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_bool rational;
+	isl_bool rational, is_empty;
 	isl_space *res_space;
 	struct isl_basic_map *res;
 	struct isl_dim_map *dim_map;
-	unsigned total, off;
+	isl_size total;
+	unsigned off;
 	enum isl_dim_type t;
 
 	if (n == 0)
 		return basic_map_space_reset(bmap, type);
 
+	is_empty = isl_basic_map_plain_is_empty(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (is_empty < 0 || total < 0)
+		return isl_basic_map_free(bmap);
 	res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
 					type, pos, n);
 	if (!res_space)
 		return isl_basic_map_free(bmap);
+	if (is_empty) {
+		isl_basic_map_free(bmap);
+		return isl_basic_map_empty(res_space);
+	}
 
-	total = isl_basic_map_total_dim(bmap) + n;
-	dim_map = isl_dim_map_alloc(bmap->ctx, total);
+	dim_map = isl_dim_map_alloc(bmap->ctx, total + n);
 	off = 0;
 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+		isl_size dim;
+
 		if (t != type) {
 			isl_dim_map_dim(dim_map, bmap->dim, t, off);
 		} else {
-			unsigned size = isl_basic_map_dim(bmap, t);
+			isl_size size = isl_basic_map_dim(bmap, t);
+			if (size < 0)
+				dim_map = isl_dim_map_free(dim_map);
 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
 						0, pos, off);
 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
 						pos, size - pos, off + pos + n);
 		}
-		off += isl_space_dim(res_space, t);
+		dim = isl_space_dim(res_space, t);
+		if (dim < 0)
+			dim_map = isl_dim_map_free(dim_map);
+		off += dim;
 	}
 	isl_dim_map_div(dim_map, bmap, off);
 
@@ -3916,11 +3942,6 @@ __isl_give isl_basic_map *isl_basic_map_insert_dims(
 		res = isl_basic_map_free(res);
 	if (rational)
 		res = isl_basic_map_set_rational(res);
-	if (isl_basic_map_plain_is_empty(bmap)) {
-		isl_basic_map_free(bmap);
-		free(dim_map);
-		return isl_basic_map_set_to_empty(res);
-	}
 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
 	return isl_basic_map_finalize(res);
 }
@@ -3935,10 +3956,12 @@ __isl_give isl_basic_set *isl_basic_set_insert_dims(
 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
 		enum isl_dim_type type, unsigned n)
 {
-	if (!bmap)
-		return NULL;
-	return isl_basic_map_insert_dims(bmap, type,
-					isl_basic_map_dim(bmap, type), n);
+	isl_size dim;
+
+	dim = isl_basic_map_dim(bmap, type);
+	if (dim < 0)
+		return isl_basic_map_free(bmap);
+	return isl_basic_map_insert_dims(bmap, type, dim, n);
 }
 
 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
@@ -3971,6 +3994,7 @@ __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
 		enum isl_dim_type type, unsigned pos, unsigned n)
 {
 	int i;
+	isl_space *space;
 
 	if (n == 0)
 		return map_space_reset(map, type);
@@ -3979,16 +4003,16 @@ __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
 	if (!map)
 		return NULL;
 
-	map->dim = isl_space_insert_dims(map->dim, type, pos, n);
-	if (!map->dim)
-		goto error;
-
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
 		if (!map->p[i])
 			goto error;
 	}
 
+	space = isl_map_take_space(map);
+	space = isl_space_insert_dims(space, type, pos, n);
+	map = isl_map_restore_space(map, space);
+
 	return map;
 error:
 	isl_map_free(map);
@@ -4004,9 +4028,12 @@ __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
 		enum isl_dim_type type, unsigned n)
 {
-	if (!map)
-		return NULL;
-	return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
+	isl_size dim;
+
+	dim = isl_map_dim(map, type);
+	if (dim < 0)
+		return isl_map_free(map);
+	return isl_map_insert_dims(map, type, dim, n);
 }
 
 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
@@ -4026,10 +4053,12 @@ __isl_give isl_basic_map *isl_basic_map_move_dims(
 	enum isl_dim_type dst_type, unsigned dst_pos,
 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
 {
+	isl_space *space;
 	struct isl_dim_map *dim_map;
 	struct isl_basic_map *res;
 	enum isl_dim_type t;
-	unsigned total, off;
+	isl_size total;
+	unsigned off;
 
 	if (!bmap)
 		return NULL;
@@ -4050,45 +4079,45 @@ __isl_give isl_basic_map *isl_basic_map_move_dims(
 	if (pos(bmap->dim, dst_type) + dst_pos ==
 	    pos(bmap->dim, src_type) + src_pos +
 					    ((src_type < dst_type) ? n : 0)) {
-		bmap = isl_basic_map_cow(bmap);
-		if (!bmap)
-			return NULL;
-
-		bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
+		space = isl_basic_map_take_space(bmap);
+		space = isl_space_move_dims(space, dst_type, dst_pos,
 						src_type, src_pos, n);
-		if (!bmap->dim)
-			goto error;
-
+		bmap = isl_basic_map_restore_space(bmap, space);
 		bmap = isl_basic_map_finalize(bmap);
 
 		return bmap;
 	}
 
-	total = isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
 
 	off = 0;
+	space = isl_basic_map_peek_space(bmap);
 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
-		unsigned size = isl_space_dim(bmap->dim, t);
+		isl_size size = isl_space_dim(space, t);
+		if (size < 0)
+			dim_map = isl_dim_map_free(dim_map);
 		if (t == dst_type) {
-			isl_dim_map_dim_range(dim_map, bmap->dim, t,
+			isl_dim_map_dim_range(dim_map, space, t,
 					    0, dst_pos, off);
 			off += dst_pos;
-			isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
+			isl_dim_map_dim_range(dim_map, space, src_type,
 					    src_pos, n, off);
 			off += n;
-			isl_dim_map_dim_range(dim_map, bmap->dim, t,
+			isl_dim_map_dim_range(dim_map, space, t,
 					    dst_pos, size - dst_pos, off);
 			off += size - dst_pos;
 		} else if (t == src_type) {
-			isl_dim_map_dim_range(dim_map, bmap->dim, t,
+			isl_dim_map_dim_range(dim_map, space, t,
 					    0, src_pos, off);
 			off += src_pos;
-			isl_dim_map_dim_range(dim_map, bmap->dim, t,
+			isl_dim_map_dim_range(dim_map, space, t,
 					src_pos + n, size - src_pos - n, off);
 			off += size - src_pos - n;
 		} else {
-			isl_dim_map_dim(dim_map, bmap->dim, t, off);
+			isl_dim_map_dim(dim_map, space, t, off);
 			off += size;
 		}
 	}
@@ -4097,15 +4126,14 @@ __isl_give isl_basic_map *isl_basic_map_move_dims(
 	res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
 	bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
-	if (!bmap)
-		goto error;
-
-	bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_move_dims(space, dst_type, dst_pos,
 					src_type, src_pos, n);
-	if (!bmap->dim)
+	bmap = isl_basic_map_restore_space(bmap, space);
+	if (!bmap)
 		goto error;
 
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
 	bmap = isl_basic_map_gauss(bmap, NULL);
 	bmap = isl_basic_map_finalize(bmap);
 
@@ -4144,6 +4172,7 @@ __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
 	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
 {
 	int i;
+	isl_space *space;
 
 	if (n == 0) {
 		map = isl_map_reset(map, src_type);
@@ -4163,10 +4192,6 @@ __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
 	if (!map)
 		return NULL;
 
-	map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
-	if (!map->dim)
-		goto error;
-
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_move_dims(map->p[i],
 						dst_type, dst_pos,
@@ -4175,6 +4200,11 @@ __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
 			goto error;
 	}
 
+	space = isl_map_take_space(map);
+	space = isl_space_move_dims(space, dst_type, dst_pos,
+					    src_type, src_pos, n);
+	map = isl_map_restore_space(map, space);
+
 	return map;
 error:
 	isl_map_free(map);
@@ -4188,34 +4218,41 @@ __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
+	isl_space *space;
 	struct isl_dim_map *dim_map;
 	struct isl_basic_map *res;
 	enum isl_dim_type t;
-	unsigned total, off;
+	isl_size total;
+	unsigned off;
 
 	if (!bmap)
 		return NULL;
-	if (pos(bmap->dim, type) + first + n ==
-				1 + isl_space_dim(bmap->dim, isl_dim_all))
+	if (isl_basic_map_offset(bmap, type) + first + n ==
+				isl_basic_map_offset(bmap, isl_dim_div))
 		return bmap;
 
-	total = isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
 
 	off = 0;
+	space = isl_basic_map_peek_space(bmap);
 	for (t = isl_dim_param; t <= isl_dim_out; ++t) {
-		unsigned size = isl_space_dim(bmap->dim, t);
+		isl_size size = isl_space_dim(space, t);
+		if (size < 0)
+			dim_map = isl_dim_map_free(dim_map);
 		if (t == type) {
-			isl_dim_map_dim_range(dim_map, bmap->dim, t,
+			isl_dim_map_dim_range(dim_map, space, t,
 					    0, first, off);
 			off += first;
-			isl_dim_map_dim_range(dim_map, bmap->dim, t,
+			isl_dim_map_dim_range(dim_map, space, t,
 					    first, n, total - bmap->n_div - n);
-			isl_dim_map_dim_range(dim_map, bmap->dim, t,
+			isl_dim_map_dim_range(dim_map, space, t,
 					    first + n, size - (first + n), off);
 			off += size - (first + n);
 		} else {
-			isl_dim_map_dim(dim_map, bmap->dim, t, off);
+			isl_dim_map_dim(dim_map, space, t, off);
 			off += size;
 		}
 	}
@@ -4247,7 +4284,7 @@ static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
 	if (!bmap)
 		return NULL;
 
-	row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
+	row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
 	old = bmap->block2.data;
 	bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
 					(bmap->extra + n) * (1 + row_size));
@@ -4284,7 +4321,7 @@ static __isl_give isl_basic_map *drop_irrelevant_constraints(
 {
 	int i;
 	int *groups;
-	unsigned dim, n_div;
+	isl_size dim, n_div;
 	isl_bool non_empty;
 
 	non_empty = isl_basic_map_plain_is_non_empty(bmap);
@@ -4295,6 +4332,8 @@ static __isl_give isl_basic_map *drop_irrelevant_constraints(
 
 	dim = isl_basic_map_dim(bmap, isl_dim_all);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (dim < 0 || n_div < 0)
+		return isl_basic_map_free(bmap);
 	groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
 	if (!groups)
 		return isl_basic_map_free(bmap);
@@ -4321,6 +4360,7 @@ __isl_give isl_basic_map *isl_basic_map_project_out(
 		enum isl_dim_type type, unsigned first, unsigned n)
 {
 	isl_bool empty;
+	isl_space *space;
 
 	if (n == 0)
 		return basic_map_space_reset(bmap, type);
@@ -4348,18 +4388,13 @@ __isl_give isl_basic_map *isl_basic_map_project_out(
 	bmap = move_last(bmap, type, first, n);
 	bmap = isl_basic_map_cow(bmap);
 	bmap = insert_div_rows(bmap, n);
-	if (!bmap)
-		return NULL;
 
-	bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
-	if (!bmap->dim)
-		goto error;
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_drop_dims(space, type, first, n);
+	bmap = isl_basic_map_restore_space(bmap, space);
 	bmap = isl_basic_map_simplify(bmap);
 	bmap = isl_basic_map_drop_redundant_divs(bmap);
 	return isl_basic_map_finalize(bmap);
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 /* Turn the n dimensions of type type, starting at first
@@ -4379,6 +4414,7 @@ __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
 		enum isl_dim_type type, unsigned first, unsigned n)
 {
 	int i;
+	isl_space *space;
 
 	if (n == 0)
 		return map_space_reset(map, type);
@@ -4390,33 +4426,41 @@ __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
 	if (!map)
 		return NULL;
 
-	map->dim = isl_space_drop_dims(map->dim, type, first, n);
-	if (!map->dim)
-		goto error;
-
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
 		if (!map->p[i])
 			goto error;
 	}
 
+	if (map->n > 1)
+		ISL_F_CLR(map, ISL_MAP_DISJOINT);
+	map = isl_map_unmark_normalized(map);
+
+	space = isl_map_take_space(map);
+	space = isl_space_drop_dims(space, type, first, n);
+	map = isl_map_restore_space(map, space);
+
 	return map;
 error:
 	isl_map_free(map);
 	return NULL;
 }
 
+#undef TYPE
+#define TYPE	isl_map
+#include "isl_project_out_all_params_templ.c"
+
 /* Turn all the dimensions of type "type", except the "n" starting at "first"
  * into existentially quantified variables.
  */
 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
-	unsigned dim;
+	isl_size dim;
 
-	if (isl_map_check_range(map, type, first, n) < 0)
-		return isl_map_free(map);
 	dim = isl_map_dim(map, type);
+	if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)
+		return isl_map_free(map);
 	map = isl_map_project_out(map, type, first + n, dim - (first + n));
 	map = isl_map_project_out(map, type, 0, first);
 	return map;
@@ -4432,6 +4476,62 @@ __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
 						type, first, n));
 }
 
+/* If "set" involves a parameter with identifier "id",
+ * then turn it into an existentially quantified variable.
+ */
+__isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
+	__isl_take isl_id *id)
+{
+	int pos;
+
+	if (!set || !id)
+		goto error;
+	pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
+	isl_id_free(id);
+	if (pos < 0)
+		return set;
+	return isl_set_project_out(set, isl_dim_param, pos, 1);
+error:
+	isl_set_free(set);
+	isl_id_free(id);
+	return NULL;
+}
+
+/* If "set" involves any of the parameters with identifiers in "list",
+ * then turn them into existentially quantified variables.
+ */
+__isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
+	__isl_take isl_id_list *list)
+{
+	int i;
+	isl_size n;
+
+	n = isl_id_list_size(list);
+	if (n < 0)
+		goto error;
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+
+		id = isl_id_list_get_at(list, i);
+		set = isl_set_project_out_param_id(set, id);
+	}
+
+	isl_id_list_free(list);
+	return set;
+error:
+	isl_id_list_free(list);
+	isl_set_free(set);
+	return NULL;
+}
+
+/* Project out all parameters from "set" by existentially quantifying
+ * over them.
+ */
+__isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set)
+{
+	return set_from_map(isl_map_project_out_all_params(set_to_map(set)));
+}
+
 /* Return a map that projects the elements in "set" onto their
  * "n" set dimensions starting at "first".
  * "type" should be equal to isl_dim_set.
@@ -4440,18 +4540,13 @@ __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
 	int i;
-	int dim;
 	isl_map *map;
 
-	if (!set)
-		return NULL;
 	if (type != isl_dim_set)
 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
 			"only set dimensions can be projected out", goto error);
-	dim = isl_set_dim(set, isl_dim_set);
-	if (first + n > dim || first + n < first)
-		isl_die(isl_set_get_ctx(set), isl_error_invalid,
-			"index out of bounds", goto error);
+	if (isl_set_check_range(set, type, first, n) < 0)
+		return isl_set_free(set);
 
 	map = isl_map_from_domain(set);
 	map = isl_map_add_dims(map, isl_dim_out, n);
@@ -4464,15 +4559,20 @@ __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
 	return NULL;
 }
 
-static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
+static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
+	unsigned n)
 {
 	int i, j;
+	isl_size total;
 
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	for (i = 0; i < n; ++i) {
 		j = isl_basic_map_alloc_div(bmap);
 		if (j < 0)
 			goto error;
-		isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
+		isl_seq_clr(bmap->div[j], 1 + 1 + total);
 	}
 	return bmap;
 error:
@@ -4483,9 +4583,10 @@ static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
 struct isl_basic_map *isl_basic_map_apply_range(
 		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
 {
-	isl_space *dim_result = NULL;
+	isl_space *space_result = NULL;
 	struct isl_basic_map *bmap;
-	unsigned n_in, n_out, n, nparam, total, pos;
+	isl_size n_in, n_out, n, nparam;
+	unsigned total, pos;
 	struct isl_dim_map *dim_map1, *dim_map2;
 
 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
@@ -4495,13 +4596,15 @@ struct isl_basic_map *isl_basic_map_apply_range(
 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
 			"spaces don't match", goto error);
 
-	dim_result = isl_space_join(isl_space_copy(bmap1->dim),
-				  isl_space_copy(bmap2->dim));
-
 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
 	n_out = isl_basic_map_dim(bmap2, isl_dim_out);
 	n = isl_basic_map_dim(bmap1, isl_dim_out);
 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
+	if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)
+		goto error;
+
+	space_result = isl_space_join(isl_basic_map_get_space(bmap1),
+				  isl_basic_map_get_space(bmap2));
 
 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
@@ -4515,7 +4618,7 @@ struct isl_basic_map *isl_basic_map_apply_range(
 	isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
 	isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
 
-	bmap = isl_basic_map_alloc_space(dim_result,
+	bmap = isl_basic_map_alloc_space(space_result,
 			bmap1->n_div + bmap2->n_div + n,
 			bmap1->n_eq + bmap2->n_eq,
 			bmap1->n_ineq + bmap2->n_ineq);
@@ -4531,15 +4634,12 @@ struct isl_basic_map *isl_basic_map_apply_range(
 	return NULL;
 }
 
-struct isl_basic_set *isl_basic_set_apply(
-		struct isl_basic_set *bset, struct isl_basic_map *bmap)
+__isl_give isl_basic_set *isl_basic_set_apply(__isl_take isl_basic_set *bset,
+	__isl_take isl_basic_map *bmap)
 {
-	if (!bset || !bmap)
+	if (isl_basic_map_check_compatible_domain(bmap, bset) < 0)
 		goto error;
 
-	isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
-		    goto error);
-
 	return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
 							bmap));
 error:
@@ -4573,20 +4673,20 @@ struct isl_basic_map *isl_basic_map_apply_domain(
 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
 	__isl_take isl_basic_map *bmap2)
 {
-	unsigned n_in, n_out, nparam, total, pos;
+	isl_size n_in, n_out, nparam;
+	unsigned total, pos;
 	struct isl_basic_map *bmap = NULL;
 	struct isl_dim_map *dim_map1, *dim_map2;
 	int i;
 
-	if (!bmap1 || !bmap2)
+	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
 		goto error;
 
-	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
-		goto error);
-
 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
 	n_in = isl_basic_map_dim(bmap1, isl_dim_in);
 	n_out = isl_basic_map_dim(bmap1, isl_dim_out);
+	if (nparam < 0 || n_in < 0 || n_out < 0)
+		goto error;
 
 	total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
@@ -4635,11 +4735,9 @@ __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
 	struct isl_map *result;
 	int i, j;
 
-	if (!map1 || !map2)
+	if (isl_map_check_equal_space(map1, map2) < 0)
 		goto error;
 
-	isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
-
 	result = isl_map_alloc_space(isl_space_copy(map1->dim),
 				map1->n * map2->n, 0);
 	if (!result)
@@ -4677,13 +4775,14 @@ __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
 {
 	int i, j;
-	unsigned off, n;
+	unsigned off;
+	isl_size n;
 
 	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
-
 	n = isl_basic_map_dim(bmap, isl_dim_out);
+	if (n < 0)
+		return isl_basic_map_free(bmap);
+
 	off = isl_basic_map_offset(bmap, isl_dim_out);
 	for (i = 0; i < bmap->n_eq; ++i)
 		for (j = 0; j < n; ++j)
@@ -4736,17 +4835,17 @@ __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
 		isl_int d)
 {
-	unsigned n_in, n_out, nparam, total, pos;
+	isl_size n_in, n_out, nparam;
+	unsigned total, pos;
 	struct isl_basic_map *result = NULL;
 	struct isl_dim_map *dim_map;
 	int i;
 
-	if (!bmap)
-		return NULL;
-
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (nparam < 0 || n_in < 0 || n_out < 0)
+		return isl_basic_map_free(bmap);
 
 	total = nparam + n_in + n_out + bmap->n_div + n_out;
 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
@@ -4833,15 +4932,19 @@ static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
 	unsigned pos)
 {
 	int i;
-	unsigned nparam;
-	unsigned n_in;
+	isl_size nparam;
+	isl_size n_in;
+	isl_size total;
 
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	if (total < 0 || nparam < 0 || n_in < 0)
+		return isl_basic_map_free(bmap);
 	i = isl_basic_map_alloc_equality(bmap);
 	if (i < 0)
 		goto error;
-	nparam = isl_basic_map_dim(bmap, isl_dim_param);
-	n_in = isl_basic_map_dim(bmap, isl_dim_in);
-	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->eq[i], 1 + total);
 	isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
 	isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
 	return isl_basic_map_finalize(bmap);
@@ -4856,15 +4959,19 @@ static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
 	unsigned pos)
 {
 	int i;
-	unsigned nparam;
-	unsigned n_in;
+	isl_size nparam;
+	isl_size n_in;
+	isl_size total;
 
-	i = isl_basic_map_alloc_inequality(bmap);
-	if (i < 0)
-		goto error;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
-	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+	if (total < 0 || nparam < 0 || n_in < 0)
+		return isl_basic_map_free(bmap);
+	i = isl_basic_map_alloc_inequality(bmap);
+	if (i < 0)
+		goto error;
+	isl_seq_clr(bmap->ineq[i], 1 + total);
 	isl_int_set_si(bmap->ineq[i][0], -1);
 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
@@ -4880,15 +4987,19 @@ static __isl_give isl_basic_map *var_less_or_equal(
 	__isl_take isl_basic_map *bmap, unsigned pos)
 {
 	int i;
-	unsigned nparam;
-	unsigned n_in;
+	isl_size nparam;
+	isl_size n_in;
+	isl_size total;
 
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	if (total < 0 || nparam < 0 || n_in < 0)
+		return isl_basic_map_free(bmap);
 	i = isl_basic_map_alloc_inequality(bmap);
 	if (i < 0)
 		goto error;
-	nparam = isl_basic_map_dim(bmap, isl_dim_param);
-	n_in = isl_basic_map_dim(bmap, isl_dim_in);
-	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->ineq[i], 1 + total);
 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
 	return isl_basic_map_finalize(bmap);
@@ -4903,15 +5014,19 @@ static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
 	unsigned pos)
 {
 	int i;
-	unsigned nparam;
-	unsigned n_in;
+	isl_size nparam;
+	isl_size n_in;
+	isl_size total;
 
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	if (total < 0 || nparam < 0 || n_in < 0)
+		return isl_basic_map_free(bmap);
 	i = isl_basic_map_alloc_inequality(bmap);
 	if (i < 0)
 		goto error;
-	nparam = isl_basic_map_dim(bmap, isl_dim_param);
-	n_in = isl_basic_map_dim(bmap, isl_dim_in);
-	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->ineq[i], 1 + total);
 	isl_int_set_si(bmap->ineq[i][0], -1);
 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
@@ -4927,15 +5042,19 @@ static __isl_give isl_basic_map *var_more_or_equal(
 	__isl_take isl_basic_map *bmap, unsigned pos)
 {
 	int i;
-	unsigned nparam;
-	unsigned n_in;
+	isl_size nparam;
+	isl_size n_in;
+	isl_size total;
 
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	if (total < 0 || nparam < 0 || n_in < 0)
+		return isl_basic_map_free(bmap);
 	i = isl_basic_map_alloc_inequality(bmap);
 	if (i < 0)
 		goto error;
-	nparam = isl_basic_map_dim(bmap, isl_dim_param);
-	n_in = isl_basic_map_dim(bmap, isl_dim_in);
-	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->ineq[i], 1 + total);
 	isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
 	isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
 	return isl_basic_map_finalize(bmap);
@@ -4945,11 +5064,11 @@ static __isl_give isl_basic_map *var_more_or_equal(
 }
 
 __isl_give isl_basic_map *isl_basic_map_equal(
-	__isl_take isl_space *dim, unsigned n_equal)
+	__isl_take isl_space *space, unsigned n_equal)
 {
 	int i;
 	struct isl_basic_map *bmap;
-	bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
+	bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
 	if (!bmap)
 		return NULL;
 	for (i = 0; i < n_equal && bmap; ++i)
@@ -4957,14 +5076,14 @@ __isl_give isl_basic_map *isl_basic_map_equal(
 	return isl_basic_map_finalize(bmap);
 }
 
-/* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
+/* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
  */
-__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
+__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
 	unsigned pos)
 {
 	int i;
 	struct isl_basic_map *bmap;
-	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
 	if (!bmap)
 		return NULL;
 	for (i = 0; i < pos && bmap; ++i)
@@ -4974,29 +5093,29 @@ __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
 	return isl_basic_map_finalize(bmap);
 }
 
-/* Return a relation on "dim" expressing i_[0..pos] <<= o_[0..pos]
+/* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
  */
 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
-	__isl_take isl_space *dim, unsigned pos)
+	__isl_take isl_space *space, unsigned pos)
 {
 	int i;
 	isl_basic_map *bmap;
 
-	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
 	for (i = 0; i < pos; ++i)
 		bmap = var_equal(bmap, i);
 	bmap = var_less_or_equal(bmap, pos);
 	return isl_basic_map_finalize(bmap);
 }
 
-/* Return a relation on "dim" expressing i_pos > o_pos
+/* Return a relation on "space" expressing i_pos > o_pos
  */
-__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
+__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
 	unsigned pos)
 {
 	int i;
 	struct isl_basic_map *bmap;
-	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
 	if (!bmap)
 		return NULL;
 	for (i = 0; i < pos && bmap; ++i)
@@ -5006,53 +5125,53 @@ __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
 	return isl_basic_map_finalize(bmap);
 }
 
-/* Return a relation on "dim" expressing i_[0..pos] >>= o_[0..pos]
+/* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
  */
 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
-	__isl_take isl_space *dim, unsigned pos)
+	__isl_take isl_space *space, unsigned pos)
 {
 	int i;
 	isl_basic_map *bmap;
 
-	bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+	bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
 	for (i = 0; i < pos; ++i)
 		bmap = var_equal(bmap, i);
 	bmap = var_more_or_equal(bmap, pos);
 	return isl_basic_map_finalize(bmap);
 }
 
-static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
+static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
 	unsigned n, int equal)
 {
 	struct isl_map *map;
 	int i;
 
 	if (n == 0 && equal)
-		return isl_map_universe(dims);
+		return isl_map_universe(space);
 
-	map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
+	map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
 
 	for (i = 0; i + 1 < n; ++i)
 		map = isl_map_add_basic_map(map,
-				  isl_basic_map_less_at(isl_space_copy(dims), i));
+				  isl_basic_map_less_at(isl_space_copy(space), i));
 	if (n > 0) {
 		if (equal)
 			map = isl_map_add_basic_map(map,
-			      isl_basic_map_less_or_equal_at(dims, n - 1));
+			      isl_basic_map_less_or_equal_at(space, n - 1));
 		else
 			map = isl_map_add_basic_map(map,
-			      isl_basic_map_less_at(dims, n - 1));
+			      isl_basic_map_less_at(space, n - 1));
 	} else
-		isl_space_free(dims);
+		isl_space_free(space);
 
 	return map;
 }
 
-static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
+static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
 {
-	if (!dims)
+	if (!space)
 		return NULL;
-	return map_lex_lte_first(dims, dims->n_out, equal);
+	return map_lex_lte_first(space, space->n_out, equal);
 }
 
 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
@@ -5075,38 +5194,38 @@ __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
 	return map_lex_lte(isl_space_map_from_set(set_dim), 1);
 }
 
-static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
+static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
 	unsigned n, int equal)
 {
 	struct isl_map *map;
 	int i;
 
 	if (n == 0 && equal)
-		return isl_map_universe(dims);
+		return isl_map_universe(space);
 
-	map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
+	map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
 
 	for (i = 0; i + 1 < n; ++i)
 		map = isl_map_add_basic_map(map,
-				  isl_basic_map_more_at(isl_space_copy(dims), i));
+				  isl_basic_map_more_at(isl_space_copy(space), i));
 	if (n > 0) {
 		if (equal)
 			map = isl_map_add_basic_map(map,
-			      isl_basic_map_more_or_equal_at(dims, n - 1));
+			      isl_basic_map_more_or_equal_at(space, n - 1));
 		else
 			map = isl_map_add_basic_map(map,
-			      isl_basic_map_more_at(dims, n - 1));
+			      isl_basic_map_more_at(space, n - 1));
 	} else
-		isl_space_free(dims);
+		isl_space_free(space);
 
 	return map;
 }
 
-static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
+static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
 {
-	if (!dims)
+	if (!space)
 		return NULL;
-	return map_lex_gte_first(dims, dims->n_out, equal);
+	return map_lex_gte_first(space, space->n_out, equal);
 }
 
 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
@@ -5209,47 +5328,59 @@ __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
 	return map;
 }
 
-/* For a div d = floor(f/m), add the constraint
+/* For the div d = floor(f/m) at position "div", add the constraint
  *
  *		f - m d >= 0
  */
-static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
-	unsigned pos, isl_int *div)
+static __isl_give isl_basic_map *add_upper_div_constraint(
+	__isl_take isl_basic_map *bmap, unsigned div)
 {
 	int i;
-	unsigned total = isl_basic_map_total_dim(bmap);
+	isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	isl_size n_div;
+	unsigned pos;
 
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (v_div < 0 || n_div < 0)
+		return isl_basic_map_free(bmap);
+	pos = v_div + div;
 	i = isl_basic_map_alloc_inequality(bmap);
 	if (i < 0)
-		return isl_stat_error;
-	isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
-	isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
+		return isl_basic_map_free(bmap);
+	isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
+	isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
 
-	return isl_stat_ok;
+	return bmap;
 }
 
-/* For a div d = floor(f/m), add the constraint
+/* For the div d = floor(f/m) at position "div", add the constraint
  *
  *		-(f-(m-1)) + m d >= 0
  */
-static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
-	unsigned pos, isl_int *div)
+static __isl_give isl_basic_map *add_lower_div_constraint(
+	__isl_take isl_basic_map *bmap, unsigned div)
 {
 	int i;
-	unsigned total = isl_basic_map_total_dim(bmap);
+	isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	isl_size n_div;
+	unsigned pos;
 
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (v_div < 0 || n_div < 0)
+		return isl_basic_map_free(bmap);
+	pos = v_div + div;
 	i = isl_basic_map_alloc_inequality(bmap);
 	if (i < 0)
-		return isl_stat_error;
-	isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
-	isl_int_set(bmap->ineq[i][1 + pos], div[0]);
+		return isl_basic_map_free(bmap);
+	isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
+	isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
 	isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
 	isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
 
-	return isl_stat_ok;
+	return bmap;
 }
 
-/* For a div d = floor(f/m), add the constraints
+/* For the div d = floor(f/m) at position "pos", add the constraints
  *
  *		f - m d >= 0
  *		-(f-(m-1)) + m d >= 0
@@ -5258,30 +5389,12 @@ static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
  *
  *		f - m d >= m
  */
-int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
-	unsigned pos, isl_int *div)
-{
-	if (add_upper_div_constraint(bmap, pos, div) < 0)
-		return -1;
-	if (add_lower_div_constraint(bmap, pos, div) < 0)
-		return -1;
-	return 0;
-}
-
-int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
-	unsigned pos, isl_int *div)
-{
-	return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
-							pos, div);
-}
-
-int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
+__isl_give isl_basic_map *isl_basic_map_add_div_constraints(
+	__isl_take isl_basic_map *bmap, unsigned pos)
 {
-	unsigned total = isl_basic_map_total_dim(bmap);
-	unsigned div_pos = total - bmap->n_div + div;
-
-	return isl_basic_map_add_div_constraints_var(bmap, div_pos,
-							bmap->div[div]);
+	bmap = add_upper_div_constraint(bmap, pos);
+	bmap = add_lower_div_constraint(bmap, pos);
+	return bmap;
 }
 
 /* For each known div d = floor(f/m), add the constraints
@@ -5295,11 +5408,11 @@ int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
 	__isl_take isl_basic_map *bmap)
 {
-	unsigned n_div;
+	isl_size n_div;
 
-	if (!bmap)
-		return NULL;
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_basic_map_free(bmap);
 	if (n_div == 0)
 		return bmap;
 
@@ -5322,27 +5435,20 @@ __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
  *
  * if sign > 0.
  */
-int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
-	unsigned div, int sign)
+__isl_give isl_basic_map *isl_basic_map_add_div_constraint(
+	__isl_take isl_basic_map *bmap, unsigned div, int sign)
 {
-	unsigned total;
-	unsigned div_pos;
-
-	if (!bmap)
-		return -1;
-
-	total = isl_basic_map_total_dim(bmap);
-	div_pos = total - bmap->n_div + div;
-
 	if (sign < 0)
-		return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
+		return add_upper_div_constraint(bmap, div);
 	else
-		return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
+		return add_lower_div_constraint(bmap, div);
 }
 
 __isl_give isl_basic_set *isl_basic_map_underlying_set(
 	__isl_take isl_basic_map *bmap)
 {
+	isl_space *space;
+
 	if (!bmap)
 		goto error;
 	if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
@@ -5352,10 +5458,12 @@ __isl_give isl_basic_set *isl_basic_map_underlying_set(
 		return bset_from_bmap(bmap);
 	bmap = isl_basic_map_cow(bmap);
 	if (!bmap)
-		goto error;
-	bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
-	if (!bmap->dim)
-		goto error;
+		return NULL;
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_underlying(space, bmap->n_div);
+	bmap = isl_basic_map_restore_space(bmap, space);
+	if (!bmap)
+		return NULL;
 	bmap->extra -= bmap->n_div;
 	bmap->n_div = 0;
 	bmap = isl_basic_map_finalize(bmap);
@@ -5377,12 +5485,13 @@ __isl_give isl_basic_set *isl_basic_set_underlying_set(
 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
 	__isl_take isl_basic_map_list *list)
 {
-	int i, n;
-
-	if (!list)
-		return NULL;
+	int i;
+	isl_size n;
 
 	n = isl_basic_map_list_n_basic_map(list);
+	if (n < 0)
+		goto error;
+
 	for (i = 0; i < n; ++i) {
 		isl_basic_map *bmap;
 		isl_basic_set *bset;
@@ -5393,6 +5502,9 @@ __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
 	}
 
 	return list;
+error:
+	isl_basic_map_list_free(list);
+	return NULL;
 }
 
 __isl_give isl_basic_map *isl_basic_map_overlying_set(
@@ -5400,16 +5512,21 @@ __isl_give isl_basic_map *isl_basic_map_overlying_set(
 {
 	struct isl_basic_map *bmap;
 	struct isl_ctx *ctx;
+	isl_size dim, bmap_total;
 	unsigned total;
 	int i;
 
 	if (!bset || !like)
 		goto error;
 	ctx = bset->ctx;
-	isl_assert(ctx, bset->n_div == 0, goto error);
-	isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
-	isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
-			goto error);
+	if (isl_basic_set_check_no_params(bset) < 0 ||
+	    isl_basic_set_check_no_locals(bset) < 0)
+		goto error;
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	bmap_total = isl_basic_map_dim(like, isl_dim_all);
+	if (dim < 0 || bmap_total < 0)
+		goto error;
+	isl_assert(ctx, dim == bmap_total, goto error);
 	if (like->n_div == 0) {
 		isl_space *space = isl_basic_map_get_space(like);
 		isl_basic_map_free(like);
@@ -5418,11 +5535,11 @@ __isl_give isl_basic_map *isl_basic_map_overlying_set(
 	bset = isl_basic_set_cow(bset);
 	if (!bset)
 		goto error;
-	total = bset->dim->n_out + bset->extra;
+	total = dim + bset->extra;
 	bmap = bset_to_bmap(bset);
-	isl_space_free(bmap->dim);
-	bmap->dim = isl_space_copy(like->dim);
-	if (!bmap->dim)
+	isl_space_free(isl_basic_map_take_space(bmap));
+	bmap = isl_basic_map_restore_space(bmap, isl_basic_map_get_space(like));
+	if (!bmap)
 		goto error;
 	bmap->n_div = like->n_div;
 	bmap->extra += like->n_div;
@@ -5520,12 +5637,8 @@ __isl_give isl_basic_map *isl_basic_map_reset_space(
 		isl_space_free(space);
 		return bmap;
 	}
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap || !space)
-		goto error;
-
-	isl_space_free(bmap->dim);
-	bmap->dim = space;
+	isl_space_free(isl_basic_map_take_space(bmap));
+	bmap = isl_basic_map_restore_space(bmap, space);
 
 	bmap = isl_basic_map_finalize(bmap);
 
@@ -5548,12 +5661,12 @@ __isl_give isl_basic_set *isl_basic_set_reset_space(
 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
 	__isl_keep isl_space *space)
 {
-	unsigned dim1, dim2;
+	isl_size dim1, dim2;
 
-	if (!map || !space)
-		return isl_stat_error;
 	dim1 = isl_map_dim(map, isl_dim_all);
 	dim2 = isl_space_dim(space, isl_dim_all);
+	if (dim1 < 0 || dim2 < 0)
+		return isl_stat_error;
 	if (dim1 == dim2)
 		return isl_stat_ok;
 	isl_die(isl_map_get_ctx(map), isl_error_invalid,
@@ -5561,27 +5674,27 @@ static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
 }
 
 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
-	__isl_take isl_space *dim)
+	__isl_take isl_space *space)
 {
 	int i;
 
 	map = isl_map_cow(map);
-	if (!map || !dim)
+	if (!map || !space)
 		goto error;
 
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_reset_space(map->p[i],
-						    isl_space_copy(dim));
+						    isl_space_copy(space));
 		if (!map->p[i])
 			goto error;
 	}
-	isl_space_free(map->dim);
-	map->dim = dim;
+	isl_space_free(isl_map_take_space(map));
+	map = isl_map_restore_space(map, space);
 
 	return map;
 error:
 	isl_map_free(map);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -5628,7 +5741,7 @@ __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
 {
 	isl_bool is_params;
 	isl_space *space;
-	unsigned n;
+	isl_size n;
 
 	is_params = isl_basic_set_is_params(bset);
 	if (is_params < 0)
@@ -5637,6 +5750,8 @@ __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
 		return bset;
 
 	n = isl_basic_set_dim(bset, isl_dim_set);
+	if (n < 0)
+		return isl_basic_set_free(bset);
 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
 	space = isl_basic_set_get_space(bset);
 	space = isl_space_params(space);
@@ -5660,18 +5775,7 @@ __isl_give isl_basic_set *isl_basic_set_from_params(
  */
 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
 {
-	isl_space *space;
-	unsigned n;
-
-	if (isl_set_is_params(set))
-		return set;
-
-	n = isl_set_dim(set, isl_dim_set);
-	set = isl_set_project_out(set, isl_dim_set, 0, n);
-	space = isl_set_get_space(set);
-	space = isl_space_params(space);
-	set = isl_set_reset_space(set, space);
-	return set;
+	return isl_map_params(set_to_map(set));
 }
 
 /* Construct a zero-dimensional set with the given parameter domain.
@@ -5690,28 +5794,30 @@ __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
 {
 	isl_space *space;
-	unsigned n;
+	isl_size n_in, n_out;
 
-	n = isl_map_dim(map, isl_dim_in);
-	map = isl_map_project_out(map, isl_dim_in, 0, n);
-	n = isl_map_dim(map, isl_dim_out);
-	map = isl_map_project_out(map, isl_dim_out, 0, n);
+	n_in = isl_map_dim(map, isl_dim_in);
+	n_out = isl_map_dim(map, isl_dim_out);
+	if (n_in < 0 || n_out < 0)
+		return isl_map_free(map);
+	map = isl_map_project_out(map, isl_dim_in, 0, n_in);
+	map = isl_map_project_out(map, isl_dim_out, 0, n_out);
 	space = isl_map_get_space(map);
 	space = isl_space_params(space);
 	map = isl_map_reset_space(map, space);
 	return map;
 }
 
-struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
+__isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
 {
 	isl_space *space;
-	unsigned n_out;
+	isl_size n_out;
 
-	if (!bmap)
-		return NULL;
+	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (n_out < 0)
+		return isl_basic_map_free(bmap);
 	space = isl_space_domain(isl_basic_map_get_space(bmap));
 
-	n_out = isl_basic_map_dim(bmap, isl_dim_out);
 	bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
 
 	return isl_basic_map_reset_space(bmap, space);
@@ -5754,16 +5860,19 @@ __isl_give isl_basic_map *isl_basic_map_domain_map(
 	__isl_take isl_basic_map *bmap)
 {
 	int i;
-	isl_space *dim;
+	isl_space *space;
 	isl_basic_map *domain;
-	int nparam, n_in, n_out;
+	isl_size nparam, n_in, n_out;
 
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (nparam < 0 || n_in < 0 || n_out < 0)
+		return isl_basic_map_free(bmap);
 
-	dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
-	domain = isl_basic_map_universe(dim);
+	space = isl_basic_map_get_space(bmap);
+	space = isl_space_from_range(isl_space_domain(space));
+	domain = isl_basic_map_universe(space);
 
 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
 	bmap = isl_basic_map_apply_range(bmap, domain);
@@ -5781,16 +5890,19 @@ __isl_give isl_basic_map *isl_basic_map_range_map(
 	__isl_take isl_basic_map *bmap)
 {
 	int i;
-	isl_space *dim;
+	isl_space *space;
 	isl_basic_map *range;
-	int nparam, n_in, n_out;
+	isl_size nparam, n_in, n_out;
 
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (nparam < 0 || n_in < 0 || n_out < 0)
+		return isl_basic_map_free(bmap);
 
-	dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
-	range = isl_basic_map_universe(dim);
+	space = isl_basic_map_get_space(bmap);
+	space = isl_space_from_range(isl_space_range(space));
+	range = isl_basic_map_universe(space);
 
 	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
 	bmap = isl_basic_map_apply_range(bmap, range);
@@ -5855,56 +5967,44 @@ __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
+/* Transform "map" by applying "fn_space" to its space and "fn_bmap"
+ * to each of its basic maps.
+ */
+static __isl_give isl_map *isl_map_transform(__isl_take isl_map *map,
+	__isl_give isl_space *(*fn_space)(__isl_take isl_space *space),
+	__isl_give isl_basic_map *(*fn_bmap)(__isl_take isl_basic_map *bmap))
 {
 	int i;
+	isl_space *space;
 
 	map = isl_map_cow(map);
 	if (!map)
 		return NULL;
 
-	map->dim = isl_space_domain_map(map->dim);
-	if (!map->dim)
-		goto error;
 	for (i = 0; i < map->n; ++i) {
-		map->p[i] = isl_basic_map_domain_map(map->p[i]);
+		map->p[i] = fn_bmap(map->p[i]);
 		if (!map->p[i])
-			goto error;
+			return isl_map_free(map);
 	}
-	ISL_F_CLR(map, ISL_MAP_DISJOINT);
 	map = isl_map_unmark_normalized(map);
+
+	space = isl_map_take_space(map);
+	space = fn_space(space);
+	map = isl_map_restore_space(map, space);
+
 	return map;
-error:
-	isl_map_free(map);
-	return NULL;
 }
 
-__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
+__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
 {
-	int i;
-	isl_space *range_dim;
-
-	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
+	return isl_map_transform(map, &isl_space_domain_map,
+					&isl_basic_map_domain_map);
+}
 
-	range_dim = isl_space_range(isl_map_get_space(map));
-	range_dim = isl_space_from_range(range_dim);
-	map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
-	map->dim = isl_space_join(map->dim, range_dim);
-	if (!map->dim)
-		goto error;
-	for (i = 0; i < map->n; ++i) {
-		map->p[i] = isl_basic_map_range_map(map->p[i]);
-		if (!map->p[i])
-			goto error;
-	}
-	ISL_F_CLR(map, ISL_MAP_DISJOINT);
-	map = isl_map_unmark_normalized(map);
-	return map;
-error:
-	isl_map_free(map);
-	return NULL;
+__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
+{
+	return isl_map_transform(map, &isl_space_range_map,
+					&isl_basic_map_range_map);
 }
 
 /* Given a wrapped map of the form A[B -> C],
@@ -6042,13 +6142,16 @@ __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
 	return bset;
 }
 
-__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
+__isl_give isl_basic_map *isl_basic_map_nat_universe(
+	__isl_take isl_space *space)
 {
 	int i;
-	unsigned total = isl_space_dim(dim, isl_dim_all);
+	isl_size total = isl_space_dim(space, isl_dim_all);
 	isl_basic_map *bmap;
 
-	bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
+	if (total < 0)
+		space = isl_space_free(space);
+	bmap = isl_basic_map_alloc_space(space, 0, 0, total);
 	for (i = 0; i < total; ++i) {
 		int k = isl_basic_map_alloc_inequality(bmap);
 		if (k < 0)
@@ -6062,9 +6165,10 @@ __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
 	return NULL;
 }
 
-__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
+__isl_give isl_basic_set *isl_basic_set_nat_universe(
+	__isl_take isl_space *space)
 {
-	return isl_basic_map_nat_universe(dim);
+	return isl_basic_map_nat_universe(space);
 }
 
 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
@@ -6129,7 +6233,8 @@ __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
 		isl_basic_map_free(bmap);
 		return map;
 	}
-	isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
+	if (isl_map_basic_map_check_equal_space(map, bmap) < 0)
+		goto error;
 	isl_assert(map->ctx, map->n < map->size, goto error);
 	map->p[map->n] = bmap;
 	map->n++;
@@ -6163,17 +6268,22 @@ __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
 	return NULL;
 }
 
-static struct isl_basic_map *isl_basic_map_fix_pos_si(
-	struct isl_basic_map *bmap, unsigned pos, int value)
+static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
+	__isl_take isl_basic_map *bmap, unsigned pos, int value)
 {
 	int j;
+	isl_size total;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 
 	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
 	j = isl_basic_map_alloc_equality(bmap);
 	if (j < 0)
 		goto error;
-	isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->eq[j] + 1, total);
 	isl_int_set_si(bmap->eq[j][pos], -1);
 	isl_int_set_si(bmap->eq[j][0], value);
 	bmap = isl_basic_map_simplify(bmap);
@@ -6187,13 +6297,18 @@ static __isl_give isl_basic_map *isl_basic_map_fix_pos(
 	__isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
 {
 	int j;
+	isl_size total;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 
 	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
 	j = isl_basic_map_alloc_equality(bmap);
 	if (j < 0)
 		goto error;
-	isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->eq[j] + 1, total);
 	isl_int_set_si(bmap->eq[j][pos], -1);
 	isl_int_set(bmap->eq[j][0], value);
 	bmap = isl_basic_map_simplify(bmap);
@@ -6347,10 +6462,8 @@ __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
 	int i;
 
 	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
-
-	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
+	if (isl_map_check_range(map, type, pos, 1) < 0)
+		return isl_map_free(map);
 	for (i = map->n - 1; i >= 0; --i) {
 		map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
 		map = remove_if_empty(map, i);
@@ -6359,9 +6472,6 @@ __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
 	}
 	map = isl_map_unmark_normalized(map);
 	return map;
-error:
-	isl_map_free(map);
-	return NULL;
 }
 
 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
@@ -6376,10 +6486,8 @@ __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
 	int i;
 
 	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
-
-	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
+	if (isl_map_check_range(map, type, pos, 1) < 0)
+		return isl_map_free(map);
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
 		if (!map->p[i])
@@ -6413,9 +6521,8 @@ __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
 	if (!isl_val_is_int(v))
 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
 			"expecting integer value", goto error);
-	if (pos >= isl_map_dim(map, type))
-		isl_die(isl_map_get_ctx(map), isl_error_invalid,
-			"index out of bounds", goto error);
+	if (isl_map_check_range(map, type, pos, 1) < 0)
+		goto error;
 	for (i = map->n - 1; i >= 0; --i) {
 		map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
 							isl_val_copy(v));
@@ -6458,16 +6565,20 @@ static __isl_give isl_basic_map *basic_map_bound_si(
 	enum isl_dim_type type, unsigned pos, int value, int upper)
 {
 	int j;
+	isl_size total;
 
 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
 		return isl_basic_map_free(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	pos += isl_basic_map_offset(bmap, type);
 	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
 	j = isl_basic_map_alloc_inequality(bmap);
 	if (j < 0)
 		goto error;
-	isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->ineq[j], 1 + total);
 	if (upper) {
 		isl_int_set_si(bmap->ineq[j][pos], -1);
 		isl_int_set_si(bmap->ineq[j][0], value);
@@ -6504,10 +6615,8 @@ static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
 	int i;
 
 	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
-
-	isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
+	if (isl_map_check_range(map, type, pos, 1) < 0)
+		return isl_map_free(map);
 	for (i = 0; i < map->n; ++i) {
 		map->p[i] = basic_map_bound_si(map->p[i],
 						 type, pos, value, upper);
@@ -6554,16 +6663,20 @@ static __isl_give isl_basic_map *basic_map_bound(
 	enum isl_dim_type type, unsigned pos, isl_int value, int upper)
 {
 	int j;
+	isl_size total;
 
 	if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
 		return isl_basic_map_free(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	pos += isl_basic_map_offset(bmap, type);
 	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
 	j = isl_basic_map_alloc_inequality(bmap);
 	if (j < 0)
 		goto error;
-	isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->ineq[j], 1 + total);
 	if (upper) {
 		isl_int_set_si(bmap->ineq[j][pos], -1);
 		isl_int_set(bmap->ineq[j][0], value);
@@ -6587,12 +6700,8 @@ static __isl_give isl_map *map_bound(__isl_take isl_map *map,
 	int i;
 
 	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
-
-	if (pos >= isl_map_dim(map, type))
-		isl_die(map->ctx, isl_error_invalid,
-			"index out of bounds", goto error);
+	if (isl_map_check_range(map, type, pos, 1) < 0)
+		return isl_map_free(map);
 	for (i = map->n - 1; i >= 0; --i) {
 		map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
 		map = remove_if_empty(map, i);
@@ -6601,9 +6710,6 @@ static __isl_give isl_map *map_bound(__isl_take isl_map *map,
 	}
 	map = isl_map_unmark_normalized(map);
 	return map;
-error:
-	isl_map_free(map);
-	return NULL;
 }
 
 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
@@ -6615,59 +6721,260 @@ __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
 	enum isl_dim_type type, unsigned pos, isl_int value)
 {
-	return map_bound(map, type, pos, value, 1);
+	return map_bound(map, type, pos, value, 1);
+}
+
+__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, isl_int value)
+{
+	return isl_map_lower_bound(set, type, pos, value);
+}
+
+__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, isl_int value)
+{
+	return isl_map_upper_bound(set, type, pos, value);
+}
+
+/* Force the values of the variable at position "pos" of type "type" of "map"
+ * to be no smaller than "value".
+ */
+__isl_give isl_map *isl_map_lower_bound_val(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
+{
+	if (!value)
+		goto error;
+	if (!isl_val_is_int(value))
+		isl_die(isl_map_get_ctx(map), isl_error_invalid,
+			"expecting integer value", goto error);
+	map = isl_map_lower_bound(map, type, pos, value->n);
+	isl_val_free(value);
+	return map;
+error:
+	isl_val_free(value);
+	isl_map_free(map);
+	return NULL;
+}
+
+/* Force the values of the variable at position "pos" of type "type" of "set"
+ * to be no smaller than "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_map *map;
+
+	map = set_to_map(set);
+	return set_from_map(isl_map_lower_bound_val(map, type, pos, value));
+}
+
+/* Force the values of the variable at position "pos" of type "type" of "map"
+ * to be no greater than "value".
+ */
+__isl_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
+{
+	if (!value)
+		goto error;
+	if (!isl_val_is_int(value))
+		isl_die(isl_map_get_ctx(map), isl_error_invalid,
+			"expecting integer value", goto error);
+	map = isl_map_upper_bound(map, type, pos, value->n);
+	isl_val_free(value);
+	return map;
+error:
+	isl_val_free(value);
+	isl_map_free(map);
+	return NULL;
+}
+
+/* Force the values of the variable at position "pos" of type "type" of "set"
+ * to be no greater than "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_map *map;
+
+	map = set_to_map(set);
+	return set_from_map(isl_map_upper_bound_val(map, type, pos, value));
+}
+
+#undef BASE
+#define BASE	val
+#include "isl_map_bound_templ.c"
+
+/* Apply "map_bound" to "set" with the corresponding value in "bound"
+ * for each set dimension, by treating the set as a map.
+ */
+static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
+	__isl_take isl_multi_val *bound,
+	__isl_give isl_map *map_bound(__isl_take isl_map *map,
+		unsigned pos, __isl_take isl_val *value))
+{
+	isl_map *map;
+
+	map = set_to_map(set);
+	return set_from_map(map_bound_multi_val(map, bound, map_bound));
+}
+
+#undef BASE
+#define BASE	pw_aff
+#include "isl_map_bound_templ.c"
+
+/* Apply "map_bound" to "set" with the corresponding value in "bound"
+ * for each set dimension, by converting the set and the bound
+ * to objects living in a map space.
+ */
+static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
+	__isl_take isl_multi_pw_aff *bound,
+	__isl_give isl_map *set_bound(__isl_take isl_map *map,
+		unsigned pos, __isl_take TYPE *value))
+{
+	isl_map *map;
+
+	map = isl_map_from_range(set);
+	bound = isl_multi_pw_aff_from_range(bound);
+	map = map_bound_multi_pw_aff(map, bound, set_bound);
+	return isl_map_range(map);
+}
+
+/* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
+ * setting a bound on the given output dimension.
+ */
+static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
+	unsigned pos, __isl_take isl_val *v)
+{
+	return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
+}
+
+/* Force the values of the set dimensions of "set"
+ * to be no smaller than the corresponding values in "lower".
+ */
+__isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
+	__isl_take isl_multi_val *lower)
+{
+	return set_bound_multi_val(set, lower, &map_lower_bound_val);
+}
+
+/* Force the values of the output dimensions of "map"
+ * to be no smaller than the corresponding values in "lower".
+ */
+__isl_give isl_map *isl_map_lower_bound_multi_val(__isl_take isl_map *map,
+	__isl_take isl_multi_val *lower)
+{
+	return map_bound_multi_val(map, lower, &map_lower_bound_val);
+}
+
+/* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
+ * setting a bound on the given output dimension.
+ */
+static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
+	unsigned pos, __isl_take isl_val *v)
+{
+	return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
+}
+
+/* Force the values of the set dimensions of "set"
+ * to be no greater than the corresponding values in "upper".
+ */
+__isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
+	__isl_take isl_multi_val *upper)
+{
+	return set_bound_multi_val(set, upper, &map_upper_bound_val);
+}
+
+/* Force the values of the set dimensions of "set"
+ * to be no greater than the corresponding values in "upper".
+ */
+__isl_give isl_map *isl_map_upper_bound_multi_val(__isl_take isl_map *map,
+	__isl_take isl_multi_val *upper)
+{
+	return map_bound_multi_val(map, upper, &map_upper_bound_val);
+}
+
+/* Force the symbolic constant expression "bound"
+ * to satisfy the relation "order" with respect to
+ * the output variable at position "pos" of "map".
+ *
+ * Create an affine expression representing the output variable
+ * in terms of the range and
+ * compare it using "order" to "bound" (defined on the domain).
+ * The result is a relation between elements in domain and range that
+ * can be intersected with "map".
+ */
+static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
+	unsigned pos, __isl_take isl_pw_aff *bound,
+	__isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
+		__isl_take isl_pw_aff *pa2))
+{
+	isl_space *space;
+	isl_local_space *ls;
+	isl_pw_aff *var;
+
+	space = isl_space_range(isl_map_get_space(map));
+	ls = isl_local_space_from_space(space);
+	var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
+	map = isl_map_intersect(map, order(bound, var));
+	return map;
+}
+
+/* Force the values of the output variable at position "pos" of "map"
+ * to be no smaller than the symbolic constant expression "lower".
+ */
+static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
+	unsigned pos, __isl_take isl_pw_aff *lower)
+{
+	return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
+}
+
+/* Force the values of the output variable at position "pos" of "map"
+ * to be no greater than the symbolic constant expression "upper".
+ */
+static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
+	unsigned pos, __isl_take isl_pw_aff *upper)
+{
+	return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
 }
 
-__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
-	enum isl_dim_type type, unsigned pos, isl_int value)
+/* Force the values of the set dimensions of "set"
+ * to be no smaller than the corresponding constant symbolic expressions
+ * in "lower".
+ */
+__isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
+	__isl_take isl_multi_pw_aff *lower)
 {
-	return isl_map_lower_bound(set, type, pos, value);
+	return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
 }
 
-__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
-	enum isl_dim_type type, unsigned pos, isl_int value)
+/* Force the values of the set dimensions of "set"
+ * to be no greater than the corresponding constant symbolic expressions
+ * in "upper".
+ */
+__isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
+	__isl_take isl_multi_pw_aff *upper)
 {
-	return isl_map_upper_bound(set, type, pos, value);
+	return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
 }
 
-/* Force the values of the variable at position "pos" of type "type" of "set"
- * to be no smaller than "value".
+/* Force the values of the output dimensions of "map"
+ * to be no smaller than the corresponding constant symbolic expressions
+ * in "lower".
  */
-__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_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
+	__isl_take isl_multi_pw_aff *lower)
 {
-	if (!value)
-		goto error;
-	if (!isl_val_is_int(value))
-		isl_die(isl_set_get_ctx(set), isl_error_invalid,
-			"expecting integer value", goto error);
-	set = isl_set_lower_bound(set, type, pos, value->n);
-	isl_val_free(value);
-	return set;
-error:
-	isl_val_free(value);
-	isl_set_free(set);
-	return NULL;
+	return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
 }
 
-/* Force the values of the variable at position "pos" of type "type" of "set"
- * to be no greater than "value".
+/* Force the values of the output dimensions of "map"
+ * to be no greater than the corresponding constant symbolic expressions
+ * in "upper".
  */
-__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_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
+	__isl_take isl_multi_pw_aff *upper)
 {
-	if (!value)
-		goto error;
-	if (!isl_val_is_int(value))
-		isl_die(isl_set_get_ctx(set), isl_error_invalid,
-			"expecting integer value", goto error);
-	set = isl_set_upper_bound(set, type, pos, value->n);
-	isl_val_free(value);
-	return set;
-error:
-	isl_val_free(value);
-	isl_set_free(set);
-	return NULL;
+	return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
 }
 
 /* Bound the given variable of "bset" from below (or above is "upper"
@@ -6722,25 +7029,16 @@ __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
 
 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
 {
-	int i;
-
-	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
+	return isl_map_transform(map, &isl_space_reverse,
+					&isl_basic_map_reverse);
+}
 
-	map->dim = isl_space_reverse(map->dim);
-	if (!map->dim)
-		goto error;
-	for (i = 0; i < map->n; ++i) {
-		map->p[i] = isl_basic_map_reverse(map->p[i]);
-		if (!map->p[i])
-			goto error;
-	}
-	map = isl_map_unmark_normalized(map);
-	return map;
-error:
-	isl_map_free(map);
-	return NULL;
+/* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
+ */
+__isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
+{
+	return isl_map_transform(map, &isl_space_range_reverse,
+					&isl_basic_map_range_reverse);
 }
 
 #undef TYPE
@@ -6998,18 +7296,20 @@ static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
 {
 	int i;
 	isl_pw_aff *pwaff;
-	unsigned n_out;
+	isl_size n_out;
 
 	n_out = isl_map_dim(map, isl_dim_out);
+	if (n_out < 0)
+		map = isl_map_free(map);
 	map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
 	map = isl_map_project_out(map, isl_dim_out, 0, pos);
 	if (!map)
 		return NULL;
 
 	if (map->n == 0) {
-		isl_space *dim = isl_map_get_space(map);
+		isl_space *space = isl_map_get_space(map);
 		isl_map_free(map);
-		return isl_pw_aff_empty(dim);
+		return isl_pw_aff_empty(space);
 	}
 
 	pwaff = basic_map_dim_opt(map->p[0], max);
@@ -7075,17 +7375,16 @@ __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
 static __isl_give isl_basic_set *basic_set_parameter_preimage(
 	__isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
 {
-	unsigned nparam;
+	isl_size nparam;
 
-	if (!bset || !mat)
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (nparam < 0 || !mat)
 		goto error;
 
 	bset->dim = isl_space_cow(bset->dim);
 	if (!bset->dim)
 		goto error;
 
-	nparam = isl_basic_set_dim(bset, isl_dim_param);
-
 	isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
 
 	bset->dim->nparam = 0;
@@ -7109,12 +7408,11 @@ static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
 	__isl_take isl_mat *mat)
 {
 	isl_space *space;
-	unsigned nparam;
-
-	if (!set || !mat)
-		goto error;
+	isl_size nparam;
 
 	nparam = isl_set_dim(set, isl_dim_param);
+	if (nparam < 0 || !mat)
+		goto error;
 
 	if (mat->n_row != 1 + nparam)
 		isl_die(isl_set_get_ctx(set), isl_error_internal,
@@ -7126,6 +7424,8 @@ static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
 	set = isl_set_reset_space(set, space);
 	set = isl_set_preimage(set, mat);
 	nparam = isl_set_dim(set, isl_dim_out);
+	if (nparam < 0)
+		set = isl_set_free(set);
 	space = isl_set_get_space(set);
 	space = isl_space_move_dims(space, isl_dim_param, 0,
 				    isl_dim_out, 0, nparam);
@@ -7149,12 +7449,11 @@ static __isl_give isl_basic_set *basic_set_append_equalities(
 	if (!bset || !eq)
 		goto error;
 
-	bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
-					eq->n_row, 0);
+	bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
 	if (!bset)
 		goto error;
 
-	len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
+	len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
 	for (i = 0; i < eq->n_row; ++i) {
 		k = isl_basic_set_alloc_equality(bset);
 		if (k < 0)
@@ -7209,13 +7508,12 @@ static struct isl_set *set_append_equalities(struct isl_set *set,
 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
 {
 	int i, j;
-	unsigned nparam, n_div;
-
-	if (!bset)
-		return -1;
+	isl_size nparam, n_div;
 
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
 	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	if (nparam < 0 || n_div < 0)
+		return -1;
 
 	for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
 		if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
@@ -7243,7 +7541,7 @@ static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
 {
 	isl_morph *morph1, *morph2;
 	isl_set *set;
-	unsigned n;
+	isl_size n;
 
 	if (!bset)
 		return NULL;
@@ -7256,6 +7554,8 @@ static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
 	morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
 	bset = isl_morph_basic_set(morph2, bset);
 	n = isl_basic_set_dim(bset, isl_dim_set);
+	if (n < 0)
+		bset = isl_basic_set_free(bset);
 	bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
 
 	set = isl_basic_set_lexmin_compute_divs(bset);
@@ -7289,7 +7589,7 @@ static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
 	struct isl_mat *eq;
 	struct isl_mat *T, *T2;
 	struct isl_set *set;
-	unsigned nparam;
+	isl_size nparam;
 
 	bset = isl_basic_set_cow(bset);
 	if (!bset)
@@ -7309,6 +7609,8 @@ static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
 		return base_compute_divs(bset);
 
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (nparam < 0)
+		return isl_set_from_basic_set(isl_basic_set_free(bset));
 	eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
 		0, 1 + nparam);
 	eq = isl_mat_cow(eq);
@@ -7345,10 +7647,12 @@ static __isl_give isl_basic_map *insert_divs_from_local_space(
 	__isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
 {
 	int i;
-	int n_div;
+	isl_size n_div;
 	int old_n_div;
 
 	n_div = isl_local_space_dim(ls, isl_dim_div);
+	if (n_div < 0)
+		return isl_basic_map_free(bmap);
 	if (n_div == 0)
 		return bmap;
 
@@ -7374,13 +7678,13 @@ static __isl_give isl_basic_map *insert_divs_from_local_space(
 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
 	__isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
 {
-	int n_div;
+	isl_size n_div;
 
 	bmap = isl_basic_map_cow(bmap);
-	if (!bmap || !ls)
+	n_div = isl_local_space_dim(ls, isl_dim_div);
+	if (!bmap || n_div < 0)
 		goto error;
 
-	n_div = isl_local_space_dim(ls, isl_dim_div);
 	bmap = insert_divs_from_local_space(bmap, ls);
 	if (!bmap)
 		goto error;
@@ -7418,10 +7722,8 @@ static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
 		if (!map->p[i])
 			goto error;
 	}
-	isl_space_free(map->dim);
-	map->dim = isl_local_space_get_space(ls);
-	if (!map->dim)
-		goto error;
+	isl_space_free(isl_map_take_space(map));
+	map = isl_map_restore_space(map, isl_local_space_get_space(ls));
 
 	isl_local_space_free(ls);
 	return map;
@@ -7445,16 +7747,16 @@ static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
  * is reset to that of the input, including the existentially quantified
  * variables for which we already had an explicit representation.
  */
-static struct isl_map *compute_divs(struct isl_basic_map *bmap)
+static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
 {
 	struct isl_basic_set *bset;
 	struct isl_set *set;
 	struct isl_map *map;
-	isl_space *dim;
+	isl_space *space;
 	isl_local_space *ls;
-	unsigned	 nparam;
-	unsigned	 n_in;
-	unsigned	 n_out;
+	isl_size nparam;
+	isl_size n_in;
+	isl_size n_out;
 	int n_known;
 	int i;
 
@@ -7464,15 +7766,15 @@ static struct isl_map *compute_divs(struct isl_basic_map *bmap)
 		return NULL;
 
 	n_known = isl_basic_map_first_unknown_div(bmap);
-	if (n_known < 0)
-		return isl_map_from_basic_map(isl_basic_map_free(bmap));
-
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
-	dim = isl_space_set_alloc(bmap->ctx,
+	if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
+		return isl_map_from_basic_map(isl_basic_map_free(bmap));
+
+	space = isl_space_set_alloc(bmap->ctx,
 				    nparam + n_in + n_out + n_known, 0);
-	if (!dim)
+	if (!space)
 		goto error;
 
 	ls = isl_basic_map_get_local_space(bmap);
@@ -7484,7 +7786,7 @@ static struct isl_map *compute_divs(struct isl_basic_map *bmap)
 		bmap->n_div -= n_known;
 		bmap->extra -= n_known;
 	}
-	bmap = isl_basic_map_reset_space(bmap, dim);
+	bmap = isl_basic_map_reset_space(bmap, space);
 	bset = bset_from_bmap(bmap);
 
 	set = parameter_compute_divs(bset);
@@ -7568,11 +7870,12 @@ int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
  */
 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
 {
-	int first, n;
+	int first;
+	isl_size n;
 
 	n = isl_basic_map_dim(bmap, isl_dim_div);
 	first = isl_basic_map_first_unknown_div(bmap);
-	if (first < 0)
+	if (n < 0 || first < 0)
 		return isl_bool_error;
 	return first == n;
 }
@@ -7717,13 +8020,9 @@ static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
 	struct isl_map *map = NULL;
 	int is_universe;
 
-	if (!map1 || !map2)
+	if (isl_map_check_equal_space(map1, map2) < 0)
 		goto error;
 
-	if (!isl_space_is_equal(map1->dim, map2->dim))
-		isl_die(isl_map_get_ctx(map1), isl_error_invalid,
-			"spaces don't match", goto error);
-
 	if (map1->n == 0) {
 		isl_map_free(map1);
 		return map2;
@@ -7789,11 +8088,12 @@ static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
-	return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
+	isl_map_align_params_bin(&map1, &map2);
+	return map_union_disjoint(map1, map2);
 }
 
 /* Return the union of "map1" and "map2", where "map1" and "map2" may
- * not be disjoint.  The parameters are assumed to have been aligned.
+ * not be disjoint.
  *
  * We currently simply call map_union_disjoint, the internal operation
  * of which does not really depend on the inputs being disjoint.
@@ -7804,12 +8104,12 @@ __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
  * As a special case, if "map1" and "map2" are obviously equal,
  * then we simply return "map1".
  */
-static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
+__isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
 	int equal;
 
-	if (!map1 || !map2)
+	if (isl_map_align_params_bin(&map1, &map2) < 0)
 		goto error;
 
 	equal = isl_map_plain_is_equal(map1, map2);
@@ -7832,15 +8132,6 @@ static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
 	return NULL;
 }
 
-/* Return the union of "map1" and "map2", where "map1" and "map2" may
- * not be disjoint.
- */
-__isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
-}
-
 __isl_give isl_set *isl_set_union_disjoint(
 	__isl_take isl_set *set1, __isl_take isl_set *set2)
 {
@@ -7854,12 +8145,12 @@ struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
 }
 
 /* Apply "fn" to pairs of elements from "map" and "set" and collect
- * the results.
+ * the results in a map living in "space".
  *
  * "map" and "set" are assumed to be compatible and non-NULL.
  */
 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
-	__isl_take isl_set *set,
+	__isl_take isl_space *space, __isl_take isl_set *set,
 	__isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
 		__isl_take isl_basic_set *bset))
 {
@@ -7869,15 +8160,14 @@ static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
 
 	if (isl_set_plain_is_universe(set)) {
 		isl_set_free(set);
-		return map;
+		return isl_map_reset_equal_dim_space(map, space);
 	}
 
 	if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
 	    ISL_F_ISSET(set, ISL_MAP_DISJOINT))
 		ISL_FL_SET(flags, ISL_MAP_DISJOINT);
 
-	result = isl_map_alloc_space(isl_space_copy(map->dim),
-					map->n * set->n, flags);
+	result = isl_map_alloc_space(space, map->n * set->n, flags);
 	for (i = 0; result && i < map->n; ++i)
 		for (j = 0; j < set->n; ++j) {
 			result = isl_map_add_basic_map(result,
@@ -7892,11 +8182,13 @@ static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
 	return result;
 }
 
-static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
+__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
 	__isl_take isl_set *set)
 {
 	isl_bool ok;
+	isl_space *space;
 
+	isl_map_align_params_set(&map, &set);
 	ok = isl_map_compatible_range(map, set);
 	if (ok < 0)
 		goto error;
@@ -7904,24 +8196,27 @@ static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
 		isl_die(set->ctx, isl_error_invalid,
 			"incompatible spaces", goto error);
 
-	return map_intersect_set(map, set, &isl_basic_map_intersect_range);
+	space = isl_map_get_space(map);
+	return map_intersect_set(map, space, set,
+				&isl_basic_map_intersect_range);
 error:
 	isl_map_free(map);
 	isl_set_free(set);
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
-	__isl_take isl_set *set)
-{
-	return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
-}
-
-static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
+/* Intersect the domain of "map" with "set".
+ *
+ * If the domain dimensions of "map" do not have any identifiers,
+ * then copy them over from "set".
+ */
+__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
 	__isl_take isl_set *set)
 {
 	isl_bool ok;
+	isl_space *space;
 
+	isl_map_align_params_set(&map, &set);
 	ok = isl_map_compatible_domain(map, set);
 	if (ok < 0)
 		goto error;
@@ -7929,37 +8224,100 @@ static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
 		isl_die(set->ctx, isl_error_invalid,
 			"incompatible spaces", goto error);
 
-	return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
+	space = isl_map_get_space(map);
+	space = isl_space_copy_ids_if_unset(space, isl_dim_in,
+					isl_set_peek_space(set), isl_dim_set);
+	return map_intersect_set(map, space, set,
+				&isl_basic_map_intersect_domain);
 error:
 	isl_map_free(map);
 	isl_set_free(set);
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
-	__isl_take isl_set *set)
-{
-	return isl_map_align_params_map_map_and(map, set,
-						&map_intersect_domain);
-}
+/* Data structure that specifies how isl_map_intersect_factor
+ * should operate.
+ *
+ * "preserve_type" is the tuple where the factor 
diff ers from
+ * the input map and of which the identifiers needs
+ * to be preserved explicitly.
+ * "other_factor" is used to extract the space of the other factor
+ * from the space of the product ("map").
+ * "product" is used to combine the given factor and a universe map
+ * in the space returned by "other_factor" to produce a map
+ * that lives in the same space as the input map.
+ */
+struct isl_intersect_factor_control {
+	enum isl_dim_type preserve_type;
+	__isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
+	__isl_give isl_map *(*product)(__isl_take isl_map *factor,
+		__isl_take isl_map *other);
+};
 
-/* Given a map "map" in a space [A -> B] -> C and a map "factor"
- * in the space B -> C, return the intersection.
- * The parameters are assumed to have been aligned.
+/* Given a map "map" in some product space and a map "factor"
+ * living in some factor space, return the intersection.
+ *
+ * After aligning the parameters,
+ * the map "factor" is first extended to a map living in the same space
+ * as "map" and then a regular intersection is computed.
  *
- * The map "factor" is first extended to a map living in the space
- * [A -> B] -> C and then a regular intersection is computed.
+ * Note that the extension is computed as a product, which is anonymous
+ * by default.  If "map" has an identifier on the corresponding tuple,
+ * then this identifier needs to be set on the product
+ * before the intersection is computed.
  */
-static __isl_give isl_map *map_intersect_domain_factor_range(
-	__isl_take isl_map *map, __isl_take isl_map *factor)
+static __isl_give isl_map *isl_map_intersect_factor(
+	__isl_take isl_map *map, __isl_take isl_map *factor,
+	struct isl_intersect_factor_control *control)
 {
+	isl_bool equal, has_id;
+	isl_id *id;
 	isl_space *space;
-	isl_map *ext_factor;
+	isl_map *other, *product;
+
+	equal = isl_map_has_equal_params(map, factor);
+	if (equal < 0)
+		goto error;
+	if (!equal) {
+		map = isl_map_align_params(map, isl_map_get_space(factor));
+		factor = isl_map_align_params(factor, isl_map_get_space(map));
+	}
+
+	space = isl_map_get_space(map);
+	has_id = isl_space_has_tuple_id(space, control->preserve_type);
+	if (has_id < 0)
+		space = isl_space_free(space);
+	else if (has_id)
+		id = isl_space_get_tuple_id(space, control->preserve_type);
+
+	other = isl_map_universe(control->other_factor(space));
+	product = control->product(factor, other);
+
+	if (has_id >= 0 && has_id)
+		product = isl_map_set_tuple_id(product,
+						control->preserve_type, id);
+
+	return map_intersect(map, product);
+error:
+	isl_map_free(map);
+	isl_map_free(factor);
+	return NULL;
+}
+
+/* Return the domain product of "map2" and "map1".
+ */
+static __isl_give isl_map *isl_map_reverse_domain_product(
+	__isl_take isl_map *map1, __isl_take isl_map *map2)
+{
+	return isl_map_domain_product(map2, map1);
+}
 
-	space = isl_space_domain_factor_domain(isl_map_get_space(map));
-	ext_factor = isl_map_universe(space);
-	ext_factor = isl_map_domain_product(ext_factor, factor);
-	return map_intersect(map, ext_factor);
+/* Return the range product of "map2" and "map1".
+ */
+static __isl_give isl_map *isl_map_reverse_range_product(
+	__isl_take isl_map *map1, __isl_take isl_map *map2)
+{
+	return isl_map_range_product(map2, map1);
 }
 
 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
@@ -7968,26 +8326,28 @@ static __isl_give isl_map *map_intersect_domain_factor_range(
 __isl_give isl_map *isl_map_intersect_domain_factor_range(
 	__isl_take isl_map *map, __isl_take isl_map *factor)
 {
-	return isl_map_align_params_map_map_and(map, factor,
-					    &map_intersect_domain_factor_range);
+	struct isl_intersect_factor_control control = {
+		.preserve_type = isl_dim_in,
+		.other_factor = isl_space_domain_factor_domain,
+		.product = isl_map_reverse_domain_product,
+	};
+
+	return isl_map_intersect_factor(map, factor, &control);
 }
 
 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
- * in the space A -> C, return the intersection.
- *
- * The map "factor" is first extended to a map living in the space
- * A -> [B -> C] and then a regular intersection is computed.
+ * in the space A -> B, return the intersection.
  */
-static __isl_give isl_map *map_intersect_range_factor_range(
+__isl_give isl_map *isl_map_intersect_range_factor_domain(
 	__isl_take isl_map *map, __isl_take isl_map *factor)
 {
-	isl_space *space;
-	isl_map *ext_factor;
+	struct isl_intersect_factor_control control = {
+		.preserve_type = isl_dim_out,
+		.other_factor = isl_space_range_factor_range,
+		.product = isl_map_range_product,
+	};
 
-	space = isl_space_range_factor_domain(isl_map_get_space(map));
-	ext_factor = isl_map_universe(space);
-	ext_factor = isl_map_range_product(ext_factor, factor);
-	return isl_map_intersect(map, ext_factor);
+	return isl_map_intersect_factor(map, factor, &control);
 }
 
 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
@@ -7996,14 +8356,57 @@ static __isl_give isl_map *map_intersect_range_factor_range(
 __isl_give isl_map *isl_map_intersect_range_factor_range(
 	__isl_take isl_map *map, __isl_take isl_map *factor)
 {
-	return isl_map_align_params_map_map_and(map, factor,
-					    &map_intersect_range_factor_range);
+	struct isl_intersect_factor_control control = {
+		.preserve_type = isl_dim_out,
+		.other_factor = isl_space_range_factor_domain,
+		.product = isl_map_reverse_range_product,
+	};
+
+	return isl_map_intersect_factor(map, factor, &control);
+}
+
+/* Given a set "set" in a space [A -> B] and a set "domain"
+ * in the space A, return the intersection.
+ *
+ * The set "domain" is first extended to a set living in the space
+ * [A -> B] and then a regular intersection is computed.
+ */
+__isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
+	__isl_take isl_set *domain)
+{
+	struct isl_intersect_factor_control control = {
+		.preserve_type = isl_dim_set,
+		.other_factor = isl_space_factor_range,
+		.product = isl_map_range_product,
+	};
+
+	return set_from_map(isl_map_intersect_factor(set_to_map(set),
+						set_to_map(domain), &control));
+}
+
+/* Given a set "set" in a space [A -> B] and a set "range"
+ * in the space B, return the intersection.
+ *
+ * The set "range" is first extended to a set living in the space
+ * [A -> B] and then a regular intersection is computed.
+ */
+__isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
+	__isl_take isl_set *range)
+{
+	struct isl_intersect_factor_control control = {
+		.preserve_type = isl_dim_set,
+		.other_factor = isl_space_factor_domain,
+		.product = isl_map_reverse_range_product,
+	};
+
+	return set_from_map(isl_map_intersect_factor(set_to_map(set),
+						set_to_map(range), &control));
 }
 
-static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
+__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
-	if (!map1 || !map2)
+	if (isl_map_align_params_bin(&map1, &map2) < 0)
 		goto error;
 	map1 = isl_map_reverse(map1);
 	map1 = isl_map_apply_range(map1, map2);
@@ -8014,26 +8417,20 @@ static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
-}
-
-static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
+__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
-	isl_space *dim_result;
+	isl_space *space;
 	struct isl_map *result;
 	int i, j;
 
-	if (!map1 || !map2)
+	if (isl_map_align_params_bin(&map1, &map2) < 0)
 		goto error;
 
-	dim_result = isl_space_join(isl_space_copy(map1->dim),
+	space = isl_space_join(isl_space_copy(map1->dim),
 				  isl_space_copy(map2->dim));
 
-	result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
+	result = isl_map_alloc_space(space, map1->n * map2->n, 0);
 	if (!result)
 		goto error;
 	for (i = 0; i < map1->n; ++i)
@@ -8056,12 +8453,6 @@ static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
-}
-
 /*
  * returns range - domain
  */
@@ -8069,8 +8460,9 @@ __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
 {
 	isl_space *target_space;
 	struct isl_basic_set *bset;
-	unsigned dim;
-	unsigned nparam;
+	isl_size dim;
+	isl_size nparam;
+	isl_size total;
 	int i;
 
 	if (!bmap)
@@ -8078,11 +8470,16 @@ __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
 	isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
 						  bmap->dim, isl_dim_out),
 		   goto error);
-	target_space = isl_space_domain(isl_basic_map_get_space(bmap));
 	dim = isl_basic_map_dim(bmap, isl_dim_in);
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	if (dim < 0 || nparam < 0)
+		goto error;
+	target_space = isl_space_domain(isl_basic_map_get_space(bmap));
 	bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
 	bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		bmap = isl_basic_map_free(bmap);
 	bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
 	for (i = 0; i < dim; ++i) {
 		int j = isl_basic_map_alloc_equality(bmap);
@@ -8090,7 +8487,7 @@ __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
 			bmap = isl_basic_map_free(bmap);
 			break;
 		}
-		isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
+		isl_seq_clr(bmap->eq[j], 1 + total);
 		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
 		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
 		isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
@@ -8103,6 +8500,23 @@ __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
 	return NULL;
 }
 
+/* Check that domain and range of "map" are the same.
+ */
+isl_stat isl_map_check_equal_tuples(__isl_keep isl_map *map)
+{
+	isl_space *space;
+	isl_bool equal;
+
+	space = isl_map_peek_space(map);
+	equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
+	if (equal < 0)
+		return isl_stat_error;
+	if (!equal)
+		isl_die(isl_map_get_ctx(map), isl_error_invalid,
+			"domain and range don't match", return isl_stat_error);
+	return isl_stat_ok;
+}
+
 /*
  * returns range - domain
  */
@@ -8140,10 +8554,10 @@ __isl_give isl_basic_map *isl_basic_map_deltas_map(
 	__isl_take isl_basic_map *bmap)
 {
 	int i, k;
-	isl_space *dim;
+	isl_space *space;
 	isl_basic_map *domain;
-	int nparam, n;
-	unsigned total;
+	isl_size nparam, n;
+	isl_size total;
 
 	if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
 					bmap->dim, isl_dim_out))
@@ -8151,112 +8565,66 @@ __isl_give isl_basic_map *isl_basic_map_deltas_map(
 			"domain and range don't match", goto error);
 
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
-	n = isl_basic_map_dim(bmap, isl_dim_in);
-
-	dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
-	domain = isl_basic_map_universe(dim);
-
-	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
-	bmap = isl_basic_map_apply_range(bmap, domain);
-	bmap = isl_basic_map_extend_constraints(bmap, n, 0);
-
-	total = isl_basic_map_total_dim(bmap);
-
-	for (i = 0; i < n; ++i) {
-		k = isl_basic_map_alloc_equality(bmap);
-		if (k < 0)
-			goto error;
-		isl_seq_clr(bmap->eq[k], 1 + total);
-		isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
-		isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
-		isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
-	}
-
-	bmap = isl_basic_map_gauss(bmap, NULL);
-	return isl_basic_map_finalize(bmap);
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
-}
-
-/*
- * returns [domain -> range] -> range - domain
- */
-__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
-{
-	int i;
-	isl_space *domain_dim;
-
-	if (!map)
-		return NULL;
-
-	if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
-					map->dim, isl_dim_out))
-		isl_die(map->ctx, isl_error_invalid,
-			"domain and range don't match", goto error);
-
-	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
-
-	domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
-	map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
-	map->dim = isl_space_join(map->dim, domain_dim);
-	if (!map->dim)
-		goto error;
-	for (i = 0; i < map->n; ++i) {
-		map->p[i] = isl_basic_map_deltas_map(map->p[i]);
-		if (!map->p[i])
-			goto error;
-	}
-	map = isl_map_unmark_normalized(map);
-	return map;
-error:
-	isl_map_free(map);
-	return NULL;
-}
+	n = isl_basic_map_dim(bmap, isl_dim_in);
+	if (nparam < 0 || n < 0)
+		return isl_basic_map_free(bmap);
 
-static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
-{
-	struct isl_basic_map *bmap;
-	unsigned nparam;
-	unsigned dim;
-	int i;
+	space = isl_basic_map_get_space(bmap);
+	space = isl_space_from_range(isl_space_domain(space));
+	domain = isl_basic_map_universe(space);
 
-	if (!dims)
-		return NULL;
+	bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
+	bmap = isl_basic_map_apply_range(bmap, domain);
+	bmap = isl_basic_map_extend_constraints(bmap, n, 0);
 
-	nparam = dims->nparam;
-	dim = dims->n_out;
-	bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
-	if (!bmap)
-		goto error;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 
-	for (i = 0; i < dim; ++i) {
-		int j = isl_basic_map_alloc_equality(bmap);
-		if (j < 0)
+	for (i = 0; i < n; ++i) {
+		k = isl_basic_map_alloc_equality(bmap);
+		if (k < 0)
 			goto error;
-		isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
-		isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
-		isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
+		isl_seq_clr(bmap->eq[k], 1 + total);
+		isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
+		isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
+		isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
 	}
+
+	bmap = isl_basic_map_gauss(bmap, NULL);
 	return isl_basic_map_finalize(bmap);
 error:
 	isl_basic_map_free(bmap);
 	return NULL;
 }
 
-__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
+/*
+ * returns [domain -> range] -> range - domain
+ */
+__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
 {
-	if (!dim)
-		return NULL;
-	if (dim->n_in != dim->n_out)
-		isl_die(dim->ctx, isl_error_invalid,
+	if (isl_map_check_equal_tuples(map) < 0)
+		return isl_map_free(map);
+
+	return isl_map_transform(map, &isl_space_range_map,
+					&isl_basic_map_deltas_map);
+}
+
+__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
+{
+	isl_size n_in, n_out;
+
+	n_in = isl_space_dim(space, isl_dim_in);
+	n_out = isl_space_dim(space, isl_dim_out);
+	if (n_in < 0 || n_out < 0)
+		goto error;
+	if (n_in != n_out)
+		isl_die(space->ctx, isl_error_invalid,
 			"number of input and output dimensions needs to be "
 			"the same", goto error);
-	return basic_map_identity(dim);
+	return isl_basic_map_equal(space, n_in);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -8280,14 +8648,16 @@ __isl_give isl_basic_set *isl_basic_set_positive_orthant(
 	__isl_take isl_space *space)
 {
 	int i;
-	unsigned nparam;
-	unsigned dim;
+	isl_size nparam;
+	isl_size dim;
+	isl_size total;
 	struct isl_basic_set *bset;
 
-	if (!space)
-		return NULL;
-	nparam = space->nparam;
-	dim = space->n_out;
+	nparam = isl_space_dim(space, isl_dim_param);
+	dim = isl_space_dim(space, isl_dim_set);
+	total = isl_space_dim(space, isl_dim_all);
+	if (nparam < 0 || dim < 0 || total < 0)
+		space = isl_space_free(space);
 	bset = isl_basic_set_alloc_space(space, 0, 0, dim);
 	if (!bset)
 		return NULL;
@@ -8295,7 +8665,7 @@ __isl_give isl_basic_set *isl_basic_set_positive_orthant(
 		int k = isl_basic_set_alloc_inequality(bset);
 		if (k < 0)
 			goto error;
-		isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
+		isl_seq_clr(bset->ineq[k], 1 + total);
 		isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
 	}
 	return bset;
@@ -8306,17 +8676,21 @@ __isl_give isl_basic_set *isl_basic_set_positive_orthant(
 
 /* Construct the half-space x_pos >= 0.
  */
-static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
+static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
 	int pos)
 {
 	int k;
+	isl_size total;
 	isl_basic_set *nonneg;
 
-	nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0)
+		space = isl_space_free(space);
+	nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
 	k = isl_basic_set_alloc_inequality(nonneg);
 	if (k < 0)
 		goto error;
-	isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
+	isl_seq_clr(nonneg->ineq[k], 1 + total);
 	isl_int_set_si(nonneg->ineq[k][pos], 1);
 
 	return isl_basic_set_finalize(nonneg);
@@ -8327,16 +8701,21 @@ static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
 
 /* Construct the half-space x_pos <= -1.
  */
-static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
+static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
+	int pos)
 {
 	int k;
+	isl_size total;
 	isl_basic_set *neg;
 
-	neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0)
+		space = isl_space_free(space);
+	neg = isl_basic_set_alloc_space(space, 0, 0, 1);
 	k = isl_basic_set_alloc_inequality(neg);
 	if (k < 0)
 		goto error;
-	isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
+	isl_seq_clr(neg->ineq[k], 1 + total);
 	isl_int_set_si(neg->ineq[k][0], -1);
 	isl_int_set_si(neg->ineq[k][pos], -1);
 
@@ -8354,12 +8733,11 @@ __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
 	isl_basic_set *nonneg;
 	isl_basic_set *neg;
 
-	if (!set)
-		return NULL;
 	if (n == 0)
 		return set;
 
-	isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
+	if (isl_set_check_range(set, type, first, n) < 0)
+		return isl_set_free(set);
 
 	offset = pos(set->dim, type);
 	for (i = 0; i < n; ++i) {
@@ -8371,9 +8749,6 @@ __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
 	}
 
 	return set;
-error:
-	isl_set_free(set);
-	return NULL;
 }
 
 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
@@ -8418,8 +8793,8 @@ isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
 	isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
 	void *user)
 {
-	unsigned nparam;
-	unsigned nvar;
+	isl_size nparam;
+	isl_size nvar;
 	int *signs;
 	isl_stat r;
 
@@ -8430,6 +8805,8 @@ isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
 
 	nparam = isl_set_dim(set, isl_dim_param);
 	nvar = isl_set_dim(set, isl_dim_set);
+	if (nparam < 0 || nvar < 0)
+		return isl_stat_error;
 
 	signs = isl_alloc_array(set->ctx, int, nparam + nvar);
 
@@ -8449,7 +8826,7 @@ isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
 	__isl_keep isl_basic_map *bmap2)
 {
-	int is_subset;
+	isl_bool is_subset;
 	struct isl_map *map1;
 	struct isl_map *map2;
 
@@ -8526,22 +8903,54 @@ isl_bool isl_set_is_empty(__isl_keep isl_set *set)
 	return isl_map_is_empty(set_to_map(set));
 }
 
-isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
-	__isl_keep isl_map *map2)
-{
-	if (!map1 || !map2)
-		return isl_bool_error;
+#undef TYPE
+#define TYPE	isl_basic_map
 
-	return isl_space_is_equal(map1->dim, map2->dim);
+static
+#include "isl_type_has_equal_space_bin_templ.c"
+#include "isl_type_check_equal_space_templ.c"
+
+/* Check that "bset1" and "bset2" live in the same space,
+ * reporting an error if they do not.
+ */
+isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
+	__isl_keep isl_basic_set *bset2)
+{
+	return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
+						bset_to_bmap(bset1));
 }
 
+#undef TYPE
+#define TYPE	isl_map
+
+#include "isl_type_has_equal_space_bin_templ.c"
+#include "isl_type_check_equal_space_templ.c"
+
 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
 	__isl_keep isl_set *set2)
 {
-	if (!set1 || !set2)
-		return isl_bool_error;
+	return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
+}
 
-	return isl_space_is_equal(set1->dim, set2->dim);
+#undef TYPE1
+#define TYPE1		isl_map
+#undef TYPE2
+#define TYPE2		isl_basic_map
+#undef TYPE_PAIR
+#define TYPE_PAIR	isl_map_basic_map
+
+static
+#include "isl_type_has_equal_space_templ.c"
+#include "isl_type_check_equal_space_templ.c"
+
+/* Check that "set" and "bset" live in the same space,
+ * reporting an error if they do not.
+ */
+isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
+	__isl_keep isl_basic_set *bset)
+{
+	return isl_map_basic_map_check_equal_space(set_to_map(set),
+						    bset_to_bmap(bset));
 }
 
 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
@@ -8583,9 +8992,7 @@ isl_bool isl_basic_map_is_strict_subset(
 	if (is_subset != isl_bool_true)
 		return is_subset;
 	is_subset = isl_basic_map_is_subset(bmap2, bmap1);
-	if (is_subset == isl_bool_error)
-		return is_subset;
-	return !is_subset;
+	return isl_bool_not(is_subset);
 }
 
 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
@@ -8599,9 +9006,7 @@ isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
 	if (is_subset != isl_bool_true)
 		return is_subset;
 	is_subset = isl_map_is_subset(map2, map1);
-	if (is_subset == isl_bool_error)
-		return is_subset;
-	return !is_subset;
+	return isl_bool_not(is_subset);
 }
 
 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
@@ -8634,9 +9039,11 @@ isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
 {
 	isl_bool *univ = user;
-	unsigned n;
+	isl_size n;
 
 	n = isl_constraint_dim(c, isl_dim_div);
+	if (n < 0)
+		c = isl_constraint_free(c);
 	*univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
 	isl_constraint_free(c);
 	if (*univ < 0 || !*univ)
@@ -8654,13 +9061,17 @@ static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
  */
 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
 {
+	isl_size n_div;
 	isl_bool univ;
 	isl_basic_map *test;
 
 	univ = isl_basic_map_plain_is_universe(bmap);
 	if (univ < 0 || univ)
 		return univ;
-	if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_bool_error;
+	if (n_div == 0)
 		return isl_bool_false;
 	univ = isl_bool_true;
 	if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
@@ -8767,14 +9178,16 @@ isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
  */
 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
 {
-	unsigned total;
+	isl_size total;
 
 	if (!bmap)
 		return isl_bool_error;
 	if (!bmap->sample)
 		return isl_bool_false;
-	total = 1 + isl_basic_map_total_dim(bmap);
-	if (bmap->sample->size != total)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
+	if (bmap->sample->size != 1 + total)
 		return isl_bool_false;
 	return isl_basic_map_contains(bmap, bmap->sample);
 }
@@ -8788,10 +9201,9 @@ __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
 	__isl_take isl_basic_map *bmap2)
 {
 	struct isl_map *map;
-	if (!bmap1 || !bmap2)
-		goto error;
 
-	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
+	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
+		goto error;
 
 	map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
 	if (!map)
@@ -8817,12 +9229,11 @@ __isl_give isl_basic_map *isl_basic_map_order_divs(
 	__isl_take isl_basic_map *bmap)
 {
 	int i;
-	unsigned off;
-
-	if (!bmap)
-		return NULL;
+	isl_size off;
 
-	off = isl_space_dim(bmap->dim, isl_dim_all);
+	off = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (off < 0)
+		return isl_basic_map_free(bmap);
 
 	for (i = 0; i < bmap->n_div; ++i) {
 		int pos;
@@ -8836,7 +9247,9 @@ __isl_give isl_basic_map *isl_basic_map_order_divs(
 			isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
 				"integer division depends on itself",
 				return isl_basic_map_free(bmap));
-		isl_basic_map_swap_div(bmap, i, i + pos);
+		bmap = isl_basic_map_swap_div(bmap, i, i + pos);
+		if (!bmap)
+			return NULL;
 		--i;
 	}
 	return bmap;
@@ -8899,8 +9312,7 @@ __isl_give isl_basic_map *isl_basic_map_expand_divs(
 			"not an expansion", goto error);
 
 	n_div = bmap->n_div;
-	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
-					    div->n_row - n_div, 0,
+	bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
 					    2 * (div->n_row - n_div));
 
 	for (i = n_div; i < div->n_row; ++i)
@@ -8910,7 +9322,9 @@ __isl_give isl_basic_map *isl_basic_map_expand_divs(
 	for (j = n_div - 1; j >= 0; --j) {
 		if (exp[j] == j)
 			break;
-		isl_basic_map_swap_div(bmap, j, exp[j]);
+		bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
+		if (!bmap)
+			goto error;
 	}
 	j = 0;
 	for (i = 0; i < div->n_row; ++i) {
@@ -8920,7 +9334,8 @@ __isl_give isl_basic_map *isl_basic_map_expand_divs(
 			isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
 			if (isl_basic_map_div_is_marked_unknown(bmap, i))
 				continue;
-			if (isl_basic_map_add_div_constraints(bmap, i) < 0)
+			bmap = isl_basic_map_add_div_constraints(bmap, i);
+			if (!bmap)
 				goto error;
 		}
 	}
@@ -8946,23 +9361,28 @@ __isl_give isl_basic_set *isl_basic_set_expand_divs(
 /* Look for a div in dst that corresponds to the div "div" in src.
  * The divs before "div" in src and dst are assumed to be the same.
  * 
- * Returns -1 if no corresponding div was found and the position
- * of the corresponding div in dst otherwise.
+ * Return the position of the corresponding div in dst
+ * if there is one.  Otherwise, return a position beyond the integer divisions.
+ * Return -1 on error.
  */
 static int find_div(__isl_keep isl_basic_map *dst,
 	__isl_keep isl_basic_map *src, unsigned div)
 {
 	int i;
+	isl_size n_div;
+	isl_size v_div;
 
-	unsigned total = isl_space_dim(src->dim, isl_dim_all);
-
-	isl_assert(dst->ctx, div <= dst->n_div, return -1);
-	for (i = div; i < dst->n_div; ++i)
-		if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
-		    isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
-						dst->n_div - div) == -1)
+	v_div = isl_basic_map_var_offset(src, isl_dim_div);
+	n_div = isl_basic_map_dim(dst, isl_dim_div);
+	if (n_div < 0 || v_div < 0)
+		return -1;
+	isl_assert(dst->ctx, div <= n_div, return -1);
+	for (i = div; i < n_div; ++i)
+		if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
+		    isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
+						n_div - div) == -1)
 			return i;
-	return -1;
+	return n_div;
 }
 
 /* Align the divs of "dst" to those of "src", adding divs from "src"
@@ -8976,8 +9396,10 @@ __isl_give isl_basic_map *isl_basic_map_align_divs(
 	__isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
 {
 	int i;
-	int known, extended;
-	unsigned total;
+	isl_bool known;
+	int extended;
+	isl_size v_div;
+	isl_size dst_n_div;
 
 	if (!dst || !src)
 		return isl_basic_map_free(dst);
@@ -8993,35 +9415,53 @@ __isl_give isl_basic_map *isl_basic_map_align_divs(
 			"some src divs are unknown",
 			return isl_basic_map_free(dst));
 
-	src = isl_basic_map_order_divs(src);
+	v_div = isl_basic_map_var_offset(src, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(dst);
+
+	src = isl_basic_map_order_divs(isl_basic_map_copy(src));
+	if (!src)
+		return isl_basic_map_free(dst);
 
 	extended = 0;
-	total = isl_space_dim(src->dim, isl_dim_all);
+	dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
+	if (dst_n_div < 0)
+		dst = isl_basic_map_free(dst);
 	for (i = 0; i < src->n_div; ++i) {
 		int j = find_div(dst, src, i);
-		if (j < 0) {
+		if (j < 0)
+			dst = isl_basic_map_free(dst);
+		if (j == dst_n_div) {
 			if (!extended) {
 				int extra = src->n_div - i;
 				dst = isl_basic_map_cow(dst);
 				if (!dst)
-					return NULL;
-				dst = isl_basic_map_extend_space(dst,
-						isl_space_copy(dst->dim),
+					goto error;
+				dst = isl_basic_map_extend(dst,
 						extra, 0, 2 * extra);
 				extended = 1;
 			}
 			j = isl_basic_map_alloc_div(dst);
 			if (j < 0)
-				return isl_basic_map_free(dst);
-			isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
-			isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
-			if (isl_basic_map_add_div_constraints(dst, j) < 0)
-				return isl_basic_map_free(dst);
+				goto error;
+			isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
+			isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
+			dst_n_div++;
+			dst = isl_basic_map_add_div_constraints(dst, j);
+			if (!dst)
+				goto error;
 		}
 		if (j != i)
-			isl_basic_map_swap_div(dst, i, j);
+			dst = isl_basic_map_swap_div(dst, i, j);
+		if (!dst)
+			goto error;
 	}
+	isl_basic_map_free(src);
 	return dst;
+error:
+	isl_basic_map_free(src);
+	isl_basic_map_free(dst);
+	return NULL;
 }
 
 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
@@ -9066,16 +9506,17 @@ struct isl_set *isl_set_align_divs(struct isl_set *set)
 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
 	__isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
+	n = isl_basic_map_list_n_basic_map(list);
 	map = isl_map_compute_divs(map);
 	map = isl_map_cow(map);
-	if (!map || !list)
+	if (!map || n < 0)
 		return isl_map_free(map);
 	if (map->n == 0)
 		return map;
 
-	n = isl_basic_map_list_n_basic_map(list);
 	for (i = 0; i < n; ++i) {
 		isl_basic_map *bmap;
 
@@ -9095,12 +9536,13 @@ __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
 	__isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!list || !bmap)
+	n = isl_basic_map_list_n_basic_map(list);
+	if (n < 0 || !bmap)
 		return isl_basic_map_list_free(list);
 
-	n = isl_basic_map_list_n_basic_map(list);
 	for (i = 0; i < n; ++i) {
 		isl_basic_map *bmap_i;
 
@@ -9112,11 +9554,12 @@ __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
 	return list;
 }
 
-static __isl_give isl_set *set_apply( __isl_take isl_set *set,
+__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
 	__isl_take isl_map *map)
 {
 	isl_bool ok;
 
+	isl_map_align_params_set(&map, &set);
 	ok = isl_map_compatible_domain(map, set);
 	if (ok < 0)
 		goto error;
@@ -9132,12 +9575,6 @@ static __isl_give isl_set *set_apply( __isl_take isl_set *set,
 	return NULL;
 }
 
-__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
-	__isl_take isl_map *map)
-{
-	return isl_map_align_params_map_map_and(set, map, &set_apply);
-}
-
 /* There is no need to cow as removing empty parts doesn't change
  * the meaning of the set.
  */
@@ -9188,22 +9625,21 @@ static enum isl_lp_result basic_set_maximal_
diff erence_at(
 	isl_basic_map *bmap1;
 	struct isl_ctx *ctx;
 	struct isl_vec *obj;
-	unsigned total;
-	unsigned nparam;
-	unsigned dim1;
+	isl_size total;
+	isl_size nparam;
+	isl_size dim1;
 	enum isl_lp_result res;
 
-	if (!bset1 || !bset2)
+	nparam = isl_basic_set_dim(bset1, isl_dim_param);
+	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
+	if (nparam < 0 || dim1 < 0 || !bset2)
 		return isl_lp_error;
 
-	nparam = isl_basic_set_n_param(bset1);
-	dim1 = isl_basic_set_n_dim(bset1);
-
 	bmap1 = join_initial(bset1, bset2, pos);
-	if (!bmap1)
+	total = isl_basic_map_dim(bmap1, isl_dim_all);
+	if (total < 0)
 		return isl_lp_error;
 
-	total = isl_basic_map_total_dim(bmap1);
 	ctx = bmap1->ctx;
 	obj = isl_vec_alloc(ctx, 1 + total);
 	if (!obj)
@@ -9232,8 +9668,8 @@ static enum isl_lp_result basic_set_maximal_
diff erence_at(
  *	 0 if bset1 and bset2 are incomparable
  *	-2 if some error occurred.
  */
-int isl_basic_set_compare_at(struct isl_basic_set *bset1,
-	struct isl_basic_set *bset2, int pos)
+int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
+	__isl_keep isl_basic_set *bset2, int pos)
 {
 	isl_int opt;
 	enum isl_lp_result res;
@@ -9273,9 +9709,11 @@ int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
 {
 	isl_bool empty;
 	isl_basic_map *bmap;
-	unsigned dim1;
+	isl_size dim1;
 
 	dim1 = isl_basic_set_dim(bset1, isl_dim_set);
+	if (dim1 < 0)
+		return -2;
 	bmap = join_initial(bset1, bset2, pos);
 	bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
 					    isl_dim_out, dim1 - pos);
@@ -9338,11 +9776,11 @@ static isl_bool isl_basic_map_plain_has_fixed_var(
 {
 	int i;
 	int d;
-	unsigned total;
+	isl_size total;
 
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return isl_bool_error;
-	total = isl_basic_map_total_dim(bmap);
 	for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
 		for (; d+1 > pos; --d)
 			if (!isl_int_is_zero(bmap->eq[i][1+d]))
@@ -9439,9 +9877,8 @@ __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
 	enum isl_dim_type type, unsigned pos, isl_int *val)
 {
-	if (pos >= isl_map_dim(map, type))
-		isl_die(isl_map_get_ctx(map), isl_error_invalid,
-			"position out of bounds", return isl_bool_error);
+	if (isl_map_check_range(map, type, pos, 1) < 0)
+		return isl_bool_error;
 	return isl_map_plain_has_fixed_var(map,
 		map_offset(map, type) - 1 + pos, val);
 }
@@ -9484,14 +9921,48 @@ __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
 	return isl_map_plain_get_val_if_fixed(set, type, pos);
 }
 
+/* Return a sequence of values in the same space as "set"
+ * that are equal to the corresponding set dimensions of "set"
+ * for those set dimensions that obviously lie on a hyperplane
+ * where the dimension has a fixed value.
+ * The other elements are set to NaN.
+ */
+__isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
+	__isl_keep isl_set *set)
+{
+	int i;
+	isl_size n;
+	isl_space *space;
+	isl_multi_val *mv;
+
+	space = isl_space_drop_all_params(isl_set_get_space(set));
+	mv = isl_multi_val_alloc(space);
+	n = isl_multi_val_size(mv);
+	if (n < 0)
+		return isl_multi_val_free(mv);
+
+	for (i = 0; i < n; ++i) {
+		isl_val *v;
+
+		v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
+		mv = isl_multi_val_set_val(mv, i, v);
+	}
+
+	return mv;
+}
+
 /* Check if dimension dim has fixed value and if so and if val is not NULL,
  * then return this fixed value in *val.
  */
 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
 	unsigned dim, isl_int *val)
 {
-	return isl_basic_set_plain_has_fixed_var(bset,
-					isl_basic_set_n_param(bset) + dim, val);
+	isl_size nparam;
+
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (nparam < 0)
+		return isl_bool_error;
+	return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
 }
 
 /* Return -1 if the constraint "c1" should be sorted before "c2"
@@ -9543,29 +10014,36 @@ static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
 	isl_int *c1, isl_int *c2)
 {
-	unsigned total;
+	isl_size total;
+	unsigned size;
 
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return -2;
-	total = isl_basic_map_total_dim(bmap);
-	return sort_constraint_cmp(&c1, &c2, &total);
+	size = total;
+	return sort_constraint_cmp(&c1, &c2, &size);
 }
 
 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
 	__isl_take isl_basic_map *bmap)
 {
-	unsigned total;
+	isl_size total;
+	unsigned size;
 
 	if (!bmap)
 		return NULL;
 	if (bmap->n_ineq == 0)
 		return bmap;
-	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
+	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
 		return bmap;
-	total = isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
+	size = total;
 	if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
-		    &sort_constraint_cmp, &total) < 0)
+		    &sort_constraint_cmp, &size) < 0)
 		return isl_basic_map_free(bmap);
+	ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
 	return bmap;
 }
 
@@ -9579,21 +10057,15 @@ __isl_give isl_basic_set *isl_basic_set_sort_constraints(
 __isl_give isl_basic_map *isl_basic_map_normalize(
 	__isl_take isl_basic_map *bmap)
 {
-	if (!bmap)
-		return NULL;
-	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
-		return bmap;
 	bmap = isl_basic_map_remove_redundancies(bmap);
 	bmap = isl_basic_map_sort_constraints(bmap);
-	if (bmap)
-		ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
 	return bmap;
 }
 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
 	__isl_keep isl_basic_map *bmap2)
 {
 	int i, cmp;
-	unsigned total;
+	isl_size total;
 	isl_space *space1, *space2;
 
 	if (!bmap1 || !bmap2)
@@ -9622,7 +10094,9 @@ int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
 		return bmap1->n_ineq - bmap2->n_ineq;
 	if (bmap1->n_div != bmap2->n_div)
 		return bmap1->n_div - bmap2->n_div;
-	total = isl_basic_map_total_dim(bmap1);
+	total = isl_basic_map_dim(bmap1, isl_dim_all);
+	if (total < 0)
+		return -1;
 	for (i = 0; i < bmap1->n_eq; ++i) {
 		cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
 		if (cmp)
@@ -9794,8 +10268,9 @@ isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
 
 	if (map1 == map2)
 		return isl_bool_true;
-	if (!isl_space_is_equal(map1->dim, map2->dim))
-		return isl_bool_false;
+	equal = isl_map_has_equal_space(map1, map2);
+	if (equal < 0 || !equal)
+		return equal;
 
 	map1 = isl_map_copy(map1);
 	map2 = isl_map_copy(map2);
@@ -9854,12 +10329,13 @@ __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
 __isl_give isl_basic_map *isl_basic_map_list_intersect(
 	__isl_take isl_basic_map_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_basic_map *bmap;
 
-	if (!list)
-		return NULL;
 	n = isl_basic_map_list_n_basic_map(list);
+	if (n < 0)
+		goto error;
 	if (n < 1)
 		isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
 			"expecting non-empty list", goto error);
@@ -9894,14 +10370,15 @@ __isl_give isl_basic_set *isl_basic_set_list_intersect(
 __isl_give isl_set *isl_basic_set_list_union(
 	__isl_take isl_basic_set_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_basic_set *bset;
 	isl_set *set;
 
-	if (!list)
-		return NULL;
 	n = isl_basic_set_list_n_basic_set(list);
+	if (n < 0)
+		goto error;
 	if (n < 1)
 		isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
 			"expecting non-empty list", goto error);
@@ -9928,12 +10405,13 @@ __isl_give isl_set *isl_basic_set_list_union(
  */
 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_set *set;
 
-	if (!list)
-		return NULL;
 	n = isl_set_list_n_set(list);
+	if (n < 0)
+		goto error;
 	if (n < 1)
 		isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
 			"expecting non-empty list", goto error);
@@ -9956,14 +10434,14 @@ __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
 __isl_give isl_basic_map *isl_basic_map_product(
 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
 {
-	isl_space *dim_result = NULL;
+	isl_space *space_result = NULL;
 	struct isl_basic_map *bmap;
 	unsigned in1, in2, out1, out2, nparam, total, pos;
 	struct isl_dim_map *dim_map1, *dim_map2;
 
 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
 		goto error;
-	dim_result = isl_space_product(isl_space_copy(bmap1->dim),
+	space_result = isl_space_product(isl_space_copy(bmap1->dim),
 						   isl_space_copy(bmap2->dim));
 
 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
@@ -9984,7 +10462,7 @@ __isl_give isl_basic_map *isl_basic_map_product(
 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
 
-	bmap = isl_basic_map_alloc_space(dim_result,
+	bmap = isl_basic_map_alloc_space(space_result,
 			bmap1->n_div + bmap2->n_div,
 			bmap1->n_eq + bmap2->n_eq,
 			bmap1->n_ineq + bmap2->n_ineq);
@@ -10017,21 +10495,23 @@ __isl_give isl_basic_set *isl_basic_set_flat_product(
 __isl_give isl_basic_map *isl_basic_map_domain_product(
 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
 {
+	isl_space *space1, *space2;
 	isl_space *space_result = NULL;
 	isl_basic_map *bmap;
-	unsigned in1, in2, out, nparam, total, pos;
+	isl_size in1, in2, out, nparam;
+	unsigned total, pos;
 	struct isl_dim_map *dim_map1, *dim_map2;
 
-	if (!bmap1 || !bmap2)
-		goto error;
-
-	space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
-						isl_space_copy(bmap2->dim));
-
 	in1 = isl_basic_map_dim(bmap1, isl_dim_in);
 	in2 = isl_basic_map_dim(bmap2, isl_dim_in);
 	out = isl_basic_map_dim(bmap1, isl_dim_out);
 	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
+	if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
+		goto error;
+
+	space1 = isl_basic_map_get_space(bmap1);
+	space2 = isl_basic_map_get_space(bmap2);
+	space_result = isl_space_domain_product(space1, space2);
 
 	total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
@@ -10063,28 +10543,28 @@ __isl_give isl_basic_map *isl_basic_map_range_product(
 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
 {
 	isl_bool rational;
-	isl_space *dim_result = NULL;
+	isl_space *space_result = NULL;
 	isl_basic_map *bmap;
-	unsigned in, out1, out2, nparam, total, pos;
+	isl_size in, out1, out2, nparam;
+	unsigned total, pos;
 	struct isl_dim_map *dim_map1, *dim_map2;
 
 	rational = isl_basic_map_is_rational(bmap1);
 	if (rational >= 0 && rational)
 		rational = isl_basic_map_is_rational(bmap2);
-	if (!bmap1 || !bmap2 || rational < 0)
+	in = isl_basic_map_dim(bmap1, isl_dim_in);
+	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
+	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
+	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
+	if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
 		goto error;
 
 	if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
 		goto error;
 
-	dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
+	space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
 					   isl_space_copy(bmap2->dim));
 
-	in = isl_basic_map_dim(bmap1, isl_dim_in);
-	out1 = isl_basic_map_dim(bmap1, isl_dim_out);
-	out2 = isl_basic_map_dim(bmap2, isl_dim_out);
-	nparam = isl_basic_map_dim(bmap1, isl_dim_param);
-
 	total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
 	dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
 	dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
@@ -10097,7 +10577,7 @@ __isl_give isl_basic_map *isl_basic_map_range_product(
 	isl_dim_map_div(dim_map1, bmap1, pos += out2);
 	isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
 
-	bmap = isl_basic_map_alloc_space(dim_result,
+	bmap = isl_basic_map_alloc_space(space_result,
 			bmap1->n_div + bmap2->n_div,
 			bmap1->n_eq + bmap2->n_eq,
 			bmap1->n_ineq + bmap2->n_ineq);
@@ -10186,19 +10666,14 @@ static __isl_give isl_map *map_product(__isl_take isl_map *map1,
 
 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
  */
-static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
+__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
+	isl_map_align_params_bin(&map1, &map2);
 	return map_product(map1, map2, &isl_space_product,
 			&isl_basic_map_product, 0);
 }
 
-__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
-}
-
 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
  */
 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
@@ -10226,56 +10701,46 @@ __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
 
 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
  */
-static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
+__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
+	isl_map_align_params_bin(&map1, &map2);
 	return map_product(map1, map2, &isl_space_domain_product,
 				&isl_basic_map_domain_product, 1);
 }
 
 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
  */
-static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
+__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
+	isl_map_align_params_bin(&map1, &map2);
 	return map_product(map1, map2, &isl_space_range_product,
 				&isl_basic_map_range_product, 1);
 }
 
-__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2,
-						&map_domain_product_aligned);
-}
-
-__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2,
-						&map_range_product_aligned);
-}
-
 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
  */
 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
 {
 	isl_space *space;
-	int total1, keep1, total2, keep2;
+	isl_size total1, keep1, total2, keep2;
 
-	if (!map)
-		return NULL;
+	total1 = isl_map_dim(map, isl_dim_in);
+	total2 = isl_map_dim(map, isl_dim_out);
+	if (total1 < 0 || total2 < 0)
+		return isl_map_free(map);
 	if (!isl_space_domain_is_wrapping(map->dim) ||
 	    !isl_space_range_is_wrapping(map->dim))
 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
 			"not a product", return isl_map_free(map));
 
 	space = isl_map_get_space(map);
-	total1 = isl_space_dim(space, isl_dim_in);
-	total2 = isl_space_dim(space, isl_dim_out);
 	space = isl_space_factor_domain(space);
 	keep1 = isl_space_dim(space, isl_dim_in);
 	keep2 = isl_space_dim(space, isl_dim_out);
+	if (keep1 < 0 || keep2 < 0)
+		map = isl_map_free(map);
 	map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
 	map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
 	map = isl_map_reset_space(map, space);
@@ -10288,21 +10753,23 @@ __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_space *space;
-	int total1, keep1, total2, keep2;
+	isl_size total1, keep1, total2, keep2;
 
-	if (!map)
-		return NULL;
+	total1 = isl_map_dim(map, isl_dim_in);
+	total2 = isl_map_dim(map, isl_dim_out);
+	if (total1 < 0 || total2 < 0)
+		return isl_map_free(map);
 	if (!isl_space_domain_is_wrapping(map->dim) ||
 	    !isl_space_range_is_wrapping(map->dim))
 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
 			"not a product", return isl_map_free(map));
 
 	space = isl_map_get_space(map);
-	total1 = isl_space_dim(space, isl_dim_in);
-	total2 = isl_space_dim(space, isl_dim_out);
 	space = isl_space_factor_range(space);
 	keep1 = isl_space_dim(space, isl_dim_in);
 	keep2 = isl_space_dim(space, isl_dim_out);
+	if (keep1 < 0 || keep2 < 0)
+		map = isl_map_free(map);
 	map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
 	map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
 	map = isl_map_reset_space(map, space);
@@ -10315,18 +10782,20 @@ __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_space *space;
-	int total, keep;
+	isl_size total, keep;
 
-	if (!map)
-		return NULL;
+	total = isl_map_dim(map, isl_dim_in);
+	if (total < 0)
+		return isl_map_free(map);
 	if (!isl_space_domain_is_wrapping(map->dim))
 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
 			"domain is not a product", return isl_map_free(map));
 
 	space = isl_map_get_space(map);
-	total = isl_space_dim(space, isl_dim_in);
 	space = isl_space_domain_factor_domain(space);
 	keep = isl_space_dim(space, isl_dim_in);
+	if (keep < 0)
+		map = isl_map_free(map);
 	map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
 	map = isl_map_reset_space(map, space);
 
@@ -10338,18 +10807,20 @@ __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_space *space;
-	int total, keep;
+	isl_size total, keep;
 
-	if (!map)
-		return NULL;
+	total = isl_map_dim(map, isl_dim_in);
+	if (total < 0)
+		return isl_map_free(map);
 	if (!isl_space_domain_is_wrapping(map->dim))
 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
 			"domain is not a product", return isl_map_free(map));
 
 	space = isl_map_get_space(map);
-	total = isl_space_dim(space, isl_dim_in);
 	space = isl_space_domain_factor_range(space);
 	keep = isl_space_dim(space, isl_dim_in);
+	if (keep < 0)
+		map = isl_map_free(map);
 	map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
 	map = isl_map_reset_space(map, space);
 
@@ -10361,18 +10832,20 @@ __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_space *space;
-	int total, keep;
+	isl_size total, keep;
 
-	if (!map)
-		return NULL;
+	total = isl_map_dim(map, isl_dim_out);
+	if (total < 0)
+		return isl_map_free(map);
 	if (!isl_space_range_is_wrapping(map->dim))
 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
 			"range is not a product", return isl_map_free(map));
 
 	space = isl_map_get_space(map);
-	total = isl_space_dim(space, isl_dim_out);
 	space = isl_space_range_factor_domain(space);
 	keep = isl_space_dim(space, isl_dim_out);
+	if (keep < 0)
+		map = isl_map_free(map);
 	map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
 	map = isl_map_reset_space(map, space);
 
@@ -10384,18 +10857,20 @@ __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_space *space;
-	int total, keep;
+	isl_size total, keep;
 
-	if (!map)
-		return NULL;
+	total = isl_map_dim(map, isl_dim_out);
+	if (total < 0)
+		return isl_map_free(map);
 	if (!isl_space_range_is_wrapping(map->dim))
 		isl_die(isl_map_get_ctx(map), isl_error_invalid,
 			"range is not a product", return isl_map_free(map));
 
 	space = isl_map_get_space(map);
-	total = isl_space_dim(space, isl_dim_out);
 	space = isl_space_range_factor_range(space);
 	keep = isl_space_dim(space, isl_dim_out);
+	if (keep < 0)
+		map = isl_map_free(map);
 	map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
 	map = isl_map_reset_space(map, space);
 
@@ -10430,15 +10905,15 @@ uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
 {
 	int i;
 	uint32_t hash = isl_hash_init();
-	unsigned total;
+	isl_size total;
 
 	if (!bmap)
 		return 0;
 	bmap = isl_basic_map_copy(bmap);
 	bmap = isl_basic_map_normalize(bmap);
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return 0;
-	total = isl_basic_map_total_dim(bmap);
 	isl_hash_byte(hash, bmap->n_eq & 0xFF);
 	for (i = 0; i < bmap->n_eq; ++i) {
 		uint32_t c_hash;
@@ -10500,14 +10975,14 @@ uint32_t isl_set_get_hash(__isl_keep isl_set *set)
 
 /* Return the number of basic maps in the (current) representation of "map".
  */
-int isl_map_n_basic_map(__isl_keep isl_map *map)
+isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
 {
-	return map ? map->n : 0;
+	return map ? map->n : isl_size_error;
 }
 
-int isl_set_n_basic_set(__isl_keep isl_set *set)
+isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
 {
-	return set ? set->n : 0;
+	return set ? set->n : isl_size_error;
 }
 
 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
@@ -10564,7 +11039,7 @@ __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
 
 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
 {
-	isl_space *dim;
+	isl_space *space;
 
 	if (!bset)
 		return NULL;
@@ -10573,12 +11048,12 @@ __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
 	if (!bset)
 		return NULL;
 
-	dim = isl_basic_set_get_space(bset);
-	dim = isl_space_lift(dim, bset->n_div);
-	if (!dim)
+	space = isl_basic_set_get_space(bset);
+	space = isl_space_lift(space, bset->n_div);
+	if (!space)
 		goto error;
 	isl_space_free(bset->dim);
-	bset->dim = dim;
+	bset->dim = space;
 	bset->extra -= bset->n_div;
 	bset->n_div = 0;
 
@@ -10593,7 +11068,7 @@ __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)
 {
 	int i;
-	isl_space *dim;
+	isl_space *space;
 	unsigned n_div;
 
 	set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
@@ -10606,12 +11081,12 @@ __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
 		return NULL;
 
 	n_div = set->p[0]->n_div;
-	dim = isl_set_get_space(set);
-	dim = isl_space_lift(dim, n_div);
-	if (!dim)
+	space = isl_set_get_space(set);
+	space = isl_space_lift(space, n_div);
+	if (!space)
 		goto error;
 	isl_space_free(set->dim);
-	set->dim = dim;
+	set->dim = space;
 
 	for (i = 0; i < set->n; ++i) {
 		set->p[i] = isl_basic_set_lift(set->p[i]);
@@ -10627,13 +11102,12 @@ __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
 
 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
 {
-	unsigned dim;
+	isl_size dim;
 	int size = 0;
 
-	if (!bset)
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0)
 		return -1;
-
-	dim = isl_basic_set_total_dim(bset);
 	size += bset->n_eq * (1 + dim);
 	size += bset->n_ineq * (1 + dim);
 	size += bset->n_div * (2 + dim);
@@ -10828,11 +11302,13 @@ isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
 	struct isl_tab *tab = NULL;
 	struct isl_tab_undo *snap;
 	int i;
+	isl_size total;
 
-	if (!bset || !signs)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0 || !signs)
 		return isl_stat_error;
 
-	bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
+	bound = isl_vec_alloc(bset->ctx, 1 + total);
 	tab = isl_tab_from_basic_set(bset, 0);
 	if (!bound || !tab)
 		goto error;
@@ -10882,8 +11358,8 @@ isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
 {
 	if (!bset || !signs)
 		return isl_stat_error;
-	isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
-		return isl_stat_error);
+	if (isl_basic_set_check_range(bset, type, first, n) < 0)
+		return isl_stat_error;
 
 	first += pos(bset->dim, type) - 1;
 	return isl_basic_set_vars_get_sign(bset, first, n, signs);
@@ -10900,19 +11376,23 @@ isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
 {
 	int i;
-	unsigned n_out, o_out;
-	unsigned n_div, o_div;
+	isl_size n_out, n_div;
+	unsigned o_out, o_div;
 
 	if (isl_int_is_zero(bmap->div[div][0]))
 		return isl_bool_true;
 
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (n_out < 0)
+		return isl_bool_error;
 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
 
 	if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
 		return isl_bool_true;
 
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_bool_error;
 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
 
 	for (i = 0; i < n_div; ++i) {
@@ -10976,19 +11456,19 @@ static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
 {
 	int i, j;
 	isl_ctx *ctx;
-	unsigned total;
-	unsigned n_div, o_div;
-	unsigned n_out, o_out;
+	isl_size total;
+	isl_size n_div, n_out;
+	unsigned o_div, o_out;
 	int less;
 
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (total < 0 || n_out < 0 || n_div < 0)
 		return -1;
 
 	ctx = isl_basic_map_get_ctx(bmap);
-	total = isl_basic_map_total_dim(bmap);
-	n_out = isl_basic_map_dim(bmap, isl_dim_out);
 	o_out = isl_basic_map_offset(bmap, isl_dim_out);
-	n_div = isl_basic_map_dim(bmap, isl_dim_div);
 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
 	for (i = 0; i < bmap->n_ineq; ++i) {
 		if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
@@ -11053,15 +11533,15 @@ int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
 	int pos, int *div, int *ineq)
 {
 	int j, k, l;
-	unsigned n_out, o_out;
-	unsigned n_div, o_div;
-
-	if (!bmap)
-		return -1;
+	isl_size n_div, n_out;
+	unsigned o_div, o_out;
 
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
-	o_out = isl_basic_map_offset(bmap, isl_dim_out);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_out < 0 || n_div < 0)
+		return -1;
+
+	o_out = isl_basic_map_offset(bmap, isl_dim_out);
 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
 
 	if (ineq)
@@ -11108,12 +11588,11 @@ int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
 {
 	int i;
-	unsigned n_out;
-
-	if (!bmap)
-		return isl_bool_error;
+	isl_size n_out;
 
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (n_out < 0)
+		return isl_bool_error;
 
 	for (i = 0; i < n_out; ++i) {
 		int eq;
@@ -11300,16 +11779,18 @@ static int unique(isl_int *p, unsigned pos, unsigned len)
 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
 {
 	int i, j;
-	unsigned nvar;
+	isl_size nvar, n_div;
 	unsigned ovar;
 
-	if (!bset)
+	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	if (n_div < 0)
 		return isl_bool_error;
-
-	if (isl_basic_set_dim(bset, isl_dim_div) != 0)
+	if (n_div != 0)
 		return isl_bool_false;
 
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0)
+		return isl_bool_error;
 	ovar = isl_space_offset(bset->dim, isl_dim_set);
 	for (j = 0; j < nvar; ++j) {
 		int lower = 0, upper = 0;
@@ -11423,20 +11904,15 @@ isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
 
 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
 {
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
+	isl_space *space;
 
-	bmap->dim = isl_space_wrap(bmap->dim);
-	if (!bmap->dim)
-		goto error;
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_wrap(space);
+	bmap = isl_basic_map_restore_space(bmap, space);
 
 	bmap = isl_basic_map_finalize(bmap);
 
 	return bset_from_bmap(bmap);
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 /* Given a map A -> B, return the set (A -> B).
@@ -11476,32 +11952,22 @@ __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
 	enum isl_dim_type type)
 {
-	if (!bmap)
-		return NULL;
-
-	if (!isl_space_is_named_or_nested(bmap->dim, type))
-		return bmap;
-
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
+	isl_space *space;
 
-	bmap->dim = isl_space_reset(bmap->dim, type);
-	if (!bmap->dim)
-		goto error;
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_reset(space, type);
+	bmap = isl_basic_map_restore_space(bmap, space);
 
-	bmap = isl_basic_map_finalize(bmap);
+	bmap = isl_basic_map_mark_final(bmap);
 
 	return bmap;
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
 	enum isl_dim_type type)
 {
 	int i;
+	isl_space *space;
 
 	if (!map)
 		return NULL;
@@ -11518,9 +11984,10 @@ __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
 		if (!map->p[i])
 			goto error;
 	}
-	map->dim = isl_space_reset(map->dim, type);
-	if (!map->dim)
-		goto error;
+
+	space = isl_map_take_space(map);
+	space = isl_space_reset(space, type);
+	map = isl_map_restore_space(map, space);
 
 	return map;
 error:
@@ -11530,26 +11997,15 @@ __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
 
 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
 {
-	if (!bmap)
-		return NULL;
-
-	if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
-		return bmap;
-
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
+	isl_space *space;
 
-	bmap->dim = isl_space_flatten(bmap->dim);
-	if (!bmap->dim)
-		goto error;
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_flatten(space);
+	bmap = isl_basic_map_restore_space(bmap, space);
 
-	bmap = isl_basic_map_finalize(bmap);
+	bmap = isl_basic_map_mark_final(bmap);
 
 	return bmap;
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
@@ -11560,51 +12016,29 @@ __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
 	__isl_take isl_basic_map *bmap)
 {
-	if (!bmap)
-		return NULL;
-
-	if (!bmap->dim->nested[0])
-		return bmap;
-
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
+	isl_space *space;
 
-	bmap->dim = isl_space_flatten_domain(bmap->dim);
-	if (!bmap->dim)
-		goto error;
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_flatten_domain(space);
+	bmap = isl_basic_map_restore_space(bmap, space);
 
-	bmap = isl_basic_map_finalize(bmap);
+	bmap = isl_basic_map_mark_final(bmap);
 
 	return bmap;
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 __isl_give isl_basic_map *isl_basic_map_flatten_range(
 	__isl_take isl_basic_map *bmap)
 {
-	if (!bmap)
-		return NULL;
-
-	if (!bmap->dim->nested[1])
-		return bmap;
-
-	bmap = isl_basic_map_cow(bmap);
-	if (!bmap)
-		return NULL;
+	isl_space *space;
 
-	bmap->dim = isl_space_flatten_range(bmap->dim);
-	if (!bmap->dim)
-		goto error;
+	space = isl_basic_map_take_space(bmap);
+	space = isl_space_flatten_range(space);
+	bmap = isl_basic_map_restore_space(bmap, space);
 
-	bmap = isl_basic_map_finalize(bmap);
+	bmap = isl_basic_map_mark_final(bmap);
 
 	return bmap;
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 /* Remove any internal structure from the spaces of domain and range of "map".
@@ -11627,12 +12061,13 @@ __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_space *dim, *flat_dim;
+	isl_space *space, *flat_space;
 	isl_map *map;
 
-	dim = isl_set_get_space(set);
-	flat_dim = isl_space_flatten(isl_space_copy(dim));
-	map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
+	space = isl_set_get_space(set);
+	flat_space = isl_space_flatten(isl_space_copy(space));
+	map = isl_map_identity(isl_space_join(isl_space_reverse(space),
+						flat_space));
 	map = isl_map_intersect_domain(map, set);
 
 	return map;
@@ -11673,16 +12108,16 @@ __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
 {
 	isl_basic_map *res;
 	unsigned flags;
-	unsigned n_div;
+	isl_size n_div;
 
-	if (!bmap || !space || !dim_map)
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0 || !space || !dim_map)
 		goto error;
 
 	flags = bmap->flags;
 	ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
-	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
+	ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
 	ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
-	n_div = isl_basic_map_dim(bmap, isl_dim_div);
 	res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
 	res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
 	if (res)
@@ -11691,7 +12126,7 @@ __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
 	res = isl_basic_map_finalize(res);
 	return res;
 error:
-	free(dim_map);
+	isl_dim_map_free(dim_map);
 	isl_basic_map_free(bmap);
 	isl_space_free(space);
 	return NULL;
@@ -11727,10 +12162,10 @@ __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
 	map = isl_map_unmark_normalized(map);
 
 	isl_reordering_free(r);
-	free(dim_map);
+	isl_dim_map_free(dim_map);
 	return map;
 error:
-	free(dim_map);
+	isl_dim_map_free(dim_map);
 	isl_map_free(map);
 	isl_reordering_free(r);
 	return NULL;
@@ -11815,7 +12250,7 @@ __isl_give isl_basic_map *isl_basic_map_align_params(
 				    isl_reordering_get_space(exp),
 				    isl_dim_map_extend(dim_map, bmap));
 		isl_reordering_free(exp);
-		free(dim_map);
+		isl_dim_map_free(dim_map);
 	}
 
 	isl_space_free(model);
@@ -11870,11 +12305,13 @@ __isl_give isl_basic_set *isl_basic_set_align_params(
 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
 {
 	int i;
+	isl_size n;
 
-	if (isl_map_check_named_params(map) < 0)
+	n = isl_map_dim(map, isl_dim_param);
+	if (isl_map_check_named_params(map) < 0 || n < 0)
 		return isl_map_free(map);
 
-	for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
+	for (i = n - 1; i >= 0; i--) {
 		isl_bool involves;
 
 		involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
@@ -11900,12 +12337,14 @@ __isl_give isl_set *isl_set_drop_unused_params(
 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
 	__isl_take isl_basic_map *bmap)
 {
+	isl_size nparam;
 	int i;
 
-	if (isl_basic_map_check_named_params(bmap) < 0)
+	nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
 		return isl_basic_map_free(bmap);
 
-	for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
+	for (i = nparam - 1; i >= 0; i--) {
 		isl_bool involves;
 
 		involves = isl_basic_map_involves_dims(bmap,
@@ -11928,6 +12367,193 @@ __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
 							bset_to_bmap(bset)));
 }
 
+/* Given a tuple of identifiers "tuple" in a space that corresponds
+ * to that of "set", if any of those identifiers appear as parameters
+ * in "set", then equate those parameters with the corresponding
+ * set dimensions and project out the parameters.
+ * The result therefore has no such parameters.
+ */
+static __isl_give isl_set *equate_params(__isl_take isl_set *set,
+	__isl_keep isl_multi_id *tuple)
+{
+	int i;
+	isl_size n;
+	isl_space *set_space, *tuple_space;
+
+	set_space = isl_set_peek_space(set);
+	tuple_space = isl_multi_id_peek_space(tuple);
+	if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
+		return isl_set_free(set);
+	n = isl_multi_id_size(tuple);
+	if (n < 0)
+		return isl_set_free(set);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+		int pos;
+
+		id = isl_multi_id_get_at(tuple, i);
+		if (!id)
+			return isl_set_free(set);
+		pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
+		isl_id_free(id);
+		if (pos < 0)
+			continue;
+		set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
+		set = isl_set_project_out(set, isl_dim_param, pos, 1);
+	}
+	return set;
+}
+
+/* Bind the set dimensions of "set" to parameters with identifiers
+ * specified by "tuple", living in the same space as "set".
+ *
+ * If no parameters with these identifiers appear in "set" already,
+ * then the set dimensions are simply reinterpreted as parameters.
+ * Otherwise, the parameters are first equated to the corresponding
+ * set dimensions.
+ */
+__isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
+	__isl_take isl_multi_id *tuple)
+{
+	isl_space *space;
+
+	set = equate_params(set, tuple);
+	space = isl_set_get_space(set);
+	space = isl_space_bind_set(space, tuple);
+	isl_multi_id_free(tuple);
+	set = isl_set_reset_space(set, space);
+
+	return set;
+}
+
+/* Given a tuple of identifiers "tuple" in a space that corresponds
+ * to the domain of "map", if any of those identifiers appear as parameters
+ * in "map", then equate those parameters with the corresponding
+ * input dimensions and project out the parameters.
+ * The result therefore has no such parameters.
+ */
+static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
+	__isl_keep isl_multi_id *tuple)
+{
+	int i;
+	isl_size n;
+	isl_space *map_space, *tuple_space;
+
+	map_space = isl_map_peek_space(map);
+	tuple_space = isl_multi_id_peek_space(tuple);
+	if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
+		return isl_map_free(map);
+	n = isl_multi_id_size(tuple);
+	if (n < 0)
+		return isl_map_free(map);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+		int pos;
+
+		id = isl_multi_id_get_at(tuple, i);
+		if (!id)
+			return isl_map_free(map);
+		pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
+		isl_id_free(id);
+		if (pos < 0)
+			continue;
+		map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
+		map = isl_map_project_out(map, isl_dim_param, pos, 1);
+	}
+	return map;
+}
+
+/* Bind the input dimensions of "map" to parameters with identifiers
+ * specified by "tuple", living in the domain space of "map".
+ *
+ * If no parameters with these identifiers appear in "map" already,
+ * then the input dimensions are simply reinterpreted as parameters.
+ * Otherwise, the parameters are first equated to the corresponding
+ * input dimensions.
+ */
+__isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
+	__isl_take isl_multi_id *tuple)
+{
+	isl_space *space;
+	isl_set *set;
+
+	map = map_equate_params(map, tuple);
+	space = isl_map_get_space(map);
+	space = isl_space_bind_map_domain(space, tuple);
+	isl_multi_id_free(tuple);
+	set = set_from_map(isl_map_reset_space(map, space));
+
+	return set;
+}
+
+/* Bind the output dimensions of "map" to parameters with identifiers
+ * specified by "tuple", living in the range space of "map".
+ *
+ * Since binding is more easily implemented on the domain,
+ * bind the input dimensions of the inverse of "map".
+ */
+__isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
+	__isl_take isl_multi_id *tuple)
+{
+	return isl_map_bind_domain(isl_map_reverse(map), tuple);
+}
+
+/* Insert a domain corresponding to "tuple"
+ * into the nullary or unary relation "set".
+ * The result has an extra initial tuple and is therefore
+ * either a unary or binary relation.
+ * Any parameters with identifiers in "tuple" are reinterpreted
+ * as the corresponding domain dimensions.
+ */
+static __isl_give isl_map *unbind_params_insert_domain(
+	__isl_take isl_set *set, __isl_take isl_multi_id *tuple)
+{
+	isl_space *space;
+	isl_reordering *r;
+
+	space = isl_set_peek_space(set);
+	r = isl_reordering_unbind_params_insert_domain(space, tuple);
+	isl_multi_id_free(tuple);
+
+	return isl_map_realign(set_to_map(set), r);
+}
+
+/* Construct a set with "tuple" as domain from the parameter domain "set".
+ * Any parameters with identifiers in "tuple" are reinterpreted
+ * as the corresponding set dimensions.
+ */
+__isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
+	__isl_take isl_multi_id *tuple)
+{
+	isl_bool is_params;
+
+	is_params = isl_set_is_params(set);
+	if (is_params < 0)
+		set = isl_set_free(set);
+	else if (!is_params)
+		isl_die(isl_set_get_ctx(set), isl_error_invalid,
+			"expecting parameter domain", set = isl_set_free(set));
+	return set_from_map(unbind_params_insert_domain(set, tuple));
+}
+
+/* Construct a map with "domain" as domain and "set" as range.
+ * Any parameters with identifiers in "domain" are reinterpreted
+ * as the corresponding domain dimensions.
+ */
+__isl_give isl_map *isl_set_unbind_params_insert_domain(
+	__isl_take isl_set *set, __isl_take isl_multi_id *domain)
+{
+	isl_bool is_params;
+
+	is_params = isl_set_is_params(set);
+	if (is_params < 0)
+		set = isl_set_free(set);
+	else if (is_params)
+		isl_die(isl_set_get_ctx(set), isl_error_invalid,
+			"expecting proper set", set = isl_set_free(set));
+	return unbind_params_insert_domain(set, domain);
+}
+
 __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,
@@ -11937,17 +12563,21 @@ __isl_give isl_mat *isl_basic_map_equalities_matrix(
 	struct isl_mat *mat;
 	int i, j, k;
 	int pos;
+	isl_size total;
 
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return NULL;
-	mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
-				isl_basic_map_total_dim(bmap) + 1);
+	mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
 	if (!mat)
 		return NULL;
 	for (i = 0; i < bmap->n_eq; ++i)
 		for (j = 0, pos = 0; j < 5; ++j) {
 			int off = isl_basic_map_offset(bmap, c[j]);
-			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+			isl_size dim = isl_basic_map_dim(bmap, c[j]);
+			if (dim < 0)
+				return isl_mat_free(mat);
+			for (k = 0; k < dim; ++k) {
 				isl_int_set(mat->row[i][pos],
 					    bmap->eq[i][off + k]);
 				++pos;
@@ -11966,17 +12596,21 @@ __isl_give isl_mat *isl_basic_map_inequalities_matrix(
 	struct isl_mat *mat;
 	int i, j, k;
 	int pos;
+	isl_size total;
 
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return NULL;
-	mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
-				isl_basic_map_total_dim(bmap) + 1);
+	mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
 	if (!mat)
 		return NULL;
 	for (i = 0; i < bmap->n_ineq; ++i)
 		for (j = 0, pos = 0; j < 5; ++j) {
 			int off = isl_basic_map_offset(bmap, c[j]);
-			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+			isl_size dim = isl_basic_map_dim(bmap, c[j]);
+			if (dim < 0)
+				return isl_mat_free(mat);
+			for (k = 0; k < dim; ++k) {
 				isl_int_set(mat->row[i][pos],
 					    bmap->ineq[i][off + k]);
 				++pos;
@@ -11987,35 +12621,37 @@ __isl_give isl_mat *isl_basic_map_inequalities_matrix(
 }
 
 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
-	__isl_take isl_space *dim,
+	__isl_take isl_space *space,
 	__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)
 {
 	enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
-	isl_basic_map *bmap;
+	isl_basic_map *bmap = NULL;
+	isl_size dim;
 	unsigned total;
 	unsigned extra;
 	int i, j, k, l;
 	int pos;
 
-	if (!dim || !eq || !ineq)
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0 || !eq || !ineq)
 		goto error;
 
 	if (eq->n_col != ineq->n_col)
-		isl_die(dim->ctx, isl_error_invalid,
+		isl_die(space->ctx, isl_error_invalid,
 			"equalities and inequalities matrices should have "
 			"same number of columns", goto error);
 
-	total = 1 + isl_space_dim(dim, isl_dim_all);
+	total = 1 + dim;
 
 	if (eq->n_col < total)
-		isl_die(dim->ctx, isl_error_invalid,
+		isl_die(space->ctx, isl_error_invalid,
 			"number of columns too small", goto error);
 
 	extra = eq->n_col - total;
 
-	bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
+	bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
 				       eq->n_row, ineq->n_row);
 	if (!bmap)
 		goto error;
@@ -12031,7 +12667,10 @@ __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
 			goto error;
 		for (j = 0, pos = 0; j < 5; ++j) {
 			int off = isl_basic_map_offset(bmap, c[j]);
-			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+			isl_size dim = isl_basic_map_dim(bmap, c[j]);
+			if (dim < 0)
+				goto error;
+			for (k = 0; k < dim; ++k) {
 				isl_int_set(bmap->eq[l][off + k], 
 					    eq->row[i][pos]);
 				++pos;
@@ -12044,7 +12683,10 @@ __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
 			goto error;
 		for (j = 0, pos = 0; j < 5; ++j) {
 			int off = isl_basic_map_offset(bmap, c[j]);
-			for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+			isl_size dim = isl_basic_map_dim(bmap, c[j]);
+			if (dim < 0)
+				goto error;
+			for (k = 0; k < dim; ++k) {
 				isl_int_set(bmap->ineq[l][off + k], 
 					    ineq->row[i][pos]);
 				++pos;
@@ -12052,16 +12694,17 @@ __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
 		}
 	}
 
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_mat_free(eq);
 	isl_mat_free(ineq);
 
 	bmap = isl_basic_map_simplify(bmap);
 	return isl_basic_map_finalize(bmap);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_mat_free(eq);
 	isl_mat_free(ineq);
+	isl_basic_map_free(bmap);
 	return NULL;
 }
 
@@ -12114,8 +12757,9 @@ isl_bool isl_map_can_zip(__isl_keep isl_map *map)
 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
 {
 	unsigned pos;
-	unsigned n1;
-	unsigned n2;
+	isl_size n_in;
+	isl_size n1;
+	isl_size n2;
 
 	if (!bmap)
 		return NULL;
@@ -12123,10 +12767,12 @@ __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
 	if (!isl_basic_map_can_zip(bmap))
 		isl_die(bmap->ctx, isl_error_invalid,
 			"basic map cannot be zipped", goto error);
-	pos = isl_basic_map_offset(bmap, isl_dim_in) +
-		isl_space_dim(bmap->dim->nested[0], isl_dim_in);
+	n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
 	n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
 	n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
+	if (n_in < 0 || n1 < 0 || n2 < 0)
+		return isl_basic_map_free(bmap);
+	pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
 	bmap = isl_basic_map_cow(bmap);
 	bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
 	if (!bmap)
@@ -12146,8 +12792,6 @@ __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 i;
-
 	if (!map)
 		return NULL;
 
@@ -12155,21 +12799,7 @@ __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
 		isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
 			goto error);
 
-	map = isl_map_cow(map);
-	if (!map)
-		return NULL;
-
-	for (i = 0; i < map->n; ++i) {
-		map->p[i] = isl_basic_map_zip(map->p[i]);
-		if (!map->p[i])
-			goto error;
-	}
-
-	map->dim = isl_space_zip(map->dim);
-	if (!map->dim)
-		goto error;
-
-	return map;
+	return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
 error:
 	isl_map_free(map);
 	return NULL;
@@ -12320,16 +12950,13 @@ static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
 {
 	isl_basic_map *bmap = NULL;
 	int i;
+	isl_size total;
 
-	if (!space)
-		return NULL;
-
-	if (pos1 >= isl_space_dim(space, type1))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"index out of bounds", goto error);
-	if (pos2 >= isl_space_dim(space, type2))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"index out of bounds", goto error);
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0 ||
+	    isl_space_check_range(space, type1, pos1, 1) < 0 ||
+	    isl_space_check_range(space, type2, pos2, 1) < 0)
+		goto error;
 
 	if (type1 == type2 && pos1 == pos2)
 		return isl_basic_map_universe(space);
@@ -12338,7 +12965,7 @@ static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
 	i = isl_basic_map_alloc_equality(bmap);
 	if (i < 0)
 		goto error;
-	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->eq[i], 1 + total);
 	pos1 += isl_basic_map_offset(bmap, type1);
 	pos2 += isl_basic_map_offset(bmap, type2);
 	isl_int_set_si(bmap->eq[i][pos1], -1);
@@ -12387,22 +13014,21 @@ __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
 {
 	isl_basic_map *bmap = NULL;
 	int i;
+	isl_size total;
 
-	if (!map)
-		return NULL;
-
-	if (pos1 >= isl_map_dim(map, type1))
-		isl_die(map->ctx, isl_error_invalid,
-			"index out of bounds", goto error);
-	if (pos2 >= isl_map_dim(map, type2))
-		isl_die(map->ctx, isl_error_invalid,
-			"index out of bounds", goto error);
+	if (isl_map_check_range(map, type1, pos1, 1) < 0)
+		return isl_map_free(map);
+	if (isl_map_check_range(map, type2, pos2, 1) < 0)
+		return isl_map_free(map);
 
+	total = isl_map_dim(map, isl_dim_all);
+	if (total < 0)
+		return isl_map_free(map);
 	bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
 	i = isl_basic_map_alloc_equality(bmap);
 	if (i < 0)
 		goto error;
-	isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->eq[i], 1 + total);
 	pos1 += isl_basic_map_offset(bmap, type1);
 	pos2 += isl_basic_map_offset(bmap, type2);
 	isl_int_set_si(bmap->eq[i][pos1], 1);
@@ -12427,18 +13053,14 @@ static __isl_give isl_constraint *constraint_order_ge(
 {
 	isl_constraint *c;
 
+	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
+	    isl_space_check_range(space, type2, pos2, 1) < 0)
+		space = isl_space_free(space);
 	if (!space)
 		return NULL;
 
 	c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
 
-	if (pos1 >= isl_constraint_dim(c, type1))
-		isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
-			"index out of bounds", return isl_constraint_free(c));
-	if (pos2 >= isl_constraint_dim(c, type2))
-		isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
-			"index out of bounds", return isl_constraint_free(c));
-
 	if (type1 == type2 && pos1 == pos2)
 		return c;
 
@@ -12501,25 +13123,21 @@ static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
 {
 	isl_basic_map *bmap = NULL;
 	int i;
+	isl_size total;
 
-	if (!space)
-		return NULL;
-
-	if (pos1 >= isl_space_dim(space, type1))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"index out of bounds", goto error);
-	if (pos2 >= isl_space_dim(space, type2))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"index out of bounds", goto error);
+	if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
+	    isl_space_check_range(space, type2, pos2, 1) < 0)
+		goto error;
 
 	if (type1 == type2 && pos1 == pos2)
 		return isl_basic_map_empty(space);
 
 	bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
 	i = isl_basic_map_alloc_inequality(bmap);
-	if (i < 0)
+	if (total < 0 || i < 0)
 		return isl_basic_map_free(bmap);
-	isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->ineq[i], 1 + total);
 	pos1 += isl_basic_map_offset(bmap, type1);
 	pos2 += isl_basic_map_offset(bmap, type2);
 	isl_int_set_si(bmap->ineq[i][pos1], 1);
@@ -12632,6 +13250,7 @@ __isl_give isl_basic_set *isl_basic_set_substitute(
 	int i;
 	isl_int v;
 	isl_ctx *ctx;
+	isl_size n_div;
 
 	if (bset && isl_basic_set_plain_is_empty(bset))
 		return bset;
@@ -12644,7 +13263,10 @@ __isl_give isl_basic_set *isl_basic_set_substitute(
 	if (!isl_space_is_equal(bset->dim, subs->ls->dim))
 		isl_die(ctx, isl_error_invalid,
 			"spaces don't match", goto error);
-	if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
+	n_div = isl_local_space_dim(subs->ls, isl_dim_div);
+	if (n_div < 0)
+		goto error;
+	if (n_div != 0)
 		isl_die(ctx, isl_error_unsupported,
 			"cannot handle divs yet", goto error);
 	if (!isl_int_is_one(subs->v->el[0]))
@@ -12757,23 +13379,23 @@ static isl_stat check_basic_map_compatible_range_multi_aff(
  * the "n_after" coefficients after the transformed range of dimensions
  * and the coefficients of the other divs in "bmap".
  */
-static int set_ma_divs(__isl_keep isl_basic_map *bmap,
+static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
 	__isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
 {
 	int i;
-	int n_param;
-	int n_set;
+	isl_size n_param;
+	isl_size n_set;
 	isl_local_space *ls;
 
 	if (n_div == 0)
-		return 0;
+		return bmap;
 
 	ls = isl_aff_get_domain_local_space(ma->u.p[0]);
-	if (!ls)
-		return -1;
-
 	n_param = isl_local_space_dim(ls, isl_dim_param);
 	n_set = isl_local_space_dim(ls, isl_dim_set);
+	if (n_param < 0 || n_set < 0)
+		return isl_basic_map_free(bmap);
+
 	for (i = 0; i < n_div; ++i) {
 		int o_bmap = 0, o_ls = 0;
 
@@ -12793,15 +13415,16 @@ static int set_ma_divs(__isl_keep isl_basic_map *bmap,
 		o_bmap += n_div;
 		o_ls += n_div;
 		isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
-		if (isl_basic_map_add_div_constraints(bmap, i) < 0)
+		bmap = isl_basic_map_add_div_constraints(bmap, i);
+		if (!bmap)
 			goto error;
 	}
 
 	isl_local_space_free(ls);
-	return 0;
+	return bmap;
 error:
 	isl_local_space_free(ls);
-	return -1;
+	return isl_basic_map_free(bmap);
 }
 
 /* How many stride constraints does "ma" enforce?
@@ -12844,13 +13467,15 @@ static __isl_give isl_basic_map *add_ma_strides(
 {
 	int i, k;
 	int div;
-	int total;
-	int n_param;
-	int n_in;
+	isl_size total;
+	isl_size n_param;
+	isl_size n_in;
 
-	total = isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
 	n_param = isl_multi_aff_dim(ma, isl_dim_param);
 	n_in = isl_multi_aff_dim(ma, isl_dim_in);
+	if (total < 0 || n_param < 0 || n_in < 0)
+		return isl_basic_map_free(bmap);
 	for (i = 0; i < ma->n; ++i) {
 		int o_bmap = 0, o_ma = 1;
 
@@ -12957,7 +13582,7 @@ __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
 	int i, k;
 	isl_space *space;
 	isl_basic_map *res = NULL;
-	int n_before, n_after, n_div_bmap, n_div_ma;
+	isl_size n_before, n_after, n_div_bmap, n_div_ma;
 	isl_int f, c1, c2, g;
 	isl_bool rational;
 	int strides;
@@ -12982,6 +13607,8 @@ __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
 	}
 	n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
 	n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
+	if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
+		goto error;
 
 	space = isl_multi_aff_get_domain_space(ma);
 	space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
@@ -12996,23 +13623,28 @@ __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
 		if (isl_basic_map_alloc_div(res) < 0)
 			goto error;
 
-	if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
+	res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
+	if (!res)
 		goto error;
 
 	for (i = 0; i < bmap->n_eq; ++i) {
 		k = isl_basic_map_alloc_equality(res);
 		if (k < 0)
 			goto error;
-		isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
-				n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
+		if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
+				    n_after, n_div_ma, n_div_bmap,
+				    f, c1, c2, g, 0) < 0)
+			goto error;
 	}
 
 	for (i = 0; i < bmap->n_ineq; ++i) {
 		k = isl_basic_map_alloc_inequality(res);
 		if (k < 0)
 			goto error;
-		isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
-				n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
+		if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
+				    n_after, n_div_ma, n_div_bmap,
+				    f, c1, c2, g, 0) < 0)
+			goto error;
 	}
 
 	for (i = 0; i < bmap->n_div; ++i) {
@@ -13020,9 +13652,10 @@ __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
 			isl_int_set_si(res->div[n_div_ma + i][0], 0);
 			continue;
 		}
-		isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
+		if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
 				    n_before, n_after, n_div_ma, n_div_bmap,
-				    f, c1, c2, g, 1);
+				    f, c1, c2, g, 1) < 0)
+			goto error;
 	}
 
 	if (strides)
@@ -13135,9 +13768,9 @@ static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
 	space = isl_multi_aff_get_domain_space(ma);
 	space = isl_space_set(isl_map_get_space(map), type, space);
 
-	isl_space_free(map->dim);
-	map->dim = space;
-	if (!map->dim)
+	isl_space_free(isl_map_take_space(map));
+	map = isl_map_restore_space(map, space);
+	if (!map)
 		goto error;
 
 	isl_multi_aff_free(ma);
@@ -13362,14 +13995,14 @@ __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
 	enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
 {
-	int n;
+	isl_size n;
 	isl_bool full;
 	isl_pw_multi_aff *pma;
 
-	if (!map || !mpa)
+	n = isl_map_dim(map, type);
+	if (n < 0 || !mpa)
 		goto error;
 
-	n = isl_map_dim(map, type);
 	full = isl_map_involves_dims(map, type, 0, n);
 	if (full >= 0 && !full)
 		full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
@@ -13419,14 +14052,14 @@ __isl_give isl_mat *isl_basic_set_extract_equalities(
 	__isl_keep isl_basic_set *bset)
 {
 	isl_ctx *ctx;
-	unsigned total;
+	isl_size total;
 
-	if (!bset)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		return NULL;
 
 	ctx = isl_basic_set_get_ctx(bset);
-	total = 1 + isl_basic_set_dim(bset, isl_dim_all);
-	return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
+	return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
 }
 
 /* Are the "n" "coefficients" starting at "first" of the integer division
@@ -13456,12 +14089,13 @@ isl_bool isl_basic_map_equal_div_expr_except_constant(
 	__isl_keep isl_basic_map *bmap2, int pos2)
 {
 	isl_bool equal;
-	unsigned total;
+	isl_size total, total2;
 
-	if (!bmap1 || !bmap2)
+	total = isl_basic_map_dim(bmap1, isl_dim_all);
+	total2 = isl_basic_map_dim(bmap2, isl_dim_all);
+	if (total < 0 || total2 < 0)
 		return isl_bool_error;
-	total = isl_basic_map_total_dim(bmap1);
-	if (total != isl_basic_map_total_dim(bmap2))
+	if (total != total2)
 		isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
 			"incomparable div expressions", return isl_bool_error);
 	equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
@@ -13503,7 +14137,7 @@ static isl_bool is_internal(__isl_keep isl_vec *inner,
 {
 	isl_ctx *ctx;
 	int pos;
-	unsigned total;
+	isl_size total;
 
 	if (!inner || !bset)
 		return isl_bool_error;
@@ -13515,6 +14149,8 @@ static isl_bool is_internal(__isl_keep isl_vec *inner,
 		return isl_int_is_nonneg(ctx->normalize_gcd);
 
 	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
 	pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
 	return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
 }
@@ -13577,9 +14213,8 @@ __isl_give isl_basic_map *isl_basic_map_transform_dims(
 	if (trans->n_row != trans->n_col)
 		isl_die(trans->ctx, isl_error_invalid,
 			"expecting square transformation matrix", goto error);
-	if (first + trans->n_row > isl_basic_map_dim(bmap, type))
-		isl_die(trans->ctx, isl_error_invalid,
-			"oversized transformation matrix", goto error);
+	if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
+		goto error;
 
 	pos = isl_basic_map_offset(bmap, type) + first;
 
@@ -13593,7 +14228,7 @@ __isl_give isl_basic_map *isl_basic_map_transform_dims(
 		      isl_mat_copy(trans)) < 0)
 		goto error;
 
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+	ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
 	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
 
 	isl_mat_free(trans);

diff  --git a/polly/lib/External/isl/isl_map_bound_templ.c b/polly/lib/External/isl/isl_map_bound_templ.c
new file mode 100644
index 000000000000..116ab6fc8244
--- /dev/null
+++ b/polly/lib/External/isl/isl_map_bound_templ.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#include "isl_multi_macro.h"
+#undef TYPE
+#define TYPE CAT(isl_,BASE)
+
+/* Check that "map" and "multi" live in the same space, ignoring parameters.
+ */
+static isl_stat FN(check_map_equal_tuples_multi,BASE)(__isl_keep isl_map *map,
+	__isl_keep MULTI(BASE) *multi)
+{
+	isl_space *map_space, *multi_space;
+
+	map_space = isl_map_peek_space(map);
+	multi_space = FN(MULTI(BASE),peek_space)(multi);
+	return isl_space_check_equal_tuples(map_space, multi_space);
+}
+
+/* Apply "map_bound" to "map" with the corresponding value in "bound"
+ * for each output dimension.
+ */
+static __isl_give isl_map *FN(map_bound_multi,BASE)(__isl_take isl_map *map,
+	__isl_take MULTI(BASE) *bound,
+	__isl_give isl_map *map_bound(__isl_take isl_map *map,
+		unsigned pos, __isl_take TYPE *value))
+{
+	int i;
+	isl_size dim;
+
+	dim = isl_map_dim(map, isl_dim_out);
+	if (dim < 0 || FN(check_map_equal_tuples_multi,BASE)(map, bound) < 0)
+		goto error;
+
+	for (i = 0; i < dim; ++i) {
+		TYPE *el;
+
+		el = FN(MULTI(BASE),get_at)(bound, i);
+		map = map_bound(map, i, el);
+	}
+	FN(MULTI(BASE),free)(bound);
+	return map;
+error:
+	isl_map_free(map);
+	FN(MULTI(BASE),free)(bound);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_map_list.c b/polly/lib/External/isl/isl_map_list.c
index 5e9305f6441b..cb94c35e512e 100644
--- a/polly/lib/External/isl/isl_map_list.c
+++ b/polly/lib/External/isl/isl_map_list.c
@@ -6,8 +6,8 @@
 
 #include <isl_list_templ.h>
 
-#undef BASE
-#define BASE basic_map
+#undef EL_BASE
+#define EL_BASE basic_map
 
 #include <isl_list_templ.c>
 
@@ -16,8 +16,8 @@
 
 #include <isl_list_templ.h>
 
-#undef BASE
-#define BASE map
+#undef EL_BASE
+#define EL_BASE map
 
 #include <isl_list_templ.c>
 
@@ -26,7 +26,7 @@
 
 #include <isl_list_templ.h>
 
-#undef BASE
-#define BASE union_map
+#undef EL_BASE
+#define EL_BASE union_map
 
 #include <isl_list_templ.c>

diff  --git a/polly/lib/External/isl/isl_map_private.h b/polly/lib/External/isl/isl_map_private.h
index 1fbb6dcde6ec..4e9020daecf3 100644
--- a/polly/lib/External/isl/isl_map_private.h
+++ b/polly/lib/External/isl/isl_map_private.h
@@ -40,7 +40,7 @@ struct isl_basic_map {
 #define ISL_BASIC_MAP_NO_IMPLICIT	(1 << 2)
 #define ISL_BASIC_MAP_NO_REDUNDANT	(1 << 3)
 #define ISL_BASIC_MAP_RATIONAL		(1 << 4)
-#define ISL_BASIC_MAP_NORMALIZED	(1 << 5)
+#define ISL_BASIC_MAP_SORTED		(1 << 5)
 #define ISL_BASIC_MAP_NORMALIZED_DIVS	(1 << 6)
 #define ISL_BASIC_MAP_ALL_EQUALITIES	(1 << 7)
 #define ISL_BASIC_MAP_REDUCED_COEFFICIENTS	(1 << 8)
@@ -49,7 +49,7 @@ struct isl_basic_map {
 #define ISL_BASIC_SET_NO_IMPLICIT	(1 << 2)
 #define ISL_BASIC_SET_NO_REDUNDANT	(1 << 3)
 #define ISL_BASIC_SET_RATIONAL		(1 << 4)
-#define ISL_BASIC_SET_NORMALIZED	(1 << 5)
+#define ISL_BASIC_SET_SORTED		(1 << 5)
 #define ISL_BASIC_SET_NORMALIZED_DIVS	(1 << 6)
 #define ISL_BASIC_SET_ALL_EQUALITIES	(1 << 7)
 #define ISL_BASIC_SET_REDUCED_COEFFICIENTS	(1 << 8)
@@ -120,9 +120,6 @@ struct isl_map {
 __isl_give isl_basic_set *isl_basic_set_alloc(isl_ctx *ctx,
 	unsigned nparam, unsigned dim, unsigned extra,
 	unsigned n_eq, unsigned n_ineq);
-__isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
-	unsigned nparam, unsigned dim, unsigned extra,
-	unsigned n_eq, unsigned n_ineq);
 __isl_give isl_basic_set *isl_basic_set_extend_constraints(
 	__isl_take isl_basic_set *base, unsigned n_eq, unsigned n_ineq);
 __isl_give isl_basic_set *isl_basic_set_finalize(
@@ -138,9 +135,6 @@ __isl_give isl_basic_map *isl_basic_map_mark_final(
 	__isl_take isl_basic_map *bmap);
 __isl_give isl_basic_map *isl_basic_map_finalize(
 	__isl_take isl_basic_map *bmap);
-__isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
-	unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
-	unsigned n_eq, unsigned n_ineq);
 __isl_give isl_basic_map *isl_basic_map_extend_constraints(
 	__isl_take isl_basic_map *base, unsigned n_eq, unsigned n_ineq);
 __isl_give isl_basic_map *isl_basic_map_simplify(
@@ -170,17 +164,22 @@ __isl_keep isl_space *isl_basic_map_peek_space(
 	__isl_keep const isl_basic_map *bmap);
 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset);
 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map);
+__isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set);
 
 __isl_give isl_basic_set *isl_basic_set_reset_space(
 	__isl_take isl_basic_set *bset, __isl_take isl_space *dim);
 __isl_give isl_basic_map *isl_basic_map_reset_space(
 	__isl_take isl_basic_map *bmap, __isl_take isl_space *dim);
 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
-	__isl_take isl_space *dim);
+	__isl_take isl_space *space);
 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
 	__isl_take isl_space *space);
 
-unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
+isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type);
+isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type);
+unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
 					enum isl_dim_type type);
 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
 					enum isl_dim_type type);
@@ -194,15 +193,10 @@ isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
 	__isl_keep isl_basic_set *bset);
 
-__isl_give isl_basic_map *isl_basic_map_extend_space(
-	__isl_take isl_basic_map *base, __isl_take isl_space *dim,
+__isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
+	unsigned extra, unsigned n_eq, unsigned n_ineq);
+__isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
 	unsigned extra, unsigned n_eq, unsigned n_ineq);
-__isl_give isl_basic_set *isl_basic_set_extend_space(
-	__isl_take isl_basic_set *base,
-		__isl_take isl_space *dim, unsigned extra,
-		unsigned n_eq, unsigned n_ineq);
-struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
-		struct isl_basic_set *bset2, unsigned pos);
 
 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n);
 struct isl_set *isl_set_grow(struct isl_set *set, int n);
@@ -216,19 +210,23 @@ __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
 		unsigned extra, unsigned n_eq, unsigned n_ineq);
 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n,
 	unsigned flags);
-__isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
+__isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
 		unsigned extra, unsigned n_eq, unsigned n_ineq);
 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n,
 	unsigned flags);
 
 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap);
 int isl_basic_set_alloc_equality(struct isl_basic_set *bset);
-int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n);
-int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n);
-int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_free_inequality(
+	__isl_take isl_basic_set *bset, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_free_equality(
+	__isl_take isl_basic_map *bmap, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_free_equality(
+	__isl_take isl_basic_set *bset, unsigned n);
 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset);
 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap);
-int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_free_inequality(
+	__isl_take isl_basic_map *bmap, unsigned n);
 int isl_basic_map_alloc_div(struct isl_basic_map *bmap);
 __isl_give isl_basic_map *isl_basic_map_insert_div(
 	__isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div);
@@ -253,8 +251,10 @@ __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
 	__isl_take isl_basic_set *bset, __isl_keep isl_vec *vec);
 
-int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos);
+__isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
+	unsigned pos);
 
+isl_bool isl_basic_map_has_single_reference(__isl_keep isl_basic_map *bmap);
 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset);
 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap);
 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set);
@@ -270,8 +270,8 @@ __isl_give isl_basic_map *isl_basic_map_set_to_empty(
 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
 	__isl_take isl_basic_set *bset);
 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset);
-void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b);
-void isl_basic_set_swap_div(struct isl_basic_set *bset, int a, int b);
+__isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
+	int a, int b);
 __isl_give isl_basic_map *isl_basic_map_order_divs(
 	__isl_take isl_basic_map *bmap);
 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map);
@@ -287,6 +287,10 @@ __isl_give isl_basic_set *isl_basic_set_sort_divs(
 __isl_give isl_basic_map *isl_basic_map_sort_divs(
 	__isl_take isl_basic_map *bmap);
 __isl_give isl_map *isl_map_sort_divs(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_gauss5(__isl_take isl_basic_map *bmap,
+	int *progress,
+	isl_stat (*swap)(unsigned a, unsigned b, void *user),
+	isl_stat (*drop)(unsigned n, void *user), void *user);
 __isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap,
 	int *progress);
 __isl_give isl_basic_set *isl_basic_set_gauss(
@@ -320,6 +324,8 @@ __isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs(
 	__isl_take isl_basic_map *bmap);
 __isl_give isl_map *isl_map_drop_constraint_involving_unknown_divs(
 	__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
+	__isl_take isl_basic_map *bmap, unsigned first, unsigned n);
 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
 	__isl_take isl_basic_set *bset, unsigned first, unsigned n);
 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
@@ -361,9 +367,10 @@ __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
 	enum isl_dim_type type, unsigned first, unsigned n);
 
-int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
-	unsigned div, int sign);
-int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div);
+__isl_give isl_basic_map *isl_basic_map_add_div_constraint(
+	__isl_take isl_basic_map *bmap, unsigned div, int sign);
+__isl_give isl_basic_map *isl_basic_map_add_div_constraints(
+	__isl_take isl_basic_map *bmap, unsigned div);
 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
 	__isl_take isl_basic_map *bmap);
 __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs(
@@ -427,10 +434,6 @@ isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
 
 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i);
 
-int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
-	unsigned pos, isl_int *div);
-int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
-	unsigned pos, isl_int *div);
 isl_bool isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
 	isl_int *constraint, unsigned div);
 isl_bool isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset,
@@ -465,6 +468,13 @@ __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap);
 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
 	__isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap));
 
+isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset);
+isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset);
+
+isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n);
 isl_stat isl_map_check_named_params(__isl_keep isl_map *map);
 
 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
@@ -476,10 +486,10 @@ isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
 	__isl_keep isl_space *space);
 
-__isl_give isl_map *isl_map_align_params_map_map_and(
-	__isl_take isl_map *map1, __isl_take isl_map *map2,
-	__isl_give isl_map *(*fn)(__isl_take isl_map *map1,
-				    __isl_take isl_map *map2));
+isl_stat isl_map_align_params_bin(__isl_keep isl_map **map1,
+	__isl_keep isl_map **map2);
+isl_stat isl_map_align_params_set(__isl_keep isl_map **map,
+	__isl_keep isl_set **set);
 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
 	__isl_keep isl_map *map2,
 	isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2));
@@ -541,6 +551,18 @@ int isl_basic_set_count_upto(__isl_keep isl_basic_set *bset,
 	isl_int max, isl_int *count);
 int isl_set_count_upto(__isl_keep isl_set *set, isl_int max, isl_int *count);
 
+isl_stat isl_map_check_equal_tuples(__isl_keep isl_map *map);
+isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
+	__isl_keep isl_basic_set *bset2);
+isl_stat isl_basic_map_check_equal_space(__isl_keep isl_basic_map *bmap1,
+	__isl_keep isl_basic_map *bmap2);
+isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
+	__isl_keep isl_basic_set *bset);
+isl_stat isl_map_basic_map_check_equal_space(__isl_keep isl_map *map,
+	__isl_keep isl_basic_map *bmap);
+isl_stat isl_map_check_equal_space(__isl_keep isl_map *map1,
+	__isl_keep isl_map *map2);
+
 __isl_give isl_mat *isl_basic_set_extract_equalities(
 	__isl_keep isl_basic_set *bset);
 

diff  --git a/polly/lib/External/isl/isl_map_simplify.c b/polly/lib/External/isl/isl_map_simplify.c
index f7945561ba89..3f489ffb8300 100644
--- a/polly/lib/External/isl/isl_map_simplify.c
+++ b/polly/lib/External/isl/isl_map_simplify.c
@@ -49,10 +49,10 @@ __isl_give isl_basic_map *isl_basic_map_normalize_constraints(
 {
 	int i;
 	isl_int gcd;
-	unsigned total = isl_basic_map_total_dim(bmap);
+	isl_size total = isl_basic_map_dim(bmap, isl_dim_all);
 
-	if (!bmap)
-		return NULL;
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 
 	isl_int_init(gcd);
 	for (i = bmap->n_eq - 1; i >= 0; --i) {
@@ -62,7 +62,8 @@ __isl_give isl_basic_map *isl_basic_map_normalize_constraints(
 				bmap = isl_basic_map_set_to_empty(bmap);
 				break;
 			}
-			isl_basic_map_drop_equality(bmap, i);
+			if (isl_basic_map_drop_equality(bmap, i) < 0)
+				goto error;
 			continue;
 		}
 		if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
@@ -83,7 +84,8 @@ __isl_give isl_basic_map *isl_basic_map_normalize_constraints(
 				bmap = isl_basic_map_set_to_empty(bmap);
 				break;
 			}
-			isl_basic_map_drop_inequality(bmap, i);
+			if (isl_basic_map_drop_inequality(bmap, i) < 0)
+				goto error;
 			continue;
 		}
 		if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
@@ -96,6 +98,10 @@ __isl_give isl_basic_map *isl_basic_map_normalize_constraints(
 	isl_int_clear(gcd);
 
 	return bmap;
+error:
+	isl_int_clear(gcd);
+	isl_basic_map_free(bmap);
+	return NULL;
 }
 
 __isl_give isl_basic_set *isl_basic_set_normalize_constraints(
@@ -177,9 +183,12 @@ static __isl_give isl_basic_map *reduce_div_coefficients_of_div(
 	__isl_take isl_basic_map *bmap, int div)
 {
 	int i;
-	unsigned total = 1 + isl_basic_map_total_dim(bmap);
+	isl_size total;
 
-	for (i = 0; i < total; ++i) {
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
+	for (i = 0; i < 1 + total; ++i) {
 		isl_bool reduce;
 
 		reduce = needs_reduction(bmap, div, i);
@@ -234,23 +243,28 @@ static __isl_give isl_basic_map *reduce_div_coefficients(
  * The 
diff erence {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
  * and can therefore not influence the result of the floor.
  */
-static void normalize_div_expression(__isl_keep isl_basic_map *bmap, int div)
+static __isl_give isl_basic_map *normalize_div_expression(
+	__isl_take isl_basic_map *bmap, int div)
 {
-	unsigned total = isl_basic_map_total_dim(bmap);
+	isl_size total = isl_basic_map_dim(bmap, isl_dim_all);
 	isl_ctx *ctx = bmap->ctx;
 
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	if (isl_int_is_zero(bmap->div[div][0]))
-		return;
+		return bmap;
 	isl_seq_gcd(bmap->div[div] + 2, total, &ctx->normalize_gcd);
 	isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, bmap->div[div][0]);
 	if (isl_int_is_one(ctx->normalize_gcd))
-		return;
+		return bmap;
 	isl_int_fdiv_q(bmap->div[div][1], bmap->div[div][1],
 			ctx->normalize_gcd);
 	isl_int_divexact(bmap->div[div][0], bmap->div[div][0],
 			ctx->normalize_gcd);
 	isl_seq_scale_down(bmap->div[div] + 2, bmap->div[div] + 2,
 			ctx->normalize_gcd, total);
+
+	return bmap;
 }
 
 /* Remove any common factor in numerator and denominator of a div expression,
@@ -277,24 +291,27 @@ static __isl_give isl_basic_map *normalize_div_expressions(
 		return bmap;
 
 	for (i = 0; i < bmap->n_div; ++i)
-		normalize_div_expression(bmap, i);
+		bmap = normalize_div_expression(bmap, i);
 
 	return bmap;
 }
 
 /* Assumes divs have been ordered if keep_divs is set.
  */
-static void eliminate_var_using_equality(struct isl_basic_map *bmap,
+static __isl_give isl_basic_map *eliminate_var_using_equality(
+	__isl_take isl_basic_map *bmap,
 	unsigned pos, isl_int *eq, int keep_divs, int *progress)
 {
-	unsigned total;
-	unsigned space_total;
+	isl_size total;
+	isl_size v_div;
 	int k;
 	int last_div;
 
-	total = isl_basic_map_total_dim(bmap);
-	space_total = isl_space_dim(bmap->dim, isl_dim_all);
-	last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (total < 0 || v_div < 0)
+		return isl_basic_map_free(bmap);
+	last_div = isl_seq_last_non_zero(eq + 1 + v_div, bmap->n_div);
 	for (k = 0; k < bmap->n_eq; ++k) {
 		if (bmap->eq[k] == eq)
 			continue;
@@ -313,7 +330,8 @@ static void eliminate_var_using_equality(struct isl_basic_map *bmap,
 			*progress = 1;
 		isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
 		isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total);
-		ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+		ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+		ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
 	}
 
 	for (k = 0; k < bmap->n_div; ++k) {
@@ -333,11 +351,14 @@ static void eliminate_var_using_equality(struct isl_basic_map *bmap,
 		if (last_div == -1 || (keep_divs && last_div < k)) {
 			isl_seq_elim(bmap->div[k]+1, eq,
 					1+pos, 1+total, &bmap->div[k][0]);
-			normalize_div_expression(bmap, k);
+			bmap = normalize_div_expression(bmap, k);
+			if (!bmap)
+				return NULL;
 		} else
 			isl_seq_clr(bmap->div[k], 1 + total);
-		ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
 	}
+
+	return bmap;
 }
 
 /* Assumes divs have been ordered if keep_divs is set.
@@ -345,9 +366,14 @@ static void eliminate_var_using_equality(struct isl_basic_map *bmap,
 static __isl_give isl_basic_map *eliminate_div(__isl_take isl_basic_map *bmap,
 	isl_int *eq, unsigned div, int keep_divs)
 {
-	unsigned pos = isl_space_dim(bmap->dim, isl_dim_all) + div;
+	isl_size v_div;
+	unsigned pos;
 
-	eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL);
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(bmap);
+	pos = v_div + div;
+	bmap = eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL);
 
 	bmap = isl_basic_map_drop_div(bmap, div);
 
@@ -362,10 +388,15 @@ static isl_bool ok_to_eliminate_div(__isl_keep isl_basic_map *bmap, isl_int *eq,
 {
 	int k;
 	int last_div;
-	unsigned space_total = isl_space_dim(bmap->dim, isl_dim_all);
-	unsigned pos = space_total + div;
+	isl_size v_div;
+	unsigned pos;
+
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_bool_error;
+	pos = v_div + div;
 
-	last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
+	last_div = isl_seq_last_non_zero(eq + 1 + v_div, bmap->n_div);
 	if (last_div < 0 || last_div <= div)
 		return isl_bool_true;
 
@@ -394,7 +425,7 @@ static __isl_give isl_basic_map *eliminate_divs_eq(
 	if (!bmap)
 		return NULL;
 
-	off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	off = isl_basic_map_offset(bmap, isl_dim_div);
 
 	for (d = bmap->n_div - 1; d >= 0 ; --d) {
 		for (i = 0; i < bmap->n_eq; ++i) {
@@ -435,7 +466,7 @@ static __isl_give isl_basic_map *eliminate_divs_ineq(
 		return NULL;
 
 	ctx = bmap->ctx;
-	off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	off = isl_basic_map_offset(bmap, isl_dim_div);
 
 	for (d = bmap->n_div - 1; d >= 0 ; --d) {
 		for (i = 0; i < bmap->n_eq; ++i)
@@ -514,7 +545,8 @@ static isl_bool bmap_eq_involves_unknown_divs(__isl_keep isl_basic_map *bmap,
 static __isl_give isl_basic_map *set_div_from_eq(__isl_take isl_basic_map *bmap,
 	int div, int eq, int *progress)
 {
-	unsigned total, o_div;
+	isl_size total;
+	unsigned o_div;
 	isl_bool involves;
 
 	if (!bmap)
@@ -530,32 +562,56 @@ static __isl_give isl_basic_map *set_div_from_eq(__isl_take isl_basic_map *bmap,
 		return bmap;
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
 	isl_seq_neg(bmap->div[div] + 1, bmap->eq[eq], 1 + total);
 	isl_int_set_si(bmap->div[div][1 + o_div + div], 0);
 	isl_int_set(bmap->div[div][0], bmap->eq[eq][o_div + div]);
 	if (progress)
 		*progress = 1;
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
 
 	return bmap;
 }
 
-__isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap,
-	int *progress)
+/* Perform fangcheng (Gaussian elimination) on the equality
+ * constraints of "bmap".
+ * That is, put them into row-echelon form, starting from the last column
+ * backward and use them to eliminate the corresponding coefficients
+ * from all constraints.
+ *
+ * If "progress" is not NULL, then it gets set if the elimination
+ * result in any changes.
+ * The elimination process may result in some equality constraints
+ * getting interchanged or removed.
+ * If "swap" or "drop" are not NULL, then they get called when
+ * two equality constraints get interchanged or
+ * when a number of final equality constraints get removed.
+ * As a special case, if the input turns out to be empty,
+ * then drop gets called with the number of removed equality
+ * constraints set to the total number of equality constraints.
+ * If "swap" or "drop" are not NULL, then the local variables (if any)
+ * are assumed to be in a valid order.
+ */
+__isl_give isl_basic_map *isl_basic_map_gauss5(__isl_take isl_basic_map *bmap,
+	int *progress,
+	isl_stat (*swap)(unsigned a, unsigned b, void *user),
+	isl_stat (*drop)(unsigned n, void *user), void *user)
 {
 	int k;
 	int done;
 	int last_var;
 	unsigned total_var;
-	unsigned total;
+	isl_size total;
+	unsigned n_drop;
 
-	bmap = isl_basic_map_order_divs(bmap);
+	if (!swap && !drop)
+		bmap = isl_basic_map_order_divs(bmap);
 
-	if (!bmap)
-		return NULL;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 
-	total = isl_basic_map_total_dim(bmap);
 	total_var = total - bmap->n_div;
 
 	last_var = total - 1;
@@ -569,13 +625,16 @@ __isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap,
 		}
 		if (last_var < 0)
 			break;
-		if (k != done)
+		if (k != done) {
 			swap_equality(bmap, k, done);
+			if (swap && swap(k, done, user) < 0)
+				return isl_basic_map_free(bmap);
+		}
 		if (isl_int_is_neg(bmap->eq[done][1+last_var]))
 			isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total);
 
-		eliminate_var_using_equality(bmap, last_var, bmap->eq[done], 1,
-						progress);
+		bmap = eliminate_var_using_equality(bmap, last_var,
+						bmap->eq[done], 1, progress);
 
 		if (last_var >= total_var)
 			bmap = set_div_from_eq(bmap, last_var - total_var,
@@ -588,12 +647,23 @@ __isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap,
 	for (k = done; k < bmap->n_eq; ++k) {
 		if (isl_int_is_zero(bmap->eq[k][0]))
 			continue;
+		if (drop && drop(bmap->n_eq, user) < 0)
+			return isl_basic_map_free(bmap);
 		return isl_basic_map_set_to_empty(bmap);
 	}
-	isl_basic_map_free_equality(bmap, bmap->n_eq-done);
+	n_drop = bmap->n_eq - done;
+	bmap = isl_basic_map_free_equality(bmap, n_drop);
+	if (drop && drop(n_drop, user) < 0)
+		return isl_basic_map_free(bmap);
 	return bmap;
 }
 
+__isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap,
+	int *progress)
+{
+	return isl_basic_map_gauss5(bmap, progress, NULL, NULL, NULL);
+}
+
 __isl_give isl_basic_set *isl_basic_set_gauss(
 	__isl_take isl_basic_set *bset, int *progress)
 {
@@ -625,7 +695,7 @@ struct isl_constraint_index {
 	unsigned int size;
 	int bits;
 	isl_int ***index;
-	unsigned total;
+	isl_size total;
 };
 
 /* Fill in the "ci" data structure for holding the inequalities of "bmap".
@@ -638,7 +708,9 @@ static isl_stat create_constraint_index(struct isl_constraint_index *ci,
 	ci->index = NULL;
 	if (!bmap)
 		return isl_stat_error;
-	ci->total = isl_basic_set_total_dim(bmap);
+	ci->total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (ci->total < 0)
+		return isl_stat_error;
 	if (bmap->n_ineq == 0)
 		return isl_stat_ok;
 	ci->size = round_up(4 * (bmap->n_ineq + 1) / 3 - 1);
@@ -750,7 +822,7 @@ static __isl_give isl_basic_map *remove_duplicate_divs(
 	int k, l, h;
 	int bits;
 	struct isl_blk eq;
-	unsigned total_var;
+	isl_size v_div;
 	unsigned total;
 	struct isl_ctx *ctx;
 
@@ -758,8 +830,10 @@ static __isl_give isl_basic_map *remove_duplicate_divs(
 	if (!bmap || bmap->n_div <= 1)
 		return bmap;
 
-	total_var = isl_space_dim(bmap->dim, isl_dim_all);
-	total = total_var + bmap->n_div;
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(bmap);
+	total = v_div + bmap->n_div;
 
 	ctx = bmap->ctx;
 	for (k = bmap->n_div - 1; k >= 0; --k)
@@ -804,13 +878,13 @@ static __isl_give isl_basic_map *remove_duplicate_divs(
 		if (!elim_for[l])
 			continue;
 		k = elim_for[l] - 1;
-		isl_int_set_si(eq.data[1+total_var+k], -1);
-		isl_int_set_si(eq.data[1+total_var+l], 1);
+		isl_int_set_si(eq.data[1 + v_div + k], -1);
+		isl_int_set_si(eq.data[1 + v_div + l], 1);
 		bmap = eliminate_div(bmap, eq.data, l, 1);
 		if (!bmap)
 			break;
-		isl_int_set_si(eq.data[1+total_var+k], 0);
-		isl_int_set_si(eq.data[1+total_var+l], 0);
+		isl_int_set_si(eq.data[1 + v_div + k], 0);
+		isl_int_set_si(eq.data[1 + v_div + l], 0);
 	}
 
 	isl_blk_free(ctx, eq);
@@ -823,15 +897,17 @@ static __isl_give isl_basic_map *remove_duplicate_divs(
 static int n_pure_div_eq(struct isl_basic_map *bmap)
 {
 	int i, j;
-	unsigned total;
+	isl_size v_div;
 
-	total = isl_space_dim(bmap->dim, isl_dim_all);
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return -1;
 	for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i) {
-		while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
+		while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + v_div + j]))
 			--j;
 		if (j < 0)
 			break;
-		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1)
+		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + v_div, j) != -1)
 			return 0;
 	}
 	return i;
@@ -889,7 +965,7 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 	int *progress)
 {
 	int i, j, k;
-	int total;
+	isl_size v_div;
 	int div_eq;
 	struct isl_mat *B;
 	struct isl_vec *d;
@@ -912,14 +988,16 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS))
 		return bmap;
 
-	total = isl_space_dim(bmap->dim, isl_dim_all);
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
 	div_eq = n_pure_div_eq(bmap);
+	if (v_div < 0 || div_eq < 0)
+		return isl_basic_map_free(bmap);
 	if (div_eq == 0)
 		return bmap;
 
 	if (div_eq < bmap->n_eq) {
 		B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq,
-					bmap->n_eq - div_eq, 0, 1 + total);
+					bmap->n_eq - div_eq, 0, 1 + v_div);
 		C = isl_mat_variable_compression(B, &C2);
 		if (!C || !C2)
 			goto error;
@@ -935,11 +1013,11 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 	if (!d)
 		goto error;
 	for (i = 0, j = bmap->n_div-1; i < div_eq; ++i) {
-		while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
+		while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + v_div + j]))
 			--j;
-		isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]);
+		isl_int_set(d->block.data[i], bmap->eq[i][1 + v_div + j]);
 	}
-	B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
+	B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + v_div);
 
 	if (C) {
 		B = isl_mat_product(B, C);
@@ -970,11 +1048,12 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 	dropped = 0;
 	for (j = bmap->n_div - 1; j >= 0; --j) {
 		for (i = 0; i < bmap->n_eq; ++i)
-			if (!isl_int_is_zero(bmap->eq[i][1 + total + j]))
+			if (!isl_int_is_zero(bmap->eq[i][1 + v_div + j]))
 				break;
 		if (i < bmap->n_eq) {
 			bmap = isl_basic_map_drop_div(bmap, j);
-			isl_basic_map_drop_equality(bmap, i);
+			if (isl_basic_map_drop_equality(bmap, i) < 0)
+				goto error;
 			++dropped;
 		}
 	}
@@ -987,8 +1066,7 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 			needed++;
 	}
 	if (needed > dropped) {
-		bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
-				needed, needed, 0);
+		bmap = isl_basic_map_extend(bmap, needed, needed, 0);
 		if (!bmap)
 			goto error;
 	}
@@ -996,11 +1074,11 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 		if (isl_int_is_one(T->row[i][i]))
 			continue;
 		k = isl_basic_map_alloc_div(bmap);
-		pos[i] = 1 + total + k;
-		isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div);
+		pos[i] = 1 + v_div + k;
+		isl_seq_clr(bmap->div[k] + 1, 1 + v_div + bmap->n_div);
 		isl_int_set(bmap->div[k][0], T->row[i][i]);
 		if (C2)
-			isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total);
+			isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + v_div);
 		else
 			isl_int_set_si(bmap->div[k][1 + i], 1);
 		for (j = 0; j < i; ++j) {
@@ -1008,13 +1086,13 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 				continue;
 			if (pos[j] < T->n_row && C2)
 				isl_seq_submul(bmap->div[k] + 1, T->row[i][j],
-						C2->row[pos[j]], 1 + total);
+						C2->row[pos[j]], 1 + v_div);
 			else
 				isl_int_neg(bmap->div[k][1 + pos[j]],
 								T->row[i][j]);
 		}
 		j = isl_basic_map_alloc_equality(bmap);
-		isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div);
+		isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+v_div+bmap->n_div);
 		isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0]);
 	}
 	free(pos);
@@ -1032,13 +1110,14 @@ static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
 	isl_mat_free(C);
 	isl_mat_free(C2);
 	isl_mat_free(T);
-	return bmap;
+	isl_basic_map_free(bmap);
+	return NULL;
 }
 
 static __isl_give isl_basic_map *set_div_from_lower_bound(
 	__isl_take isl_basic_map *bmap, int div, int ineq)
 {
-	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	unsigned total = isl_basic_map_offset(bmap, isl_dim_div);
 
 	isl_seq_neg(bmap->div[div] + 1, bmap->ineq[ineq], total + bmap->n_div);
 	isl_int_set(bmap->div[div][0], bmap->ineq[ineq][total + div]);
@@ -1059,7 +1138,7 @@ static isl_bool ok_to_set_div_from_bound(__isl_keep isl_basic_map *bmap,
 	int div, int ineq)
 {
 	int j;
-	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	unsigned total = isl_basic_map_offset(bmap, isl_dim_div);
 
 	/* Not defined in terms of unknown divs */
 	for (j = 0; j < bmap->n_div; ++j) {
@@ -1095,7 +1174,7 @@ static isl_bool ok_to_set_div_from_bound(__isl_keep isl_basic_map *bmap,
 static isl_bool better_div_constraint(__isl_keep isl_basic_map *bmap,
 	int div, int ineq)
 {
-	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	unsigned total = isl_basic_map_offset(bmap, isl_dim_div);
 	int last_div;
 	int last_ineq;
 
@@ -1130,7 +1209,7 @@ static __isl_give isl_basic_map *check_for_div_constraints(
 	int *progress)
 {
 	int i;
-	unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	unsigned total = isl_basic_map_offset(bmap, isl_dim_div);
 
 	for (i = 0; i < bmap->n_div; ++i) {
 		isl_bool set_div;
@@ -1162,10 +1241,10 @@ __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
 {
 	struct isl_constraint_index ci;
 	int k, l, h;
-	unsigned total = isl_basic_map_total_dim(bmap);
+	isl_size total = isl_basic_map_dim(bmap, isl_dim_all);
 	isl_int sum;
 
-	if (!bmap || bmap->n_ineq <= 1)
+	if (total < 0 || bmap->n_ineq <= 1)
 		return bmap;
 
 	if (create_constraint_index(&ci, bmap) < 0)
@@ -1188,7 +1267,7 @@ __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
 		--k;
 	}
 	isl_int_init(sum);
-	for (k = 0; k < bmap->n_ineq-1; ++k) {
+	for (k = 0; bmap && k < bmap->n_ineq-1; ++k) {
 		isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
 		h = hash_index(&ci, bmap, k);
 		isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
@@ -1292,7 +1371,7 @@ static __isl_give isl_basic_map *eliminate_unit_divs(
 		return NULL;
 
 	ctx = isl_basic_map_get_ctx(bmap);
-	total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+	total = isl_basic_map_offset(bmap, isl_dim_div);
 
 	for (i = 0; i < bmap->n_div; ++i) {
 		if (isl_int_is_zero(bmap->div[i][0]))
@@ -1328,8 +1407,9 @@ static __isl_give isl_basic_map *eliminate_unit_divs(
 			}
 
 			bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
-			if (isl_basic_map_add_div_constraint(bmap, i, s) < 0)
-				return isl_basic_map_free(bmap);
+			bmap = isl_basic_map_add_div_constraint(bmap, i, s);
+			if (!bmap)
+				return NULL;
 		}
 	}
 
@@ -1382,7 +1462,7 @@ isl_bool isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
 	if (!bmap)
 		return isl_bool_error;
 
-	pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
+	pos = isl_basic_map_offset(bmap, isl_dim_div) + div;
 
 	if (isl_int_eq(constraint[pos], bmap->div[div][0])) {
 		int neg;
@@ -1428,7 +1508,11 @@ isl_bool isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset,
 static isl_bool div_is_redundant(__isl_keep isl_basic_map *bmap, int div)
 {
 	int i;
-	unsigned pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
+	isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	unsigned pos = 1 + v_div + div;
+
+	if (v_div < 0)
+		return isl_bool_error;
 
 	for (i = 0; i < bmap->n_eq; ++i)
 		if (!isl_int_is_zero(bmap->eq[i][pos]))
@@ -1464,9 +1548,11 @@ static __isl_give isl_basic_map *remove_redundant_divs(
 	__isl_take isl_basic_map *bmap)
 {
 	int i;
+	isl_size v_div;
 
-	if (!bmap)
-		return NULL;
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(bmap);
 
 	for (i = bmap->n_div-1; i >= 0; --i) {
 		isl_bool redundant;
@@ -1476,6 +1562,8 @@ static __isl_give isl_basic_map *remove_redundant_divs(
 			return isl_basic_map_free(bmap);
 		if (!redundant)
 			continue;
+		bmap = isl_basic_map_drop_constraints_involving(bmap,
+								v_div + i, 1);
 		bmap = isl_basic_map_drop_div(bmap, i);
 	}
 	return bmap;
@@ -1540,14 +1628,14 @@ __isl_give isl_basic_map *isl_basic_map_eliminate_vars(
 {
 	int d;
 	int i, j, k;
-	unsigned total;
+	isl_size total;
 	int need_gauss = 0;
 
 	if (n == 0)
 		return bmap;
-	if (!bmap)
-		return NULL;
-	total = isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 
 	bmap = isl_basic_map_cow(bmap);
 	for (d = pos + n - 1; d >= 0 && d >= pos; --d)
@@ -1565,8 +1653,10 @@ __isl_give isl_basic_map *isl_basic_map_eliminate_vars(
 		for (i = 0; i < bmap->n_eq; ++i) {
 			if (isl_int_is_zero(bmap->eq[i][1+d]))
 				continue;
-			eliminate_var_using_equality(bmap, d, bmap->eq[i], 0, NULL);
-			isl_basic_map_drop_equality(bmap, i);
+			bmap = eliminate_var_using_equality(bmap, d,
+							bmap->eq[i], 0, NULL);
+			if (isl_basic_map_drop_equality(bmap, i) < 0)
+				return isl_basic_map_free(bmap);
 			need_gauss = 1;
 			break;
 		}
@@ -1620,7 +1710,6 @@ __isl_give isl_basic_map *isl_basic_map_eliminate_vars(
 				break;
 		}
 	}
-	ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
 	if (need_gauss)
 		bmap = isl_basic_map_gauss(bmap, NULL);
 	return bmap;
@@ -1652,9 +1741,8 @@ __isl_give isl_basic_map *isl_basic_map_eliminate(
 	if (n == 0)
 		return bmap;
 
-	if (first + n > isl_basic_map_dim(bmap, type) || first + n < first)
-		isl_die(bmap->ctx, isl_error_invalid,
-			"index out of bounds", goto error);
+	if (isl_basic_map_check_range(bmap, type, first, n) < 0)
+		return isl_basic_map_free(bmap);
 
 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
 		first += isl_basic_map_offset(bmap, type) - 1;
@@ -1667,9 +1755,6 @@ __isl_give isl_basic_map *isl_basic_map_eliminate(
 	bmap = isl_basic_map_insert_dims(bmap, type, first, n);
 	bmap = isl_basic_map_reset_space(bmap, space);
 	return bmap;
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
 }
 
 __isl_give isl_basic_set *isl_basic_set_eliminate(
@@ -1694,7 +1779,8 @@ __isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs(
 	__isl_take isl_basic_map *bmap)
 {
 	isl_bool known;
-	int i, n_div, o_div;
+	isl_size n_div;
+	int i, o_div;
 
 	known = isl_basic_map_divs_known(bmap);
 	if (known < 0)
@@ -1703,6 +1789,8 @@ __isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs(
 		return bmap;
 
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_basic_map_free(bmap);
 	o_div = isl_basic_map_offset(bmap, isl_dim_div) - 1;
 
 	for (i = 0; i < n_div; ++i) {
@@ -1714,9 +1802,9 @@ __isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs(
 		bmap = remove_dependent_vars(bmap, o_div + i);
 		bmap = isl_basic_map_drop_constraints_involving_dims(bmap,
 							    isl_dim_div, i, 1);
-		if (!bmap)
-			return NULL;
 		n_div = isl_basic_map_dim(bmap, isl_dim_div);
+		if (n_div < 0)
+			return isl_basic_map_free(bmap);
 		i = -1;
 	}
 
@@ -1820,6 +1908,7 @@ static __isl_give isl_basic_set *isl_basic_set_reduce_using_equalities(
 {
 	int i;
 	int *elim;
+	isl_size dim;
 
 	if (!bset || !context)
 		goto error;
@@ -1830,10 +1919,11 @@ static __isl_give isl_basic_set *isl_basic_set_reduce_using_equalities(
 	}
 
 	bset = isl_basic_set_cow(bset);
-	if (!bset)
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
 		goto error;
 
-	elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset));
+	elim = isl_alloc_array(bset->ctx, int, dim);
 	if (!elim)
 		goto error;
 	set_compute_elimination_index(context, elim);
@@ -1864,7 +1954,7 @@ static isl_stat mark_shifted_constraints(__isl_keep isl_mat *ineq,
 	__isl_keep isl_basic_set *context, int *row)
 {
 	struct isl_constraint_index ci;
-	int n_ineq;
+	isl_size n_ineq, cols;
 	unsigned total;
 	int k;
 
@@ -1876,7 +1966,10 @@ static isl_stat mark_shifted_constraints(__isl_keep isl_mat *ineq,
 		return isl_stat_error;
 
 	n_ineq = isl_mat_rows(ineq);
-	total = isl_mat_cols(ineq) - 1;
+	cols = isl_mat_cols(ineq);
+	if (n_ineq < 0 || cols < 0)
+		return isl_stat_error;
+	total = cols - 1;
 	for (k = 0; k < n_ineq; ++k) {
 		int l;
 		isl_bool redundant;
@@ -1994,9 +2087,12 @@ static int is_related(isl_int *c, int len, int *relevant)
 static __isl_give isl_basic_map *drop_unrelated_constraints(
 	__isl_take isl_basic_map *bmap, int *relevant)
 {
-	int i, dim;
+	int i;
+	isl_size dim;
 
 	dim = isl_basic_map_dim(bmap, isl_dim_all);
+	if (dim < 0)
+		return isl_basic_map_free(bmap);
 	for (i = 0; i < dim; ++i)
 		if (!relevant[i])
 			break;
@@ -2059,9 +2155,11 @@ static void update_groups(int dim, int *group, isl_int *c)
 static int *alloc_groups(__isl_keep isl_basic_set *context)
 {
 	isl_ctx *ctx;
-	int dim;
+	isl_size dim;
 
 	dim = isl_basic_set_dim(context, isl_dim_set);
+	if (dim < 0)
+		return NULL;
 	ctx = isl_basic_set_get_ctx(context);
 	return isl_calloc_array(ctx, int, dim);
 }
@@ -2089,14 +2187,13 @@ static int *alloc_groups(__isl_keep isl_basic_set *context)
 __isl_give isl_basic_map *isl_basic_map_drop_unrelated_constraints(
 	__isl_take isl_basic_map *bmap, __isl_take int *group)
 {
-	int dim;
+	isl_size dim;
 	int i;
 	int last;
 
-	if (!bmap)
-		return NULL;
-
 	dim = isl_basic_map_dim(bmap, isl_dim_all);
+	if (dim < 0)
+		return isl_basic_map_free(bmap);
 
 	last = -1;
 	for (i = 0; i < dim; ++i)
@@ -2139,10 +2236,11 @@ static __isl_give isl_basic_set *drop_irrelevant_constraints(
 	__isl_take isl_basic_set *context, __isl_keep isl_basic_set *bset)
 {
 	int *group;
-	int dim;
+	isl_size dim;
 	int i, j;
 
-	if (!context || !bset)
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (!context || dim < 0)
 		return isl_basic_set_free(context);
 
 	group = alloc_groups(context);
@@ -2150,7 +2248,6 @@ static __isl_give isl_basic_set *drop_irrelevant_constraints(
 	if (!group)
 		return isl_basic_set_free(context);
 
-	dim = isl_basic_set_dim(bset, isl_dim_set);
 	for (i = 0; i < dim; ++i) {
 		for (j = 0; j < bset->n_eq; ++j)
 			if (!isl_int_is_zero(bset->eq[j][1 + i]))
@@ -2185,10 +2282,13 @@ static __isl_give isl_basic_set *drop_irrelevant_constraints_marked(
 	__isl_take isl_basic_set *context, __isl_keep isl_mat *ineq, int *row)
 {
 	int *group;
-	int dim;
-	int i, j, n;
+	isl_size dim;
+	int i, j;
+	isl_size n;
 
-	if (!context || !ineq)
+	dim = isl_basic_set_dim(context, isl_dim_set);
+	n = isl_mat_rows(ineq);
+	if (dim < 0 || n < 0)
 		return isl_basic_set_free(context);
 
 	group = alloc_groups(context);
@@ -2196,8 +2296,6 @@ static __isl_give isl_basic_set *drop_irrelevant_constraints_marked(
 	if (!group)
 		return isl_basic_set_free(context);
 
-	dim = isl_basic_set_dim(context, isl_dim_set);
-	n = isl_mat_rows(ineq);
 	for (i = 0; i < dim; ++i) {
 		for (j = 0; j < n; ++j) {
 			if (row[j] < 0)
@@ -2394,8 +2492,7 @@ static __isl_give isl_basic_set *uset_gist_full(__isl_take isl_basic_set *bset,
 		if (tab->con[n_eq + r].is_redundant)
 			continue;
 		test = isl_basic_set_dup(combined);
-		if (isl_inequality_negate(test, r) < 0)
-			test = isl_basic_set_free(test);
+		test = isl_inequality_negate(test, r);
 		test = isl_basic_set_update_from_tab(test, tab);
 		is_empty = isl_basic_set_is_empty(test);
 		isl_basic_set_free(test);
@@ -2426,15 +2523,15 @@ static __isl_give isl_basic_set *uset_gist_full(__isl_take isl_basic_set *bset,
  */
 static __isl_give isl_mat *extract_ineq(__isl_keep isl_basic_set *bset)
 {
-	unsigned total;
+	isl_size total;
 	isl_ctx *ctx;
 	isl_mat *ineq;
 
-	if (!bset)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		return NULL;
 
 	ctx = isl_basic_set_get_ctx(bset);
-	total = isl_basic_set_total_dim(bset);
 	ineq = isl_mat_sub_alloc6(ctx, bset->ineq, 0, bset->n_ineq,
 				    0, 1 + total);
 
@@ -2488,7 +2585,8 @@ static __isl_give isl_basic_set *uset_gist_compressed(
 {
 	isl_ctx *ctx;
 	isl_mat *ineq;
-	int i, n_row, n_col;
+	int i;
+	isl_size n_row, n_col;
 	isl_int rem;
 
 	ineq = extract_ineq(bset);
@@ -2506,6 +2604,8 @@ static __isl_give isl_basic_set *uset_gist_compressed(
 	ctx = isl_mat_get_ctx(ineq);
 	n_row = isl_mat_rows(ineq);
 	n_col = isl_mat_cols(ineq);
+	if (n_row < 0 || n_col < 0)
+		goto error;
 	isl_int_init(rem);
 	for (i = 0; i < n_row; ++i) {
 		isl_seq_gcd(ineq->row[i] + 1, n_col - 1, &ctx->normalize_gcd);
@@ -2540,12 +2640,12 @@ static __isl_give isl_basic_set *uset_gist_compressed(
 static __isl_give isl_basic_set *project_onto_involved(
 	__isl_take isl_basic_set *bset, __isl_keep isl_basic_set *template)
 {
-	int i, n;
-
-	if (!bset || !template)
-		return isl_basic_set_free(bset);
+	int i;
+	isl_size n;
 
 	n = isl_basic_set_dim(template, isl_dim_set);
+	if (n < 0 || !template)
+		return isl_basic_set_free(bset);
 
 	for (i = 0; i < n; ++i) {
 		isl_bool involved;
@@ -2592,9 +2692,10 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
 	isl_mat *T;
 	isl_basic_set *aff;
 	isl_basic_set *aff_context;
-	unsigned total;
+	isl_size total;
 
-	if (!bset || !context)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0 || !context)
 		goto error;
 
 	context = drop_irrelevant_constraints(context, bset);
@@ -2618,7 +2719,6 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
 		isl_basic_set_free(aff);
 		return uset_gist_uncompressed(bset, context);
 	}
-	total = isl_basic_set_total_dim(bset);
 	eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total);
 	eq = isl_mat_cow(eq);
 	T = isl_mat_variable_compression(eq, NULL);
@@ -2654,7 +2754,7 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
 static int n_div_eq(__isl_keep isl_basic_map *bmap)
 {
 	int i;
-	int total, n_div;
+	isl_size total, n_div;
 
 	if (!bmap)
 		return -1;
@@ -2664,6 +2764,8 @@ static int n_div_eq(__isl_keep isl_basic_map *bmap)
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (total < 0 || n_div < 0)
+		return -1;
 	total -= n_div;
 
 	for (i = 0; i < bmap->n_eq; ++i)
@@ -2681,12 +2783,14 @@ static __isl_give isl_basic_map *basic_map_from_equalities(
 	__isl_take isl_space *space, __isl_take isl_mat *eq)
 {
 	int i, k;
+	isl_size total;
 	isl_basic_map *bmap = NULL;
 
-	if (!space || !eq)
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0 || !eq)
 		goto error;
 
-	if (1 + isl_space_dim(space, isl_dim_all) != eq->n_col)
+	if (1 + total != eq->n_col)
 		isl_die(isl_space_get_ctx(space), isl_error_internal,
 			"unexpected number of columns", goto error);
 
@@ -2800,12 +2904,14 @@ static __isl_give isl_mat *extract_compressed_stride_constraints(
 	__isl_keep isl_basic_map *bmap, int bmap_n_eq,
 	__isl_keep isl_basic_map *context, int context_n_eq)
 {
-	int total, n_div;
+	isl_size total, n_div;
 	isl_ctx *ctx;
 	isl_mat *A, *B, *T, *V;
 
 	total = isl_basic_map_dim(context, isl_dim_all);
 	n_div = isl_basic_map_dim(context, isl_dim_div);
+	if (total < 0 || n_div < 0)
+		return NULL;
 	total -= n_div;
 
 	ctx = isl_basic_map_get_ctx(bmap);
@@ -2821,7 +2927,10 @@ static __isl_give isl_mat *extract_compressed_stride_constraints(
 	T = isl_mat_product(V, T);
 
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
-	T = isl_mat_diagonal(T, isl_mat_identity(ctx, n_div));
+	if (n_div < 0)
+		T = isl_mat_free(T);
+	else
+		T = isl_mat_diagonal(T, isl_mat_identity(ctx, n_div));
 
 	A = isl_mat_sub_alloc6(ctx, bmap->eq,
 				0, bmap_n_eq, 0, 1 + total + n_div);
@@ -2926,15 +3035,14 @@ static __isl_give isl_basic_map *reduce_stride_constraints(
 	__isl_take isl_basic_map *bmap, int n, __isl_keep isl_mat *A)
 {
 	int i;
-	int total, n_div;
+	isl_size total, n_div;
 	int any = 0;
 	isl_int gcd;
 
-	if (!bmap || !A)
-		return isl_basic_map_free(bmap);
-
 	total = isl_basic_map_dim(bmap, isl_dim_all);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (total < 0 || n_div < 0 || !A)
+		return isl_basic_map_free(bmap);
 	total -= n_div;
 
 	isl_int_init(gcd);
@@ -3035,7 +3143,8 @@ __isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap,
 {
 	isl_basic_set *bset, *eq;
 	isl_basic_map *eq_bmap;
-	unsigned total, n_div, extra, n_eq, n_ineq;
+	isl_size total, n_div, n_div_bmap;
+	unsigned extra, n_eq, n_ineq;
 
 	if (!bmap || !context)
 		goto error;
@@ -3058,12 +3167,13 @@ __isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap,
 	bmap = isl_basic_map_remove_redundancies(bmap);
 	context = isl_basic_map_remove_redundancies(context);
 	context = isl_basic_map_align_divs(context, bmap);
-	if (!context)
-		goto error;
 
 	n_div = isl_basic_map_dim(context, isl_dim_div);
 	total = isl_basic_map_dim(bmap, isl_dim_all);
-	extra = n_div - isl_basic_map_dim(bmap, isl_dim_div);
+	n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0 || total < 0 || n_div_bmap < 0)
+		goto error;
+	extra = n_div - n_div_bmap;
 
 	bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
 	bset = isl_basic_set_add_dims(bset, isl_dim_set, extra);
@@ -3081,10 +3191,8 @@ __isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap,
 	n_ineq = bset->n_ineq;
 	eq = isl_basic_set_copy(bset);
 	eq = isl_basic_set_cow(eq);
-	if (isl_basic_set_free_inequality(eq, n_ineq) < 0)
-		eq = isl_basic_set_free(eq);
-	if (isl_basic_set_free_equality(bset, n_eq) < 0)
-		bset = isl_basic_set_free(bset);
+	eq = isl_basic_set_free_inequality(eq, n_ineq);
+	bset = isl_basic_set_free_equality(bset, n_eq);
 
 	eq_bmap = isl_basic_map_overlying_set(eq, isl_basic_map_copy(bmap));
 	eq_bmap = gist_strides(eq_bmap, context);
@@ -3120,9 +3228,8 @@ __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
 
 	context = isl_basic_map_remove_redundancies(context);
 	map = isl_map_cow(map);
-	if (!map || !context)
+	if (isl_map_basic_map_check_equal_space(map, context) < 0)
 		goto error;
-	isl_assert(map->ctx, isl_space_is_equal(map->dim, context->dim), goto error);
 	map = isl_map_compute_divs(map);
 	if (!map)
 		goto error;
@@ -3164,13 +3271,15 @@ static __isl_give isl_basic_map *drop_inequalities(
 	__isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context)
 {
 	int i1, i2;
-	unsigned total, extra;
+	isl_size total, bmap_total;
+	unsigned extra;
 
-	if (!bmap || !context)
+	total = isl_basic_map_dim(context, isl_dim_all);
+	bmap_total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0 || bmap_total < 0)
 		return isl_basic_map_free(bmap);
 
-	total = isl_basic_map_total_dim(context);
-	extra = isl_basic_map_total_dim(bmap) - total;
+	extra = bmap_total - total;
 
 	i1 = bmap->n_ineq - 1;
 	i2 = context->n_ineq - 1;
@@ -3219,13 +3328,15 @@ static __isl_give isl_basic_map *drop_equalities(
 	__isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context)
 {
 	int i1, i2;
-	unsigned total, extra;
+	isl_size total, bmap_total;
+	unsigned extra;
 
-	if (!bmap || !context)
+	total = isl_basic_map_dim(context, isl_dim_all);
+	bmap_total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0 || bmap_total < 0)
 		return isl_basic_map_free(bmap);
 
-	total = isl_basic_map_total_dim(context);
-	extra = isl_basic_map_total_dim(bmap) - total;
+	extra = bmap_total - total;
 
 	i1 = bmap->n_eq - 1;
 	i2 = context->n_eq - 1;
@@ -3437,12 +3548,12 @@ static __isl_give isl_map *replace_by_universe(__isl_take isl_map *map,
  * for the context.  These can then be used to simplify away
  * the corresponding constraints in "map".
  */
-static __isl_give isl_map *map_gist(__isl_take isl_map *map,
+__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
 	__isl_take isl_map *context)
 {
 	int equal;
 	int is_universe;
-	int single_disjunct_map, single_disjunct_context;
+	isl_size n_disjunct_map, n_disjunct_context;
 	isl_bool subset;
 	isl_basic_map *hull;
 
@@ -3456,15 +3567,18 @@ static __isl_give isl_map *map_gist(__isl_take isl_map *map,
 		return map;
 	}
 
+	isl_map_align_params_bin(&map, &context);
 	equal = isl_map_plain_is_equal(map, context);
 	if (equal < 0)
 		goto error;
 	if (equal)
 		return replace_by_universe(map, context);
 
-	single_disjunct_map = isl_map_n_basic_map(map) == 1;
-	single_disjunct_context = isl_map_n_basic_map(context) == 1;
-	if (!single_disjunct_map || !single_disjunct_context) {
+	n_disjunct_map = isl_map_n_basic_map(map);
+	n_disjunct_context = isl_map_n_basic_map(context);
+	if (n_disjunct_map < 0 || n_disjunct_context < 0)
+		goto error;
+	if (n_disjunct_map != 1 || n_disjunct_context != 1) {
 		subset = isl_map_is_subset(context, map);
 		if (subset < 0)
 			goto error;
@@ -3475,7 +3589,7 @@ static __isl_give isl_map *map_gist(__isl_take isl_map *map,
 	context = isl_map_compute_divs(context);
 	if (!context)
 		goto error;
-	if (single_disjunct_context) {
+	if (n_disjunct_context == 1) {
 		hull = isl_map_simple_hull(context);
 	} else {
 		isl_ctx *ctx;
@@ -3495,12 +3609,6 @@ static __isl_give isl_map *map_gist(__isl_take isl_map *map,
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
-	__isl_take isl_map *context)
-{
-	return isl_map_align_params_map_map_and(map, context, &map_gist);
-}
-
 struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
 						struct isl_basic_set *context)
 {
@@ -3583,19 +3691,19 @@ isl_bool isl_basic_map_plain_is_disjoint(__isl_keep isl_basic_map *bmap1,
 {
 	struct isl_vec *v = NULL;
 	int *elim = NULL;
-	unsigned total;
+	isl_size total;
 	int i;
 
-	if (!bmap1 || !bmap2)
+	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
 		return isl_bool_error;
-	isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
-			return isl_bool_error);
 	if (bmap1->n_div || bmap2->n_div)
 		return isl_bool_false;
 	if (!bmap1->n_eq && !bmap2->n_eq)
 		return isl_bool_false;
 
 	total = isl_space_dim(bmap1->dim, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
 	if (total == 0)
 		return isl_bool_false;
 	v = isl_vec_alloc(bmap1->ctx, 1 + total);
@@ -3783,11 +3891,11 @@ isl_bool isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
 
 	intersect = isl_map_plain_is_universe(map1);
 	if (intersect < 0 || intersect)
-		return intersect < 0 ? isl_bool_error : isl_bool_false;
+		return isl_bool_not(intersect);
 
 	intersect = isl_map_plain_is_universe(map2);
 	if (intersect < 0 || intersect)
-		return intersect < 0 ? isl_bool_error : isl_bool_false;
+		return isl_bool_not(intersect);
 
 	intersect = isl_map_plain_is_equal(map1, map2);
 	if (intersect < 0 || intersect)
@@ -3825,11 +3933,11 @@ isl_bool isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1,
 
 	intersect = isl_basic_map_plain_is_universe(bmap1);
 	if (intersect < 0 || intersect)
-		return intersect < 0 ? isl_bool_error : isl_bool_false;
+		return isl_bool_not(intersect);
 
 	intersect = isl_basic_map_plain_is_universe(bmap2);
 	if (intersect < 0 || intersect)
-		return intersect < 0 ? isl_bool_error : isl_bool_false;
+		return isl_bool_not(intersect);
 
 	test = isl_basic_map_intersect(isl_basic_map_copy(bmap1),
 		isl_basic_map_copy(bmap2));
@@ -3867,9 +3975,32 @@ static int is_zero_or_one(isl_int v)
 	return isl_int_is_zero(v) || isl_int_is_one(v) || isl_int_is_negone(v);
 }
 
+/* Are the "n" coefficients starting at "first" of inequality constraints
+ * "i" and "j" of "bmap" opposite to each other?
+ */
+static int is_opposite_part(__isl_keep isl_basic_map *bmap, int i, int j,
+	int first, int n)
+{
+	return isl_seq_is_neg(bmap->ineq[i] + first, bmap->ineq[j] + first, n);
+}
+
+/* Are inequality constraints "i" and "j" of "bmap" opposite to each other,
+ * apart from the constant term?
+ */
+static isl_bool is_opposite(__isl_keep isl_basic_map *bmap, int i, int j)
+{
+	isl_size total;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
+	return is_opposite_part(bmap, i, j, 1, total);
+}
+
 /* Check if we can combine a given div with lower bound l and upper
  * bound u with some other div and if so return that other div.
- * Otherwise return -1.
+ * Otherwise, return a position beyond the integer divisions.
+ * Return -1 on error.
  *
  * We first check that
  *	- the bounds are opposites of each other (except for the constant
@@ -3897,30 +4028,35 @@ static int is_zero_or_one(isl_int v)
  * If so, we return b so that "a + m b" can be replaced by
  * a single div "c = a + m b".
  */
-static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
+static int div_find_coalesce(__isl_keep isl_basic_map *bmap, int *pairs,
 	unsigned div, unsigned l, unsigned u)
 {
 	int i, j;
-	unsigned dim;
-	int coalesce = -1;
+	unsigned n_div;
+	isl_size v_div;
+	int coalesce;
+	isl_bool opp;
 
-	if (bmap->n_div <= 1)
-		return -1;
-	dim = isl_space_dim(bmap->dim, isl_dim_all);
-	if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim, div) != -1)
-		return -1;
-	if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim + div + 1,
-				   bmap->n_div - div - 1) != -1)
-		return -1;
-	if (!isl_seq_is_neg(bmap->ineq[l] + 1, bmap->ineq[u] + 1,
-			    dim + bmap->n_div))
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div <= 1)
+		return n_div;
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
 		return -1;
+	if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + v_div, div) != -1)
+		return n_div;
+	if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + v_div + div + 1,
+				   n_div - div - 1) != -1)
+		return n_div;
+	opp = is_opposite(bmap, l, u);
+	if (opp < 0 || !opp)
+		return opp < 0 ? -1 : n_div;
 
-	for (i = 0; i < bmap->n_div; ++i) {
+	for (i = 0; i < n_div; ++i) {
 		if (isl_int_is_zero(bmap->div[i][0]))
 			continue;
-		if (!isl_int_is_zero(bmap->div[i][1 + 1 + dim + div]))
-			return -1;
+		if (!isl_int_is_zero(bmap->div[i][1 + 1 + v_div + div]))
+			return n_div;
 	}
 
 	isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
@@ -3930,40 +4066,41 @@ static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
 		bmap = isl_basic_map_copy(bmap);
 		bmap = isl_basic_map_set_to_empty(bmap);
 		isl_basic_map_free(bmap);
-		return -1;
+		return n_div;
 	}
 	isl_int_add_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
-	for (i = 0; i < bmap->n_div; ++i) {
+	coalesce = n_div;
+	for (i = 0; i < n_div; ++i) {
 		if (i == div)
 			continue;
 		if (!pairs[i])
 			continue;
-		for (j = 0; j < bmap->n_div; ++j) {
+		for (j = 0; j < n_div; ++j) {
 			if (isl_int_is_zero(bmap->div[j][0]))
 				continue;
-			if (!isl_int_is_zero(bmap->div[j][1 + 1 + dim + i]))
+			if (!isl_int_is_zero(bmap->div[j][1 + 1 + v_div + i]))
 				break;
 		}
-		if (j < bmap->n_div)
+		if (j < n_div)
 			continue;
 		for (j = 0; j < bmap->n_ineq; ++j) {
 			int valid;
 			if (j == l || j == u)
 				continue;
-			if (isl_int_is_zero(bmap->ineq[j][1 + dim + div])) {
-				if (is_zero_or_one(bmap->ineq[j][1 + dim + i]))
+			if (isl_int_is_zero(bmap->ineq[j][1 + v_div + div])) {
+				if (is_zero_or_one(bmap->ineq[j][1 + v_div + i]))
 					continue;
 				break;
 			}
-			if (isl_int_is_zero(bmap->ineq[j][1 + dim + i]))
+			if (isl_int_is_zero(bmap->ineq[j][1 + v_div + i]))
 				break;
-			isl_int_mul(bmap->ineq[j][1 + dim + div],
-				    bmap->ineq[j][1 + dim + div],
+			isl_int_mul(bmap->ineq[j][1 + v_div + div],
+				    bmap->ineq[j][1 + v_div + div],
 				    bmap->ineq[l][0]);
-			valid = isl_int_eq(bmap->ineq[j][1 + dim + div],
-					   bmap->ineq[j][1 + dim + i]);
-			isl_int_divexact(bmap->ineq[j][1 + dim + div],
-					 bmap->ineq[j][1 + dim + div],
+			valid = isl_int_eq(bmap->ineq[j][1 + v_div + div],
+					   bmap->ineq[j][1 + v_div + i]);
+			isl_int_divexact(bmap->ineq[j][1 + v_div + div],
+					 bmap->ineq[j][1 + v_div + div],
 					 bmap->ineq[l][0]);
 			if (!valid)
 				break;
@@ -4081,9 +4218,13 @@ static isl_bool test_ineq_is_satisfied(__isl_keep isl_basic_map *bmap,
 static isl_bool int_between_bounds(__isl_keep isl_basic_map *bmap, int i,
 	int l, int u, struct test_ineq_data *data)
 {
-	unsigned offset, n_div;
+	unsigned offset;
+	isl_size n_div;
+
 	offset = isl_basic_map_offset(bmap, isl_dim_div);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_bool_error;
 
 	isl_int_gcd(data->g,
 		    bmap->ineq[l][offset + i], bmap->ineq[u][offset + i]);
@@ -4133,19 +4274,20 @@ static __isl_give isl_basic_map *drop_more_redundant_divs(
 {
 	isl_ctx *ctx;
 	struct test_ineq_data data = { NULL, NULL };
-	unsigned off, n_div;
+	unsigned off;
+	isl_size n_div;
 	int remove = -1;
 
 	isl_int_init(data.g);
 	isl_int_init(data.fl);
 	isl_int_init(data.fu);
 
-	if (!bmap)
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
 		goto error;
 
 	ctx = isl_basic_map_get_ctx(bmap);
 	off = isl_basic_map_offset(bmap, isl_dim_div);
-	n_div = isl_basic_map_dim(bmap, isl_dim_div);
 	data.v = isl_vec_alloc(ctx, off + n_div);
 	if (!data.v)
 		goto error;
@@ -4268,13 +4410,16 @@ static __isl_give isl_basic_map *coalesce_divs(__isl_take isl_basic_map *bmap,
 {
 	isl_ctx *ctx;
 	isl_int m;
-	unsigned dim, total;
+	isl_size v_div;
+	unsigned total;
 	int i;
 
 	ctx = isl_basic_map_get_ctx(bmap);
 
-	dim = isl_space_dim(bmap->dim, isl_dim_all);
-	total = 1 + dim + bmap->n_div;
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0)
+		return isl_basic_map_free(bmap);
+	total = 1 + v_div + bmap->n_div;
 
 	isl_int_init(m);
 	isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0]);
@@ -4283,19 +4428,19 @@ static __isl_give isl_basic_map *coalesce_divs(__isl_take isl_basic_map *bmap,
 	for (i = 0; i < bmap->n_ineq; ++i) {
 		if (i == l || i == u)
 			continue;
-		if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2]))
+		if (isl_int_is_zero(bmap->ineq[i][1 + v_div + div2]))
 			continue;
-		if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])) {
-			if (isl_int_is_pos(bmap->ineq[i][1 + dim + div2]))
+		if (isl_int_is_zero(bmap->ineq[i][1 + v_div + div1])) {
+			if (isl_int_is_pos(bmap->ineq[i][1 + v_div + div2]))
 				isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i],
 						ctx->one, bmap->ineq[l], total);
 			else
 				isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i],
 						ctx->one, bmap->ineq[u], total);
 		}
-		isl_int_set(bmap->ineq[i][1 + dim + div2],
-			    bmap->ineq[i][1 + dim + div1]);
-		isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0);
+		isl_int_set(bmap->ineq[i][1 + v_div + div2],
+			    bmap->ineq[i][1 + v_div + div1]);
+		isl_int_set_si(bmap->ineq[i][1 + v_div + div1], 0);
 	}
 
 	isl_int_clear(m);
@@ -4323,23 +4468,29 @@ static __isl_give isl_basic_map *coalesce_or_drop_more_redundant_divs(
 	__isl_take isl_basic_map *bmap, int *pairs, int n)
 {
 	int i, l, u;
-	unsigned dim;
+	isl_size v_div;
+	isl_size n_div;
 
-	dim = isl_space_dim(bmap->dim, isl_dim_all);
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (v_div < 0 || n_div < 0)
+		return isl_basic_map_free(bmap);
 
-	for (i = 0; i < bmap->n_div; ++i) {
+	for (i = 0; i < n_div; ++i) {
 		if (!pairs[i])
 			continue;
 		for (l = 0; l < bmap->n_ineq; ++l) {
-			if (!isl_int_is_one(bmap->ineq[l][1 + dim + i]))
+			if (!isl_int_is_one(bmap->ineq[l][1 + v_div + i]))
 				continue;
 			for (u = 0; u < bmap->n_ineq; ++u) {
 				int c;
 
-				if (!isl_int_is_negone(bmap->ineq[u][1+dim+i]))
+				if (!isl_int_is_negone(bmap->ineq[u][1+v_div+i]))
 					continue;
 				c = div_find_coalesce(bmap, pairs, i, l, u);
 				if (c < 0)
+					goto error;
+				if (c >= n_div)
 					continue;
 				free(pairs);
 				bmap = coalesce_divs(bmap, i, c, l, u);
@@ -4354,6 +4505,10 @@ static __isl_give isl_basic_map *coalesce_or_drop_more_redundant_divs(
 	}
 
 	return drop_more_redundant_divs(bmap, pairs, n);
+error:
+	free(pairs);
+	isl_basic_map_free(bmap);
+	return NULL;
 }
 
 /* Are the "n" coefficients starting at "first" of inequality constraints
@@ -4365,35 +4520,17 @@ static int is_parallel_part(__isl_keep isl_basic_map *bmap, int i, int j,
 	return isl_seq_eq(bmap->ineq[i] + first, bmap->ineq[j] + first, n);
 }
 
-/* Are the "n" coefficients starting at "first" of inequality constraints
- * "i" and "j" of "bmap" opposite to each other?
- */
-static int is_opposite_part(__isl_keep isl_basic_map *bmap, int i, int j,
-	int first, int n)
-{
-	return isl_seq_is_neg(bmap->ineq[i] + first, bmap->ineq[j] + first, n);
-}
-
-/* Are inequality constraints "i" and "j" of "bmap" opposite to each other,
- * apart from the constant term?
- */
-static isl_bool is_opposite(__isl_keep isl_basic_map *bmap, int i, int j)
-{
-	unsigned total;
-
-	total = isl_basic_map_dim(bmap, isl_dim_all);
-	return is_opposite_part(bmap, i, j, 1, total);
-}
-
 /* Are inequality constraints "i" and "j" of "bmap" equal to each other,
  * apart from the constant term and the coefficient at position "pos"?
  */
-static int is_parallel_except(__isl_keep isl_basic_map *bmap, int i, int j,
+static isl_bool is_parallel_except(__isl_keep isl_basic_map *bmap, int i, int j,
 	int pos)
 {
-	unsigned total;
+	isl_size total;
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
 	return is_parallel_part(bmap, i, j, 1, pos - 1) &&
 		is_parallel_part(bmap, i, j, pos + 1, total - pos);
 }
@@ -4401,12 +4538,14 @@ static int is_parallel_except(__isl_keep isl_basic_map *bmap, int i, int j,
 /* Are inequality constraints "i" and "j" of "bmap" opposite to each other,
  * apart from the constant term and the coefficient at position "pos"?
  */
-static int is_opposite_except(__isl_keep isl_basic_map *bmap, int i, int j,
+static isl_bool is_opposite_except(__isl_keep isl_basic_map *bmap, int i, int j,
 	int pos)
 {
-	unsigned total;
+	isl_size total;
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
 	return is_opposite_part(bmap, i, j, 1, pos - 1) &&
 		is_opposite_part(bmap, i, j, pos + 1, total - pos);
 }
@@ -4433,13 +4572,16 @@ static isl_bool single_unknown(__isl_keep isl_basic_map *bmap, int ineq,
 	int div)
 {
 	int i;
-	unsigned n_div, o_div;
+	isl_size n_div;
+	unsigned o_div;
 	isl_bool known;
 
 	known = isl_basic_map_div_is_known(bmap, div);
 	if (known < 0 || known)
 		return isl_bool_not(known);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_bool_error;
 	if (n_div == 1)
 		return isl_bool_true;
 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
@@ -4578,7 +4720,8 @@ static void lower_bound_from_opposite(__isl_keep isl_basic_map *bmap,
  *	ceil((-c1 - c)/n) = ceil((c0 - c)/n)
  *
  * If so, return the index of inequality f(x) + c0 >= 0.
- * Otherwise, return -1.
+ * Otherwise, return bmap->n_ineq.
+ * Return -1 on error.
  */
 static int lower_bound_is_cst(__isl_keep isl_basic_map *bmap, int div, int ineq)
 {
@@ -4590,23 +4733,32 @@ static int lower_bound_is_cst(__isl_keep isl_basic_map *bmap, int div, int ineq)
 
 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
 	for (i = 0; i < bmap->n_ineq && (lower < 0 || upper < 0); ++i) {
+		isl_bool par, opp;
+
 		if (i == ineq)
 			continue;
 		if (!isl_int_is_zero(bmap->ineq[i][o_div + div]))
 			continue;
-		if (lower < 0 &&
-		    is_parallel_except(bmap, ineq, i, o_div + div)) {
+		par = isl_bool_false;
+		if (lower < 0)
+			par = is_parallel_except(bmap, ineq, i, o_div + div);
+		if (par < 0)
+			return -1;
+		if (par) {
 			lower = i;
 			continue;
 		}
-		if (upper < 0 &&
-		    is_opposite_except(bmap, ineq, i, o_div + div)) {
+		opp = isl_bool_false;
+		if (upper < 0)
+			opp = is_opposite_except(bmap, ineq, i, o_div + div);
+		if (opp < 0)
+			return -1;
+		if (opp)
 			upper = i;
-		}
 	}
 
 	if (lower < 0 || upper < 0)
-		return -1;
+		return bmap->n_ineq;
 
 	isl_int_init(l);
 	isl_int_init(u);
@@ -4619,7 +4771,7 @@ static int lower_bound_is_cst(__isl_keep isl_basic_map *bmap, int div, int ineq)
 	isl_int_clear(l);
 	isl_int_clear(u);
 
-	return equal ? lower : -1;
+	return equal ? lower : bmap->n_ineq;
 }
 
 /* Given a lower bound constraint "ineq" on the existentially quantified
@@ -4705,20 +4857,24 @@ static __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs_ineq(
 	__isl_take isl_basic_map *bmap)
 {
 	int i, j;
-	unsigned off;
+	isl_size off;
 	int *pairs = NULL;
 	int n = 0;
+	int n_ineq;
 
 	if (!bmap)
 		goto error;
 	if (bmap->n_div == 0)
 		return bmap;
 
-	off = isl_space_dim(bmap->dim, isl_dim_all);
+	off = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (off < 0)
+		return isl_basic_map_free(bmap);
 	pairs = isl_calloc_array(bmap->ctx, int, bmap->n_div);
 	if (!pairs)
 		goto error;
 
+	n_ineq = isl_basic_map_n_inequality(bmap);
 	for (i = 0; i < bmap->n_div; ++i) {
 		int pos, neg;
 		int last_pos, last_neg;
@@ -4781,7 +4937,9 @@ static __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs_ineq(
 				return set_eq_and_try_again(bmap, last_pos,
 							    pairs);
 			lower = lower_bound_is_cst(bmap, i, last_pos);
-			if (lower >= 0)
+			if (lower < 0)
+				goto error;
+			if (lower < n_ineq)
 				return fix_cst_lower(bmap, i, last_pos, lower,
 						pairs);
 			continue;
@@ -4830,13 +4988,13 @@ static __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs_ineq(
  */
 static isl_stat preimage(isl_int *c, __isl_keep isl_mat *T)
 {
-	int n;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_vec *v;
 
-	if (!T)
-		return isl_stat_error;
 	n = isl_mat_rows(T);
+	if (n < 0)
+		return isl_stat_error;
 	if (isl_seq_first_non_zero(c, n) == -1)
 		return isl_stat_ok;
 	ctx = isl_mat_get_ctx(T);
@@ -4860,21 +5018,20 @@ static __isl_give isl_basic_map *isl_basic_map_preimage_vars(
 	__isl_take isl_basic_map *bmap, unsigned pos, __isl_take isl_mat *T)
 {
 	int i;
-	unsigned n, total;
+	isl_size n_row, n_col;
 
 	bmap = isl_basic_map_cow(bmap);
-	if (!bmap || !T)
+	n_row = isl_mat_rows(T);
+	n_col = isl_mat_cols(T);
+	if (!bmap || n_row < 0 || n_col < 0)
 		goto error;
 
-	n = isl_mat_cols(T);
-	if (n != isl_mat_rows(T))
+	if (n_col != n_row)
 		isl_die(isl_mat_get_ctx(T), isl_error_invalid,
 			"expecting square matrix", goto error);
 
-	total = isl_basic_map_dim(bmap, isl_dim_all);
-	if (pos + n > total || pos + n < pos)
-		isl_die(isl_mat_get_ctx(T), isl_error_invalid,
-			"invalid range", goto error);
+	if (isl_basic_map_check_range(bmap, isl_dim_all, pos, n_col) < 0)
+		goto error;
 
 	for (i = 0; i < bmap->n_eq; ++i)
 		if (preimage(bmap->eq[i] + 1 + pos, T) < 0)
@@ -4943,7 +5100,8 @@ __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs(
 {
 	int first;
 	int i;
-	unsigned o_div, n_div;
+	unsigned o_div;
+	isl_size n_div;
 	int l;
 	isl_ctx *ctx;
 	isl_mat *T;
@@ -4964,6 +5122,8 @@ __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs(
 
 	o_div = isl_basic_map_offset(bmap, isl_dim_div);
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_basic_map_free(bmap);
 
 	for (i = 0; i < bmap->n_eq; ++i) {
 		l = isl_seq_first_non_zero(bmap->eq[i] + o_div + first,
@@ -4999,12 +5159,14 @@ __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs(
 /* Does "bmap" satisfy any equality that involves more than 2 variables
  * and/or has coefficients 
diff erent from -1 and 1?
  */
-static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap)
+static isl_bool has_multiple_var_equality(__isl_keep isl_basic_map *bmap)
 {
 	int i;
-	unsigned total;
+	isl_size total;
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
 
 	for (i = 0; i < bmap->n_eq; ++i) {
 		int j, k;
@@ -5014,7 +5176,7 @@ static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap)
 			continue;
 		if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
 		    !isl_int_is_negone(bmap->eq[i][1 + j]))
-			return 1;
+			return isl_bool_true;
 
 		j += 1;
 		k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
@@ -5023,15 +5185,15 @@ static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap)
 		j += k;
 		if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
 		    !isl_int_is_negone(bmap->eq[i][1 + j]))
-			return 1;
+			return isl_bool_true;
 
 		j += 1;
 		k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
 		if (k >= 0)
-			return 1;
+			return isl_bool_true;
 	}
 
-	return 0;
+	return isl_bool_false;
 }
 
 /* Remove any common factor g from the constraint coefficients in "v".
@@ -5081,6 +5243,11 @@ static __isl_give isl_vec *normalize_constraint(__isl_take isl_vec *v,
  * which checks for such pairs of inequalities as well as eliminate_divs_eq
  * and isl_basic_map_gauss if such a pair was found.
  *
+ * Tightening may also result in some other constraints becoming
+ * (rationally) redundant with respect to the tightened constraint
+ * (in combination with other constraints).  The basic map may
+ * therefore no longer be assumed to have no redundant constraints.
+ *
  * Note that this function may leave the result in an inconsistent state.
  * In particular, the constraints may not be gaussed.
  * Unfortunately, isl_map_coalesce actually depends on this inconsistent state
@@ -5091,7 +5258,8 @@ static __isl_give isl_vec *normalize_constraint(__isl_take isl_vec *v,
 __isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
 	__isl_take isl_basic_map *bmap)
 {
-	unsigned total;
+	isl_size total;
+	isl_bool multi;
 	isl_ctx *ctx;
 	isl_vec *v;
 	isl_mat *eq, *T, *T2;
@@ -5106,10 +5274,15 @@ __isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
 		return bmap;
 	if (bmap->n_eq == 0)
 		return bmap;
-	if (!has_multiple_var_equality(bmap))
+	multi = has_multiple_var_equality(bmap);
+	if (multi < 0)
+		return isl_basic_map_free(bmap);
+	if (!multi)
 		return bmap;
 
 	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_basic_map_free(bmap);
 	ctx = isl_basic_map_get_ctx(bmap);
 	v = isl_vec_alloc(ctx, 1 + total);
 	if (!v)
@@ -5150,6 +5323,7 @@ __isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
 	if (tightened) {
 		int progress = 0;
 
+		ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
 		bmap = isl_basic_map_detect_inequality_pairs(bmap, &progress);
 		if (progress) {
 			bmap = eliminate_divs_eq(bmap, &progress);
@@ -5182,15 +5356,15 @@ __isl_give isl_basic_map *isl_basic_map_shift_div(
 	__isl_take isl_basic_map *bmap, int div, int pos, isl_int shift)
 {
 	int i;
-	unsigned total;
+	isl_size total, n_div;
 
 	if (isl_int_is_zero(shift))
 		return bmap;
-	if (!bmap)
-		return NULL;
-
 	total = isl_basic_map_dim(bmap, isl_dim_all);
-	total -= isl_basic_map_dim(bmap, isl_dim_div);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	total -= n_div;
+	if (total < 0 || n_div < 0)
+		return isl_basic_map_free(bmap);
 
 	isl_int_addmul(bmap->div[div][1 + pos], shift, bmap->div[div][0]);
 

diff  --git a/polly/lib/External/isl/isl_map_subtract.c b/polly/lib/External/isl/isl_map_subtract.c
index 1ef50ae5e70c..1e78d1d524d4 100644
--- a/polly/lib/External/isl/isl_map_subtract.c
+++ b/polly/lib/External/isl/isl_map_subtract.c
@@ -51,16 +51,20 @@ static isl_stat tab_add_constraints(struct isl_tab *tab,
 {
 	int i;
 	unsigned dim;
-	unsigned tab_total;
-	unsigned bmap_total;
+	isl_size tab_total;
+	isl_size bmap_n_div;
+	isl_size bmap_total;
 	isl_vec *v;
 
 	if (!tab || !bmap)
 		return isl_stat_error;
 
-	tab_total = isl_basic_map_total_dim(tab->bmap);
-	bmap_total = isl_basic_map_total_dim(bmap);
-	dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
+	tab_total = isl_basic_map_dim(tab->bmap, isl_dim_all);
+	bmap_total = isl_basic_map_dim(bmap, isl_dim_all);
+	bmap_n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	dim = bmap_total - bmap_n_div;
+	if (tab_total < 0 || bmap_total < 0 || bmap_n_div < 0)
+		return isl_stat_error;
 
 	if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
 		return isl_stat_error;
@@ -70,11 +74,11 @@ static isl_stat tab_add_constraints(struct isl_tab *tab,
 		return isl_stat_error;
 
 	for (i = 0; i < bmap->n_eq; ++i) {
-		expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
+		expand_constraint(v, dim, bmap->eq[i], div_map, bmap_n_div);
 		if (isl_tab_add_ineq(tab, v->el) < 0)
 			goto error;
 		isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
-		expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
+		expand_constraint(v, dim, bmap->eq[i], div_map, bmap_n_div);
 		if (isl_tab_add_ineq(tab, v->el) < 0)
 			goto error;
 		isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
@@ -83,7 +87,7 @@ static isl_stat tab_add_constraints(struct isl_tab *tab,
 	}
 
 	for (i = 0; i < bmap->n_ineq; ++i) {
-		expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div);
+		expand_constraint(v, dim, bmap->ineq[i], div_map, bmap_n_div);
 		if (isl_tab_add_ineq(tab, v->el) < 0)
 			goto error;
 		if (tab->empty)
@@ -110,17 +114,21 @@ static isl_stat tab_add_constraint(struct isl_tab *tab,
 	__isl_keep isl_basic_map *bmap, int *div_map, int c, int oppose)
 {
 	unsigned dim;
-	unsigned tab_total;
-	unsigned bmap_total;
+	isl_size tab_total;
+	isl_size bmap_n_div;
+	isl_size bmap_total;
 	isl_vec *v;
 	isl_stat r;
 
 	if (!tab || !bmap)
 		return isl_stat_error;
 
-	tab_total = isl_basic_map_total_dim(tab->bmap);
-	bmap_total = isl_basic_map_total_dim(bmap);
-	dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
+	tab_total = isl_basic_map_dim(tab->bmap, isl_dim_all);
+	bmap_total = isl_basic_map_dim(bmap, isl_dim_all);
+	bmap_n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	dim = bmap_total - bmap_n_div;
+	if (tab_total < 0 || bmap_total < 0 || bmap_n_div < 0)
+		return isl_stat_error;
 
 	v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
 	if (!v)
@@ -132,7 +140,7 @@ static isl_stat tab_add_constraint(struct isl_tab *tab,
 					1 + bmap_total);
 		if (oppose)
 			isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
-		expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div);
+		expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap_n_div);
 		r = isl_tab_add_ineq(tab, v->el);
 		if (oppose)
 			isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
@@ -146,7 +154,7 @@ static isl_stat tab_add_constraint(struct isl_tab *tab,
 					1 + bmap_total);
 			isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
 		}
-		expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div);
+		expand_constraint(v, dim, bmap->ineq[c], div_map, bmap_n_div);
 		r = isl_tab_add_ineq(tab, v->el);
 		if (oppose) {
 			isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
@@ -164,7 +172,7 @@ static isl_stat tab_add_divs(struct isl_tab *tab,
 {
 	int i, j;
 	struct isl_vec *vec;
-	unsigned total;
+	isl_size total;
 	unsigned dim;
 
 	if (!bmap)
@@ -177,7 +185,9 @@ static isl_stat tab_add_divs(struct isl_tab *tab,
 	if (!*div_map)
 		return isl_stat_error;
 
-	total = isl_basic_map_total_dim(tab->bmap);
+	total = isl_basic_map_dim(tab->bmap, isl_dim_all);
+	if (total < 0)
+		return isl_stat_error;
 	dim = total - tab->bmap->n_div;
 	vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
 	if (!vec)
@@ -520,17 +530,17 @@ static __isl_give isl_map *replace_pair_by_empty( __isl_take isl_map *map1,
  *
  * If "map1" and "map2" are disjoint, then simply return "map1".
  */
-static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
+__isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
 	__isl_take isl_map *map2)
 {
 	int i;
 	int equal, disjoint;
 	struct isl_map *
diff ;
 
-	if (!map1 || !map2)
+	if (isl_map_align_params_bin(&map1, &map2) < 0)
+		goto error;
+	if (isl_map_check_equal_space(map1, map2) < 0)
 		goto error;
-
-	isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
 
 	equal = isl_map_plain_is_equal(map1, map2);
 	if (equal < 0)
@@ -575,12 +585,6 @@ static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
-	__isl_take isl_map *map2)
-{
-	return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
-}
-
 struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
 {
 	return set_from_map(isl_map_subtract(set_to_map(set1),
@@ -589,12 +593,13 @@ struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
 
 /* Remove the elements of "dom" from the domain of "map".
  */
-static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
+__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
 	__isl_take isl_set *dom)
 {
 	isl_bool ok;
 	isl_map *ext_dom;
 
+	isl_map_align_params_set(&map, &dom);
 	ok = isl_map_compatible_domain(map, dom);
 	if (ok < 0)
 		goto error;
@@ -611,20 +616,15 @@ static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
-	__isl_take isl_set *dom)
-{
-	return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
-}
-
 /* Remove the elements of "dom" from the range of "map".
  */
-static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
+__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
 	__isl_take isl_set *dom)
 {
 	isl_bool ok;
 	isl_map *ext_dom;
 
+	isl_map_align_params_set(&map, &dom);
 	ok = isl_map_compatible_range(map, dom);
 	if (ok < 0)
 		goto error;
@@ -641,12 +641,6 @@ static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
 	return NULL;
 }
 
-__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
-	__isl_take isl_set *dom)
-{
-	return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
-}
-
 /* A 
diff  collector that aborts as soon as its add function is called,
  * setting empty to 0.
  */
@@ -663,7 +657,7 @@ static isl_stat basic_map_is_empty_add(struct isl_
diff _collector *dc,
 	struct isl_is_empty_
diff _collector *edc;
 	edc = (struct isl_is_empty_
diff _collector *)dc;
 
-	edc->empty = 0;
+	edc->empty = isl_bool_false;
 
 	isl_basic_map_free(bmap);
 	return isl_stat_error;
@@ -718,13 +712,18 @@ static isl_bool map_
diff _is_empty(__isl_keep isl_map *map1,
  */
 isl_bool isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
 {
+	isl_size total;
+
 	if (!bmap)
 		return isl_bool_error;
 	if (bmap->n_div)
 		return isl_bool_false;
 	if (bmap->n_ineq)
 		return isl_bool_false;
-	return bmap->n_eq == isl_basic_map_total_dim(bmap);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
+	return bmap->n_eq == total;
 }
 
 /* Return true if "map" contains a single element.
@@ -746,14 +745,14 @@ static __isl_give isl_point *singleton_extract_point(
 	__isl_keep isl_basic_map *bmap)
 {
 	int j;
-	unsigned dim;
+	isl_size dim;
 	struct isl_vec *point;
 	isl_int m;
 
-	if (!bmap)
+	dim = isl_basic_map_dim(bmap, isl_dim_all);
+	if (dim < 0)
 		return NULL;
 
-	dim = isl_basic_map_total_dim(bmap);
 	isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
 	point = isl_vec_alloc(bmap->ctx, 1 + dim);
 	if (!point)

diff  --git a/polly/lib/External/isl/isl_mat.c b/polly/lib/External/isl/isl_mat.c
index ab117f0cb85c..38f3038f4047 100644
--- a/polly/lib/External/isl/isl_mat.c
+++ b/polly/lib/External/isl/isl_mat.c
@@ -252,14 +252,14 @@ __isl_null isl_mat *isl_mat_free(__isl_take isl_mat *mat)
 	return NULL;
 }
 
-int isl_mat_rows(__isl_keep isl_mat *mat)
+isl_size isl_mat_rows(__isl_keep isl_mat *mat)
 {
-	return mat ? mat->n_row : -1;
+	return mat ? mat->n_row : isl_size_error;
 }
 
-int isl_mat_cols(__isl_keep isl_mat *mat)
+isl_size isl_mat_cols(__isl_keep isl_mat *mat)
 {
-	return mat ? mat->n_col : -1;
+	return mat ? mat->n_col : isl_size_error;
 }
 
 /* Check that "col" is a valid column position for "mat".
@@ -423,26 +423,26 @@ __isl_give isl_mat *isl_mat_identity(isl_ctx *ctx, unsigned n_row)
 
 /* Is "mat" a (possibly scaled) identity matrix?
  */
-int isl_mat_is_scaled_identity(__isl_keep isl_mat *mat)
+isl_bool isl_mat_is_scaled_identity(__isl_keep isl_mat *mat)
 {
 	int i;
 
 	if (!mat)
-		return -1;
+		return isl_bool_error;
 	if (mat->n_row != mat->n_col)
-		return 0;
+		return isl_bool_false;
 
 	for (i = 0; i < mat->n_row; ++i) {
 		if (isl_seq_first_non_zero(mat->row[i], i) != -1)
-			return 0;
+			return isl_bool_false;
 		if (isl_int_ne(mat->row[0][0], mat->row[i][i]))
-			return 0;
+			return isl_bool_false;
 		if (isl_seq_first_non_zero(mat->row[i] + i + 1,
 					    mat->n_col - (i + 1)) != -1)
-			return 0;
+			return isl_bool_false;
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 __isl_give isl_vec *isl_mat_vec_product(__isl_take isl_mat *mat,
@@ -718,15 +718,16 @@ __isl_give isl_mat *isl_mat_left_hermite(__isl_take isl_mat *M, int neg,
  */
 static __isl_give isl_mat *eliminate(__isl_take isl_mat *mat, int row, int col)
 {
-	int k, nr, nc;
+	int k;
+	isl_size nr, nc;
 	isl_ctx *ctx;
 
-	if (!mat)
-		return NULL;
-
-	ctx = isl_mat_get_ctx(mat);
 	nr = isl_mat_rows(mat);
 	nc = isl_mat_cols(mat);
+	if (nr < 0 || nc < 0)
+		return isl_mat_free(mat);
+
+	ctx = isl_mat_get_ctx(mat);
 
 	for (k = 0; k < nr; ++k) {
 		if (k == row)
@@ -754,13 +755,13 @@ static __isl_give isl_mat *eliminate(__isl_take isl_mat *mat, int row, int col)
  */
 __isl_give isl_mat *isl_mat_reverse_gauss(__isl_take isl_mat *mat)
 {
-	int k, row, last, nr, nc;
-
-	if (!mat)
-		return NULL;
+	int k, row, last;
+	isl_size nr, nc;
 
 	nr = isl_mat_rows(mat);
 	nc = isl_mat_cols(mat);
+	if (nr < 0 || nc < 0)
+		return isl_mat_free(mat);
 
 	last = nc - 1;
 	for (row = nr - 1; row >= 0; --row) {
@@ -793,13 +794,13 @@ __isl_give isl_mat *isl_mat_reverse_gauss(__isl_take isl_mat *mat)
  */
 __isl_give isl_mat *isl_mat_lexnonneg_rows(__isl_take isl_mat *mat)
 {
-	int i, nr, nc;
-
-	if (!mat)
-		return NULL;
+	int i;
+	isl_size nr, nc;
 
 	nr = isl_mat_rows(mat);
 	nc = isl_mat_cols(mat);
+	if (nr < 0 || nc < 0)
+		return isl_mat_free(mat);
 
 	for (i = 0; i < nr; ++i) {
 		int pos;
@@ -842,16 +843,16 @@ static int hermite_first_zero_col(__isl_keep isl_mat *H, int first_col,
 	return H->n_col;
 }
 
-/* Return the rank of "mat", or -1 in case of error.
+/* Return the rank of "mat", or isl_size_error in case of error.
  */
-int isl_mat_rank(__isl_keep isl_mat *mat)
+isl_size isl_mat_rank(__isl_keep isl_mat *mat)
 {
 	int rank;
 	isl_mat *H;
 
 	H = isl_mat_left_hermite(isl_mat_copy(mat), 0, NULL, NULL);
 	if (!H)
-		return -1;
+		return isl_size_error;
 
 	rank = hermite_first_zero_col(H, 0, H->n_row);
 	isl_mat_free(H);
@@ -1360,15 +1361,15 @@ __isl_give isl_basic_set *isl_basic_set_preimage(
 
 	ctx = bset->ctx;
 	bset = isl_basic_set_cow(bset);
-	if (!bset)
+	if (isl_basic_set_check_no_params(bset) < 0)
 		goto error;
 
-	isl_assert(ctx, bset->dim->nparam == 0, goto error);
 	isl_assert(ctx, 1+bset->dim->n_out == mat->n_row, goto error);
 	isl_assert(ctx, mat->n_col > 0, goto error);
 
 	if (mat->n_col > mat->n_row) {
-		bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0, 0, 0);
+		bset = isl_basic_set_add_dims(bset, isl_dim_set,
+						mat->n_col - mat->n_row);
 		if (!bset)
 			goto error;
 	} else if (mat->n_col < mat->n_row) {
@@ -1391,7 +1392,7 @@ __isl_give isl_basic_set *isl_basic_set_preimage(
 
 	ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
 	ISL_F_CLR(bset, ISL_BASIC_SET_NO_REDUNDANT);
-	ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
+	ISL_F_CLR(bset, ISL_BASIC_SET_SORTED);
 	ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED_DIVS);
 	ISL_F_CLR(bset, ISL_BASIC_SET_ALL_EQUALITIES);
 
@@ -2043,19 +2044,22 @@ __isl_give isl_mat *isl_mat_row_basis(__isl_take isl_mat *mat)
 __isl_give isl_mat *isl_mat_row_basis_extension(
 	__isl_take isl_mat *mat1, __isl_take isl_mat *mat2)
 {
-	int n_row;
-	int r1, r, n1;
+	isl_size n_row;
+	int r1, r;
+	isl_size n1;
 	isl_mat *H, *Q;
 
 	n1 = isl_mat_rows(mat1);
 	H = isl_mat_concat(mat1, mat2);
 	H = isl_mat_left_hermite(H, 0, NULL, &Q);
-	if (!H || !Q)
+	if (n1 < 0 || !H || !Q)
 		goto error;
 
 	r1 = hermite_first_zero_col(H, 0, n1);
 	r = hermite_first_zero_col(H, r1, H->n_row);
 	n_row = isl_mat_rows(Q);
+	if (n_row < 0)
+		goto error;
 	Q = isl_mat_drop_rows(Q, r, n_row - r);
 	Q = isl_mat_drop_rows(Q, 0, r1);
 
@@ -2076,7 +2080,7 @@ __isl_give isl_mat *isl_mat_row_basis_extension(
 isl_bool isl_mat_has_linearly_independent_rows(__isl_keep isl_mat *mat1,
 	__isl_keep isl_mat *mat2)
 {
-	int r1, r2, r;
+	isl_size r1, r2, r;
 	isl_mat *mat;
 
 	r1 = isl_mat_rank(mat1);
@@ -2095,5 +2099,5 @@ isl_bool isl_mat_has_linearly_independent_rows(__isl_keep isl_mat *mat1,
 	isl_mat_free(mat);
 	if (r < 0)
 		return isl_bool_error;
-	return r == r1 + r2;
+	return isl_bool_ok(r == r1 + r2);
 }

diff  --git a/polly/lib/External/isl/isl_mat_private.h b/polly/lib/External/isl/isl_mat_private.h
index 1a3f69ea4785..774ea16b1190 100644
--- a/polly/lib/External/isl/isl_mat_private.h
+++ b/polly/lib/External/isl/isl_mat_private.h
@@ -1,3 +1,6 @@
+#ifndef ISL_MAT_PRIVATE_H
+#define ISL_MAT_PRIVATE_H
+
 #include <isl/mat.h>
 #include <isl_blk.h>
 
@@ -47,7 +50,7 @@ __isl_give isl_vec *isl_mat_get_row(__isl_keep isl_mat *mat, unsigned row);
 
 __isl_give isl_mat *isl_mat_lexnonneg_rows(__isl_take isl_mat *mat);
 
-int isl_mat_is_scaled_identity(__isl_keep isl_mat *mat);
+isl_bool isl_mat_is_scaled_identity(__isl_keep isl_mat *mat);
 
 isl_stat isl_mat_row_gcd(__isl_keep isl_mat *mat, int row, isl_int *gcd);
 
@@ -62,3 +65,5 @@ __isl_give isl_mat *isl_mat_row_neg(__isl_take isl_mat *mat, int row);
 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);
+
+#endif

diff  --git a/polly/lib/External/isl/isl_maybe_ast_graft_list.h b/polly/lib/External/isl/isl_maybe_ast_graft_list.h
new file mode 100644
index 000000000000..14466918aac7
--- /dev/null
+++ b/polly/lib/External/isl/isl_maybe_ast_graft_list.h
@@ -0,0 +1,10 @@
+#ifndef ISL_MAYBE_AST_GRAFT_LIST_H
+#define ISL_MAYBE_AST_GRAFT_LIST_H
+
+#include "isl_ast_graft_private.h"
+
+#define ISL_TYPE	isl_ast_graft_list
+#include <isl/maybe_templ.h>
+#undef ISL_TYPE
+
+#endif

diff  --git a/polly/lib/External/isl/isl_morph.c b/polly/lib/External/isl/isl_morph.c
index 563f579a2a94..dd37516a6e0c 100644
--- a/polly/lib/External/isl/isl_morph.c
+++ b/polly/lib/External/isl/isl_morph.c
@@ -103,17 +103,20 @@ __isl_null isl_morph *isl_morph_free(__isl_take isl_morph *morph)
 
 /* Is "morph" an identity on the parameters?
  */
-static int identity_on_parameters(__isl_keep isl_morph *morph)
+static isl_bool identity_on_parameters(__isl_keep isl_morph *morph)
 {
-	int is_identity;
-	unsigned nparam;
+	isl_bool is_identity;
+	isl_size nparam, nparam_ran;
 	isl_mat *sub;
 
 	nparam = isl_morph_dom_dim(morph, isl_dim_param);
-	if (nparam != isl_morph_ran_dim(morph, isl_dim_param))
-		return 0;
+	nparam_ran = isl_morph_ran_dim(morph, isl_dim_param);
+	if (nparam < 0 || nparam_ran < 0)
+		return isl_bool_error;
+	if (nparam != nparam_ran)
+		return isl_bool_false;
 	if (nparam == 0)
-		return 1;
+		return isl_bool_true;
 	sub = isl_mat_sub_alloc(morph->map, 0, 1 + nparam, 0, 1 + nparam);
 	is_identity = isl_mat_is_scaled_identity(sub);
 	isl_mat_free(sub);
@@ -133,9 +136,9 @@ __isl_give isl_multi_aff *isl_morph_get_var_multi_aff(
 	isl_space *dom, *ran, *space;
 	isl_local_space *ls;
 	isl_multi_aff *ma;
-	unsigned nparam, nvar;
+	isl_size nparam, nvar;
 	int i;
-	int is_identity;
+	isl_bool is_identity;
 
 	if (!morph)
 		return NULL;
@@ -155,6 +158,8 @@ __isl_give isl_multi_aff *isl_morph_get_var_multi_aff(
 
 	nparam = isl_multi_aff_dim(ma, isl_dim_param);
 	nvar = isl_multi_aff_dim(ma, isl_dim_out);
+	if (nparam < 0 || nvar < 0)
+		ma = isl_multi_aff_free(ma);
 	for (i = 0; i < nvar; ++i) {
 		isl_val *val;
 		isl_vec *v;
@@ -190,18 +195,18 @@ __isl_give isl_space *isl_morph_get_ran_space(__isl_keep isl_morph *morph)
 	return isl_space_copy(morph->ran->dim);
 }
 
-unsigned isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
+isl_size isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
 {
 	if (!morph)
-		return 0;
+		return isl_size_error;
 
 	return isl_basic_set_dim(morph->dom, type);
 }
 
-unsigned isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
+isl_size isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
 {
 	if (!morph)
-		return 0;
+		return isl_size_error;
 
 	return isl_basic_set_dim(morph->ran, type);
 }
@@ -264,12 +269,14 @@ __isl_give isl_morph *isl_morph_remove_ran_dims(__isl_take isl_morph *morph,
  */
 __isl_give isl_morph *isl_morph_dom_params(__isl_take isl_morph *morph)
 {
-	unsigned n;
+	isl_size n;
 
 	morph = isl_morph_cow(morph);
 	if (!morph)
 		return NULL;
 	n = isl_basic_set_dim(morph->dom, isl_dim_set);
+	if (n < 0)
+		return isl_morph_free(morph);
 	morph = isl_morph_remove_dom_dims(morph, isl_dim_set, 0, n);
 	if (!morph)
 		return NULL;
@@ -285,12 +292,14 @@ __isl_give isl_morph *isl_morph_dom_params(__isl_take isl_morph *morph)
  */
 __isl_give isl_morph *isl_morph_ran_params(__isl_take isl_morph *morph)
 {
-	unsigned n;
+	isl_size n;
 
 	morph = isl_morph_cow(morph);
 	if (!morph)
 		return NULL;
 	n = isl_basic_set_dim(morph->ran, isl_dim_set);
+	if (n < 0)
+		return isl_morph_free(morph);
 	morph = isl_morph_remove_ran_dims(morph, isl_dim_set, 0, n);
 	if (!morph)
 		return NULL;
@@ -302,6 +311,20 @@ __isl_give isl_morph *isl_morph_ran_params(__isl_take isl_morph *morph)
 	return NULL;
 }
 
+/* Replace the identifier of the tuple of the range of the morph by "id".
+ */
+static __isl_give isl_morph *isl_morph_set_ran_tuple_id(
+	__isl_take isl_morph *morph, __isl_keep isl_id *id)
+{
+	morph = isl_morph_cow(morph);
+	if (!morph)
+		return NULL;
+	morph->ran = isl_basic_set_set_tuple_id(morph->ran, isl_id_copy(id));
+	if (!morph->ran)
+		return isl_morph_free(morph);
+	return morph;
+}
+
 void isl_morph_print_internal(__isl_take isl_morph *morph, FILE *out)
 {
 	if (!morph)
@@ -322,12 +345,12 @@ __isl_give isl_morph *isl_morph_identity(__isl_keep isl_basic_set *bset)
 {
 	isl_mat *id;
 	isl_basic_set *universe;
-	unsigned total;
+	isl_size total;
 
-	if (!bset)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		return NULL;
 
-	total = isl_basic_set_total_dim(bset);
 	id = isl_mat_identity(bset->ctx, 1 + total);
 	universe = isl_basic_set_universe(isl_space_copy(bset->dim));
 
@@ -342,12 +365,12 @@ __isl_give isl_morph *isl_morph_empty(__isl_keep isl_basic_set *bset)
 {
 	isl_mat *id;
 	isl_basic_set *empty;
-	unsigned total;
+	isl_size total;
 
-	if (!bset)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		return NULL;
 
-	total = isl_basic_set_total_dim(bset);
 	id = isl_mat_identity(bset->ctx, 1 + total);
 	empty = isl_basic_set_empty(isl_space_copy(bset->dim));
 
@@ -363,12 +386,13 @@ static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset,
 {
 	int i, k;
 	isl_basic_set *eq;
-	unsigned total;
+	isl_size total;
 
-	isl_assert(bset->ctx, bset->n_div == 0, return NULL);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0 || isl_basic_set_check_no_locals(bset) < 0)
+		return NULL;
 
-	total = isl_basic_set_total_dim(bset);
-	eq = isl_basic_set_alloc_space(isl_space_copy(bset->dim), 0, n, 0);
+	eq = isl_basic_set_alloc_space(isl_basic_set_get_space(bset), 0, n, 0);
 	if (!eq)
 		return NULL;
 	for (i = 0; i < n; ++i) {
@@ -385,8 +409,7 @@ static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset,
 }
 
 /* Given a basic set, exploit the equalities in the basic set to construct
- * a morphism that maps the basic set to a lower-dimensional space
- * with identifier "id".
+ * a morphism that maps the basic set to a lower-dimensional space.
  * Specifically, the morphism reduces the number of dimensions of type "type".
  *
  * We first select the equalities of interest, that is those that involve
@@ -410,14 +433,14 @@ static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset,
  * Both matrices are extended to map the full original space to the full
  * compressed space.
  */
-__isl_give isl_morph *isl_basic_set_variable_compression_with_id(
-	__isl_keep isl_basic_set *bset, enum isl_dim_type type,
-	__isl_keep isl_id *id)
+__isl_give isl_morph *isl_basic_set_variable_compression(
+	__isl_keep isl_basic_set *bset, enum isl_dim_type type)
 {
 	unsigned otype;
-	unsigned ntype;
+	isl_size ntype;
 	unsigned orest;
 	unsigned nrest;
+	isl_size total;
 	int f_eq, n_eq;
 	isl_space *space;
 	isl_mat *E, *Q, *C;
@@ -429,12 +452,16 @@ __isl_give isl_morph *isl_basic_set_variable_compression_with_id(
 	if (isl_basic_set_plain_is_empty(bset))
 		return isl_morph_empty(bset);
 
-	isl_assert(bset->ctx, bset->n_div == 0, return NULL);
+	if (isl_basic_set_check_no_locals(bset) < 0)
+		return NULL;
 
-	otype = 1 + isl_space_offset(bset->dim, type);
 	ntype = isl_basic_set_dim(bset, type);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (ntype < 0 || total < 0)
+		return NULL;
+	otype = isl_basic_set_offset(bset, type);
 	orest = otype + ntype;
-	nrest = isl_basic_set_total_dim(bset) - (orest - 1);
+	nrest = total - (orest - 1);
 
 	for (f_eq = 0; f_eq < bset->n_eq; ++f_eq)
 		if (isl_seq_first_non_zero(bset->eq[f_eq] + orest, nrest) == -1)
@@ -461,7 +488,6 @@ __isl_give isl_morph *isl_basic_set_variable_compression_with_id(
 	space = isl_space_copy(bset->dim);
 	space = isl_space_drop_dims(space, type, 0, ntype);
 	space = isl_space_add_dims(space, type, ntype - n_eq);
-	space = isl_space_set_tuple_id(space, isl_dim_set, isl_id_copy(id));
 	ran = isl_basic_set_universe(space);
 	dom = copy_equalities(bset, f_eq, n_eq);
 
@@ -469,14 +495,18 @@ __isl_give isl_morph *isl_basic_set_variable_compression_with_id(
 }
 
 /* Given a basic set, exploit the equalities in the basic set to construct
- * a morphism that maps the basic set to a lower-dimensional space.
- * Specifically, the morphism reduces the number of dimensions of type "type".
+ * a morphism that maps the basic set to a lower-dimensional space
+ * with identifier "id".
+ * Specifically, the morphism reduces the number of set dimensions.
  */
-__isl_give isl_morph *isl_basic_set_variable_compression(
-	__isl_keep isl_basic_set *bset, enum isl_dim_type type)
+__isl_give isl_morph *isl_basic_set_variable_compression_with_id(
+	__isl_keep isl_basic_set *bset, __isl_keep isl_id *id)
 {
-	return isl_basic_set_variable_compression_with_id(bset, type,
-							&isl_id_none);
+	isl_morph *morph;
+
+	morph = isl_basic_set_variable_compression(bset, isl_dim_set);
+	morph = isl_morph_set_ran_tuple_id(morph, id);
+	return morph;
 }
 
 /* Construct a parameter compression for "bset".
@@ -498,9 +528,9 @@ __isl_give isl_morph *isl_basic_set_variable_compression(
 __isl_give isl_morph *isl_basic_set_parameter_compression(
 	__isl_keep isl_basic_set *bset)
 {
-	unsigned nparam;
-	unsigned nvar;
-	unsigned n_div;
+	isl_size nparam;
+	isl_size nvar;
+	isl_size n_div;
 	int n_eq;
 	isl_mat *H, *B;
 	isl_mat *map, *inv;
@@ -518,6 +548,8 @@ __isl_give isl_morph *isl_basic_set_parameter_compression(
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
 	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	if (nparam < 0 || nvar < 0 || n_div < 0)
+		return NULL;
 
 	if (isl_seq_first_non_zero(bset->eq[bset->n_eq - 1] + 1 + nparam,
 				    nvar + n_div) == -1)
@@ -617,12 +649,9 @@ __isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph,
 	int i, k;
 	int max_stride;
 
-	if (!morph || !bset)
+	if (!morph || isl_basic_set_check_equal_space(bset, morph->dom) < 0)
 		goto error;
 
-	isl_assert(bset->ctx, isl_space_is_equal(bset->dim, morph->dom->dim),
-		    goto error);
-
 	max_stride = morph->inv->n_row - 1;
 	if (isl_int_is_one(morph->inv->row[0][0]))
 		max_stride = 0;
@@ -707,11 +736,9 @@ __isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph,
 {
 	int i;
 
-	if (!morph || !set)
+	if (!morph || isl_set_basic_set_check_equal_space(set, morph->dom) < 0)
 		goto error;
 
-	isl_assert(set->ctx, isl_space_is_equal(set->dim, morph->dom->dim), goto error);
-
 	set = isl_set_cow(set);
 	if (!set)
 		goto error;

diff  --git a/polly/lib/External/isl/isl_morph.h b/polly/lib/External/isl/isl_morph.h
index 8ded75359479..ef8b876c2659 100644
--- a/polly/lib/External/isl/isl_morph.h
+++ b/polly/lib/External/isl/isl_morph.h
@@ -12,6 +12,7 @@
 #define ISL_MORHP_H
 
 #include <stdio.h>
+#include <isl/id_type.h>
 #include <isl/space.h>
 #include <isl/mat.h>
 #include <isl/set.h>
@@ -48,8 +49,8 @@ __isl_give isl_space *isl_morph_get_dom_space(__isl_keep isl_morph *morph);
 __isl_give isl_space *isl_morph_get_ran_space(__isl_keep isl_morph *morph);
 __isl_give isl_multi_aff *isl_morph_get_var_multi_aff(
 	__isl_keep isl_morph *morph);
-unsigned isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type);
-unsigned isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type);
+isl_size isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type);
+isl_size isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type);
 
 __isl_give isl_morph *isl_morph_remove_dom_dims(__isl_take isl_morph *morph,
 	enum isl_dim_type type, unsigned first, unsigned n);
@@ -68,8 +69,7 @@ void isl_morph_dump(__isl_take isl_morph *morph);
 __isl_give isl_morph *isl_basic_set_variable_compression(
 	__isl_keep isl_basic_set *bset, enum isl_dim_type type);
 __isl_give isl_morph *isl_basic_set_variable_compression_with_id(
-	__isl_keep isl_basic_set *bset, enum isl_dim_type type,
-	__isl_keep isl_id *id);
+	__isl_keep isl_basic_set *bset, __isl_keep isl_id *id);
 __isl_give isl_morph *isl_basic_set_parameter_compression(
 	__isl_keep isl_basic_set *bset);
 __isl_give isl_morph *isl_basic_set_full_compression(

diff  --git a/polly/lib/External/isl/isl_multi_add_constant_templ.c b/polly/lib/External/isl/isl_multi_add_constant_templ.c
new file mode 100644
index 000000000000..fa4971fb733d
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_add_constant_templ.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#include <isl_multi_macro.h>
+
+/* Add "v" to the constant terms of all the base expressions of "multi".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),add_constant_val)(
+	__isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
+{
+	isl_bool zero;
+	isl_size n;
+	int i;
+
+	zero = isl_val_is_zero(v);
+	n = FN(MULTI(BASE),size)(multi);
+	if (zero < 0 || n < 0)
+		goto error;
+	if (zero || n == 0) {
+		isl_val_free(v);
+		return multi;
+	}
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		goto error;
+
+	for (i = 0; i < n; ++i) {
+		multi->u.p[i] = FN(EL,add_constant_val)(multi->u.p[i],
+							    isl_val_copy(v));
+		if (!multi->u.p[i])
+			goto error;
+	}
+
+	isl_val_free(v);
+	return multi;
+error:
+	FN(MULTI(BASE),free)(multi);
+	isl_val_free(v);
+	return NULL;
+}
+
+/* Add the elements of "mv" to the constant terms of
+ * the corresponding base expressions of "multi".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),add_constant_multi_val)(
+	__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+{
+	isl_space *multi_space, *mv_space;
+	isl_bool zero, equal;
+	isl_size n;
+	int i;
+
+	zero = isl_multi_val_is_zero(mv);
+	n = FN(MULTI(BASE),size)(multi);
+	multi_space = FN(MULTI(BASE),peek_space)(multi);
+	mv_space = isl_multi_val_peek_space(mv);
+	equal = isl_space_tuple_is_equal(multi_space, isl_dim_out,
+					mv_space, isl_dim_out);
+	if (zero < 0 || n < 0 || equal < 0)
+		goto error;
+	if (!equal)
+		isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
+			"spaces don't match", goto error);
+	if (zero || n == 0) {
+		isl_multi_val_free(mv);
+		return multi;
+	}
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		goto error;
+
+	for (i = 0; i < n; ++i) {
+		isl_val *v = isl_multi_val_get_at(mv, i);
+		multi->u.p[i] = FN(EL,add_constant_val)(multi->u.p[i], v);
+		if (!multi->u.p[i])
+			goto error;
+	}
+
+	isl_multi_val_free(mv);
+	return multi;
+error:
+	FN(MULTI(BASE),free)(multi);
+	isl_multi_val_free(mv);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_multi_arith_templ.c b/polly/lib/External/isl/isl_multi_arith_templ.c
new file mode 100644
index 000000000000..28d080f182d7
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_arith_templ.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2011      Sven Verdoolaege
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/space.h>
+#include <isl_val_private.h>
+
+#include <isl_multi_macro.h>
+
+/* Add "multi2" to "multi1" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
+	__isl_take MULTI(BASE) *multi2)
+{
+	FN(MULTI(BASE),align_params_bin)(&multi1, &multi2);
+	return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
+}
+
+/* Subtract "multi2" from "multi1" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
+	__isl_take MULTI(BASE) *multi2)
+{
+	FN(MULTI(BASE),align_params_bin)(&multi1, &multi2);
+	return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
+}
+
+/* Multiply the elements of "multi" by "v" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
+	__isl_take isl_val *v)
+{
+	int i;
+
+	if (!multi || !v)
+		goto error;
+
+	if (isl_val_is_one(v)) {
+		isl_val_free(v);
+		return multi;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational factor", goto error);
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	for (i = 0; i < multi->n; ++i) {
+		multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
+						isl_val_copy(v));
+		if (!multi->u.p[i])
+			goto error;
+	}
+
+	isl_val_free(v);
+	return multi;
+error:
+	isl_val_free(v);
+	return FN(MULTI(BASE),free)(multi);
+}
+
+/* Divide the elements of "multi" by "v" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
+	__isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
+{
+	int i;
+
+	if (!multi || !v)
+		goto error;
+
+	if (isl_val_is_one(v)) {
+		isl_val_free(v);
+		return multi;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational factor", goto error);
+	if (isl_val_is_zero(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"cannot scale down by zero", goto error);
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	for (i = 0; i < multi->n; ++i) {
+		multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
+						    isl_val_copy(v));
+		if (!multi->u.p[i])
+			goto error;
+	}
+
+	isl_val_free(v);
+	return multi;
+error:
+	isl_val_free(v);
+	return FN(MULTI(BASE),free)(multi);
+}
+
+/* Multiply the elements of "multi" by the corresponding element of "mv"
+ * and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
+	__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+{
+	int i;
+
+	if (!multi || !mv)
+		goto error;
+
+	if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
+					mv->space, isl_dim_set))
+		isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
+			"spaces don't match", goto error);
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		goto error;
+
+	for (i = 0; i < multi->n; ++i) {
+		isl_val *v;
+
+		v = isl_multi_val_get_val(mv, i);
+		multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
+		if (!multi->u.p[i])
+			goto error;
+	}
+
+	isl_multi_val_free(mv);
+	return multi;
+error:
+	isl_multi_val_free(mv);
+	return FN(MULTI(BASE),free)(multi);
+}
+
+/* Divide the elements of "multi" by the corresponding element of "mv"
+ * and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
+	__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+{
+	int i;
+
+	if (!multi || !mv)
+		goto error;
+
+	if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
+					mv->space, isl_dim_set))
+		isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
+			"spaces don't match", goto error);
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	for (i = 0; i < multi->n; ++i) {
+		isl_val *v;
+
+		v = isl_multi_val_get_val(mv, i);
+		multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
+		if (!multi->u.p[i])
+			goto error;
+	}
+
+	isl_multi_val_free(mv);
+	return multi;
+error:
+	isl_multi_val_free(mv);
+	return FN(MULTI(BASE),free)(multi);
+}
+
+/* Compute the residues of the elements of "multi" modulo
+ * the corresponding element of "mv" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
+	__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+{
+	int i;
+
+	if (!multi || !mv)
+		goto error;
+
+	if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
+					mv->space, isl_dim_set))
+		isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
+			"spaces don't match", goto error);
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		goto error;
+
+	for (i = 0; i < multi->n; ++i) {
+		isl_val *v;
+
+		v = isl_multi_val_get_val(mv, i);
+		multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
+		if (!multi->u.p[i])
+			goto error;
+	}
+
+	isl_multi_val_free(mv);
+	return multi;
+error:
+	isl_multi_val_free(mv);
+	return FN(MULTI(BASE),free)(multi);
+}
+
+/* Return the opposite of "multi".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
+{
+	int i;
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	for (i = 0; i < multi->n; ++i) {
+		multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
+		if (!multi->u.p[i])
+			return FN(MULTI(BASE),free)(multi);
+	}
+
+	return multi;
+}

diff  --git a/polly/lib/External/isl/isl_multi_bind_domain_templ.c b/polly/lib/External/isl/isl_multi_bind_domain_templ.c
new file mode 100644
index 000000000000..d7eec37cad26
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_bind_domain_templ.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2018      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#include <isl_multi_macro.h>
+
+#undef TYPE
+#define TYPE	MULTI(BASE)
+#include <isl_bind_domain_templ.c>

diff  --git a/polly/lib/External/isl/isl_multi_bind_templ.c b/polly/lib/External/isl/isl_multi_bind_templ.c
new file mode 100644
index 000000000000..ce2508c4517f
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_bind_templ.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+/* Bind the expressions of "multi" to parameters with identifiers
+ * specified by "tuple", living in the same space as
+ * (the target space of) "multi",
+ * returning the elements in the domain where the expressions
+ * are equal to the parameters.
+ */
+__isl_give DOM *FN(MULTI(BASE),bind)(__isl_take MULTI(BASE) *multi,
+	__isl_take isl_multi_id *tuple)
+{
+	int i;
+	isl_id *id;
+	isl_stat r;
+	isl_size n;
+	isl_space *multi_space, *tuple_space;
+	EL *el;
+	DOM *bnd;
+
+	multi_space = isl_space_range(FN(MULTI(BASE),get_space)(multi));
+	tuple_space = isl_multi_id_peek_space(tuple);
+	r = isl_space_check_equal_tuples(multi_space, tuple_space);
+	isl_space_free(multi_space);
+	if (r < 0)
+		goto error;
+	n = FN(MULTI(BASE),dim)(multi, isl_dim_set);
+	if (n < 0)
+		goto error;
+
+	if (n == 0) {
+		isl_multi_id_free(tuple);
+		return FN(MULTI(BASE),domain)(multi);
+	}
+
+	el = FN(MULTI(BASE),get_at)(multi, 0);
+	id = isl_multi_id_get_at(tuple, 0);
+	bnd = FN(EL,bind_id)(el, id);
+
+	for (i = 1; i < n; ++i) {
+		DOM *bnd_i;
+
+		el = FN(MULTI(BASE),get_at)(multi, i);
+		id = isl_multi_id_get_at(tuple, i);
+		bnd_i = FN(EL,bind_id)(el, id);
+
+		bnd_i = FN(DOM,align_params)(bnd_i, FN(DOM,get_space)(bnd));
+		bnd = FN(DOM,align_params)(bnd, FN(DOM,get_space)(bnd_i));
+		bnd = FN(DOM,intersect)(bnd, bnd_i);
+	}
+
+	FN(MULTI(BASE),free)(multi);
+	isl_multi_id_free(tuple);
+	return bnd;
+error:
+	FN(MULTI(BASE),free)(multi);
+	isl_multi_id_free(tuple);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_multi_dim_id_templ.c b/polly/lib/External/isl/isl_multi_dim_id_templ.c
new file mode 100644
index 000000000000..80dd7db5878f
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_dim_id_templ.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2011      Sven Verdoolaege
+ * Copyright 2013      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/space.h>
+
+#include <isl_multi_macro.h>
+
+/* Return the position of the dimension of the given type and name
+ * in "multi".
+ * Return -1 if no such dimension can be found.
+ */
+int FN(MULTI(BASE),find_dim_by_name)(__isl_keep MULTI(BASE) *multi,
+	enum isl_dim_type type, const char *name)
+{
+	if (!multi)
+		return -1;
+	return isl_space_find_dim_by_name(multi->space, type, name);
+}
+
+/* Return the position of the first dimension of "type" with id "id".
+ * Return -1 if there is no such dimension.
+ */
+int FN(MULTI(BASE),find_dim_by_id)(__isl_keep MULTI(BASE) *multi,
+	enum isl_dim_type type, __isl_keep isl_id *id)
+{
+	if (!multi)
+		return -1;
+	return isl_space_find_dim_by_id(multi->space, type, id);
+}
+
+/* Return the id of the given dimension.
+ */
+__isl_give isl_id *FN(MULTI(BASE),get_dim_id)(__isl_keep MULTI(BASE) *multi,
+	enum isl_dim_type type, unsigned pos)
+{
+	return multi ? isl_space_get_dim_id(multi->space, type, pos) : NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_name)(
+	__isl_take MULTI(BASE) *multi,
+	enum isl_dim_type type, unsigned pos, const char *s)
+{
+	int i;
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
+	if (!multi->space)
+		return FN(MULTI(BASE),free)(multi);
+
+	if (type == isl_dim_out)
+		return multi;
+	for (i = 0; i < multi->n; ++i) {
+		multi->u.p[i] = FN(EL,set_dim_name)(multi->u.p[i],
+							type, pos, s);
+		if (!multi->u.p[i])
+			return FN(MULTI(BASE),free)(multi);
+	}
+
+	return multi;
+}
+
+/* Set the id of the given dimension of "multi" to "id".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_id)(
+	__isl_take MULTI(BASE) *multi,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+	isl_space *space;
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi || !id)
+		goto error;
+
+	space = FN(MULTI(BASE),get_space)(multi);
+	space = isl_space_set_dim_id(space, type, pos, id);
+
+	return FN(MULTI(BASE),reset_space)(multi, space);
+error:
+	isl_id_free(id);
+	FN(MULTI(BASE),free)(multi);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_multi_dims.c b/polly/lib/External/isl/isl_multi_dims.c
index 766625e896ae..a2775eab9fc1 100644
--- a/polly/lib/External/isl/isl_multi_dims.c
+++ b/polly/lib/External/isl/isl_multi_dims.c
@@ -82,9 +82,11 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),insert_dims)(
 __isl_give MULTI(BASE) *FN(MULTI(BASE),add_dims)(__isl_take MULTI(BASE) *multi,
 	enum isl_dim_type type, unsigned n)
 {
-	unsigned pos;
+	isl_size pos;
 
 	pos = FN(MULTI(BASE),dim)(multi, type);
+	if (pos < 0)
+		return FN(MULTI(BASE),free)(multi);
 
 	return FN(MULTI(BASE),insert_dims)(multi, type, pos, n);
 }
@@ -95,11 +97,13 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),add_dims)(__isl_take MULTI(BASE) *multi,
 __isl_give MULTI(BASE) *FN(MULTI(BASE),project_domain_on_params)(
 	__isl_take MULTI(BASE) *multi)
 {
-	unsigned n;
+	isl_size n;
 	isl_bool involves;
 	isl_space *space;
 
 	n = FN(MULTI(BASE),dim)(multi, isl_dim_in);
+	if (n < 0)
+		return FN(MULTI(BASE),free)(multi);
 	involves = FN(MULTI(BASE),involves_dims)(multi, isl_dim_in, 0, n);
 	if (involves < 0)
 		return FN(MULTI(BASE),free)(multi);

diff  --git a/polly/lib/External/isl/isl_multi_domain_templ.c b/polly/lib/External/isl/isl_multi_domain_templ.c
new file mode 100644
index 000000000000..6aa97fe32017
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_domain_templ.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/set.h>
+
+#include <isl_multi_macro.h>
+
+/* Return the shared domain of the elements of "multi".
+ *
+ * If "multi" has an explicit domain, then return this domain.
+ */
+__isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
+{
+	int i;
+	isl_set *dom;
+
+	if (!multi)
+		return NULL;
+
+	if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
+		dom = FN(MULTI(BASE),get_explicit_domain)(multi);
+		FN(MULTI(BASE),free)(multi);
+		return dom;
+	}
+
+	dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
+	for (i = 0; i < multi->n; ++i) {
+		isl_set *dom_i;
+
+		dom_i = FN(EL,domain)(FN(FN(MULTI(BASE),get),BASE)(multi, i));
+		dom = isl_set_intersect(dom, dom_i);
+	}
+
+	FN(MULTI(BASE),free)(multi);
+	return dom;
+}

diff  --git a/polly/lib/External/isl/isl_multi_from_base_templ.c b/polly/lib/External/isl/isl_multi_from_base_templ.c
new file mode 100644
index 000000000000..2a2a6b1ecfe8
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_from_base_templ.c
@@ -0,0 +1,37 @@
+/*
+ * 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/space.h>
+
+#include <isl_multi_macro.h>
+
+/* Create a multiple expression with a single output/set dimension
+ * equal to "el".
+ * For most multiple expression types, the base type has a single
+ * output/set dimension and the space of the result is therefore
+ * the same as the space of the input.
+ * In the case of isl_multi_union_pw_aff, however, the base type
+ * lives in a parameter space and we therefore need to add
+ * a single set dimension.
+ */
+__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
+{
+	isl_space *space;
+	MULTI(BASE) *multi;
+
+	space = FN(EL,get_space(el));
+	if (isl_space_is_params(space)) {
+		space = isl_space_set_from_params(space);
+		space = isl_space_add_dims(space, isl_dim_set, 1);
+	}
+	multi = FN(MULTI(BASE),alloc)(space);
+	multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
+
+	return multi;
+}

diff  --git a/polly/lib/External/isl/isl_multi_identity_templ.c b/polly/lib/External/isl/isl_multi_identity_templ.c
new file mode 100644
index 000000000000..d598d11accc8
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_identity_templ.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012      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/space.h>
+#include <isl/local_space.h>
+
+#include <isl_multi_macro.h>
+
+/* Create a multi expression in the given space that maps each
+ * input dimension to the corresponding output dimension.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),identity)(__isl_take isl_space *space)
+{
+	int i;
+	isl_size n_in, n_out;
+	isl_local_space *ls;
+	MULTI(BASE) *multi;
+
+	if (!space)
+		return NULL;
+
+	if (isl_space_is_set(space))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"expecting map space", goto error);
+
+	n_in = isl_space_dim(space, isl_dim_in);
+	n_out = isl_space_dim(space, isl_dim_out);
+	if (n_in < 0 || n_out < 0)
+		goto error;
+	if (n_in != n_out)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"number of input and output dimensions needs to be "
+			"the same", goto error);
+
+	multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
+
+	if (!n_out) {
+		isl_space_free(space);
+		return multi;
+	}
+
+	space = isl_space_domain(space);
+	ls = isl_local_space_from_space(space);
+
+	for (i = 0; i < n_out; ++i) {
+		EL *el;
+		el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
+						isl_dim_set, i);
+		multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
+	}
+
+	isl_local_space_free(ls);
+
+	return multi;
+error:
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Create a multi expression that maps elements in the given space
+ * to themselves.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),identity_on_domain_space)(
+	__isl_take isl_space *space)
+{
+	return FN(MULTI(BASE),identity)(isl_space_map_from_set(space));
+}
+
+/* Create a multi expression in the same space as "multi" that maps each
+ * input dimension to the corresponding output dimension.
+ */
+__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),identity_multi),BASE)(
+	__isl_take MULTI(BASE) *multi)
+{
+	isl_space *space;
+
+	space = FN(MULTI(BASE),get_space)(multi);
+	FN(MULTI(BASE),free)(multi);
+	return FN(MULTI(BASE),identity)(space);
+}

diff  --git a/polly/lib/External/isl/isl_multi_locals_templ.c b/polly/lib/External/isl/isl_multi_locals_templ.c
new file mode 100644
index 000000000000..3cfb0a33c35a
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_locals_templ.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#include <isl_multi_macro.h>
+
+/* Does "multi" involve any local variables?
+ */
+isl_bool FN(MULTI(BASE),involves_locals)(__isl_keep MULTI(BASE) *multi)
+{
+	return FN(MULTI(BASE),any)(multi, FN(EL,involves_locals));
+}

diff  --git a/polly/lib/External/isl/isl_multi_macro.h b/polly/lib/External/isl/isl_multi_macro.h
index 0200b4ddd443..394494b06e68 100644
--- a/polly/lib/External/isl/isl_multi_macro.h
+++ b/polly/lib/External/isl/isl_multi_macro.h
@@ -1,9 +1,7 @@
-#define xCAT(A,B) A ## B
-#define CAT(A,B) xCAT(A,B)
-#undef EL
-#define EL CAT(isl_,BASE)
-#define xFN(TYPE,NAME) TYPE ## _ ## NAME
-#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#undef EL_BASE
+#define EL_BASE BASE
+#include <isl_list_macro.h>
+
 #define xMULTI(BASE) isl_multi_ ## BASE
 #define MULTI(BASE) xMULTI(BASE)
 #undef DOM

diff  --git a/polly/lib/External/isl/isl_multi_move_dims_templ.c b/polly/lib/External/isl/isl_multi_move_dims_templ.c
new file mode 100644
index 000000000000..9c880857948b
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_move_dims_templ.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/space.h>
+
+#include <isl_multi_macro.h>
+
+/* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
+ * to dimensions of "dst_type" at "dst_pos".
+ *
+ * We only support moving input dimensions to parameters and vice versa.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+	int i;
+
+	if (!multi)
+		return NULL;
+
+	if (n == 0 &&
+	    !isl_space_is_named_or_nested(multi->space, src_type) &&
+	    !isl_space_is_named_or_nested(multi->space, dst_type))
+		return multi;
+
+	if (dst_type == isl_dim_out || src_type == isl_dim_out)
+		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+			"cannot move output/set dimension",
+			return FN(MULTI(BASE),free)(multi));
+	if (dst_type == isl_dim_div || src_type == isl_dim_div)
+		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+			"cannot move divs",
+			return FN(MULTI(BASE),free)(multi));
+	if (FN(MULTI(BASE),check_range)(multi, src_type, src_pos, n) < 0)
+		return FN(MULTI(BASE),free)(multi);
+	if (dst_type == src_type)
+		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
+			"moving dims within the same type not supported",
+			return FN(MULTI(BASE),free)(multi));
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
+						src_type, src_pos, n);
+	if (!multi->space)
+		return FN(MULTI(BASE),free)(multi);
+	if (FN(MULTI(BASE),has_explicit_domain)(multi))
+		multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
+				dst_type, dst_pos, src_type, src_pos, n);
+	if (!multi)
+		return NULL;
+
+	for (i = 0; i < multi->n; ++i) {
+		multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
+						dst_type, dst_pos,
+						src_type, src_pos, n);
+		if (!multi->u.p[i])
+			return FN(MULTI(BASE),free)(multi);
+	}
+
+	return multi;
+}

diff  --git a/polly/lib/External/isl/isl_multi_nan_templ.c b/polly/lib/External/isl/isl_multi_nan_templ.c
new file mode 100644
index 000000000000..2ea73a8140bb
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_nan_templ.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2014      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl_multi_macro.h>
+
+/* Does "multi" involve any NaNs?
+ */
+isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
+{
+	return FN(MULTI(BASE),any)(multi, &FN(EL,involves_nan));
+}

diff  --git a/polly/lib/External/isl/isl_multi_no_domain_templ.c b/polly/lib/External/isl/isl_multi_no_domain_templ.c
new file mode 100644
index 000000000000..1c98ac452452
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_no_domain_templ.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2013      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/space.h>
+#include <isl/local_space.h>
+#include <isl_reordering.h>
+
+#include <isl_multi_macro.h>
+
+/* The functions in this file are meant for base object types
+ * that do not have any associated space.  They are only meant to be used
+ * in the generic isl_multi_* functions which have to deal with base objects
+ * that do have an associated space.
+ */
+
+
+/* Drop the "n" first dimensions of type "type" at position "first".
+ *
+ * For a base expression without an associated space, this function
+ * does not do anything.
+ */
+static __isl_give EL *FN(EL,drop_dims)(__isl_take EL *el,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	return el;
+}
+
+/* Return the space of "el".
+ *
+ * For a base expression without an associated space,
+ * the conditions surrounding the call to this function make sure
+ * that this function will never actually get called.  We return a valid
+ * space anyway, just in case.
+ */
+static __isl_give isl_space *FN(EL,get_space)(__isl_keep EL *el)
+{
+	if (!el)
+		return NULL;
+
+	return isl_space_params_alloc(FN(EL,get_ctx)(el), 0);
+}
+
+/* Reset the domain space of "el" to "space".
+ *
+ * For a base expression without an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ */
+static __isl_give EL *FN(EL,reset_domain_space)(__isl_take EL *el,
+	__isl_take isl_space *space)
+{
+	if (!space)
+		return FN(EL,free)(el);
+	isl_space_free(space);
+	return el;
+}
+
+/* Align the parameters of "el" to those of "space".
+ *
+ * For a base expression without an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ * Note that the conditions surrounding the call to this function make sure
+ * that this function will never actually get called.
+ */
+static __isl_give EL *FN(EL,align_params)(__isl_take EL *el,
+	__isl_take isl_space *space)
+{
+	if (!space)
+		return FN(EL,free)(el);
+	isl_space_free(space);
+	return el;
+}
+
+/* Reorder the dimensions of the domain of "el" according
+ * to the given reordering.
+ *
+ * For a base expression without an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ */
+static __isl_give EL *FN(EL,realign_domain)(__isl_take EL *el,
+	__isl_take isl_reordering *r)
+{
+	if (!r)
+		return FN(EL,free)(el);
+	isl_reordering_free(r);
+	return el;
+}
+
+/* Do the parameters of "el" match those of "space"?
+ *
+ * For a base expression without an associated space, this function
+ * simply returns true, except if "el" or "space" are NULL.
+ */
+static isl_bool FN(EL,matching_params)(__isl_keep EL *el,
+	__isl_keep isl_space *space)
+{
+	if (!el || !space)
+		return isl_bool_error;
+	return isl_bool_true;
+}
+
+/* Check that the domain space of "el" matches "space".
+ *
+ * For a base expression without an associated space, this function
+ * simply returns isl_stat_ok, except if "el" or "space" are NULL.
+ */
+static isl_stat FN(EL,check_match_domain_space)(__isl_keep EL *el,
+	__isl_keep isl_space *space)
+{
+	if (!el || !space)
+		return isl_stat_error;
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/isl_multi_no_explicit_domain.c b/polly/lib/External/isl/isl_multi_no_explicit_domain.c
index fc672a05b5fc..cba4387ab58e 100644
--- a/polly/lib/External/isl/isl_multi_no_explicit_domain.c
+++ b/polly/lib/External/isl/isl_multi_no_explicit_domain.c
@@ -51,6 +51,13 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),copy_explicit_domain)(
 	return dst;
 }
 
+/* Only used by multi-expressions that include "isl_multi_product_templ.c".
+ */
+static __isl_give MULTI(BASE) *
+FN(MULTI(BASE),intersect_explicit_domain_product)(
+	__isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src1,
+	__isl_keep MULTI(BASE) *src2) __attribute__ ((unused));
+
 /* Intersect the domain of "dst" with the domain product
  * of the explicit domains of "src1" and "src2".
  * This function is only called if at least one of "src1" or "src2"

diff  --git a/polly/lib/External/isl/isl_multi_param_templ.c b/polly/lib/External/isl/isl_multi_param_templ.c
new file mode 100644
index 000000000000..eab93548933f
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_param_templ.c
@@ -0,0 +1,60 @@
+/*
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege
+ */
+
+#include <isl_multi_macro.h>
+
+/* Does the multiple expression "multi" depend in any way
+ * on the parameter with identifier "id"?
+ */
+isl_bool FN(MULTI(BASE),involves_param_id)(__isl_keep MULTI(BASE) *multi,
+	__isl_keep isl_id *id)
+{
+	int i;
+	int pos;
+
+	if (!multi || !id)
+		return isl_bool_error;
+	if (multi->n == 0)
+		return isl_bool_false;
+	pos = FN(MULTI(BASE),find_dim_by_id)(multi, isl_dim_param, id);
+	if (pos < 0)
+		return isl_bool_false;
+
+	for (i = 0; i < multi->n; ++i) {
+		isl_bool involved = FN(EL,involves_param_id)(multi->u.p[i], id);
+		if (involved < 0 || involved)
+			return involved;
+	}
+
+	return isl_bool_false;
+}
+
+/* Does the multiple expression "multi" depend in any way
+ * on any of the parameters with identifiers in "list"?
+ */
+isl_bool FN(MULTI(BASE),involves_param_id_list)(__isl_keep MULTI(BASE) *multi,
+	__isl_keep isl_id_list *list)
+{
+	int i;
+	isl_size n;
+
+	n = isl_id_list_size(list);
+	if (n < 0)
+		return isl_bool_error;
+	for (i = 0; i < n; ++i) {
+		isl_bool involves;
+		isl_id *id;
+
+		id = isl_id_list_get_at(list, i);
+		involves = FN(MULTI(BASE),involves_param_id)(multi, id);
+		isl_id_free(id);
+
+		if (involves < 0 || involves)
+			return involves;
+	}
+
+	return isl_bool_false;
+}

diff  --git a/polly/lib/External/isl/isl_multi_product_templ.c b/polly/lib/External/isl/isl_multi_product_templ.c
new file mode 100644
index 000000000000..5640326fd826
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_product_templ.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012      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/space.h>
+
+#include <isl_multi_macro.h>
+
+/* Given two MULTI(BASE)s A -> B and C -> D,
+ * construct a MULTI(BASE) [A -> C] -> [B -> D].
+ *
+ * If "multi1" and/or "multi2" has an explicit domain, then
+ * intersect the domain of the result with these explicit domains.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
+	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+	int i;
+	EL *el;
+	isl_space *space;
+	MULTI(BASE) *res;
+	isl_size in1, in2, out1, out2;
+
+	FN(MULTI(BASE),align_params_bin)(&multi1, &multi2);
+	in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
+	in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
+	out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
+	out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
+	if (in1 < 0 || in2 < 0 || out1 < 0 || out2 < 0)
+		goto error;
+	space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
+				  FN(MULTI(BASE),get_space)(multi2));
+	res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
+	space = isl_space_domain(space);
+
+	for (i = 0; i < out1; ++i) {
+		el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
+		el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
+		el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
+		res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
+	}
+
+	for (i = 0; i < out2; ++i) {
+		el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
+		el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
+		el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
+		res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
+	}
+
+	if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
+	    FN(MULTI(BASE),has_explicit_domain)(multi2))
+		res = FN(MULTI(BASE),intersect_explicit_domain_product)(res,
+								multi1, multi2);
+
+	isl_space_free(space);
+	FN(MULTI(BASE),free)(multi1);
+	FN(MULTI(BASE),free)(multi2);
+	return res;
+error:
+	FN(MULTI(BASE),free)(multi1);
+	FN(MULTI(BASE),free)(multi2);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_multi_read_no_explicit_domain_templ.c b/polly/lib/External/isl/isl_multi_read_no_explicit_domain_templ.c
new file mode 100644
index 000000000000..b8a6ec5440ee
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_read_no_explicit_domain_templ.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/space.h>
+#include <isl/set.h>
+
+#include <isl_multi_macro.h>
+
+/* This function is called for each element in a tuple inside
+ * isl_stream_read_multi_*.
+ * Read an EL from "s" and add it to *list.
+ */
+static __isl_give isl_space *FN(read_el,BASE)(__isl_keep isl_stream *s,
+	struct vars *v, __isl_take isl_space *space, int rational, void *user)
+{
+	LIST(EL) **list = (LIST(EL) **) user;
+	EL *el;
+
+	el = FN(isl_stream_read,BASE)(s);
+	*list = FN(LIST(EL),add)(*list, el);
+	if (!*list)
+		return isl_space_free(space);
+
+	return space;
+}
+
+/* Read a multi expression from "s".
+ *
+ * We first read a tuple space, collecting the element values in a list.
+ * Then we create an isl_multi_* from the space and the isl_*_list.
+ */
+__isl_give MULTI(BASE) *FN(isl_stream_read_multi,BASE)(
+	__isl_keep isl_stream *s)
+{
+	struct vars *v;
+	isl_set *dom = NULL;
+	isl_space *space;
+	MULTI(BASE) *multi = NULL;
+	LIST(EL) *list;
+
+	v = vars_new(s->ctx);
+	if (!v)
+		return NULL;
+
+	dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
+	if (next_is_tuple(s)) {
+		dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
+		if (isl_stream_eat(s, ISL_TOKEN_TO))
+			goto error;
+	}
+	if (!isl_set_plain_is_universe(dom))
+		isl_die(s->ctx, isl_error_invalid,
+			"expecting universe parameter domain", goto error);
+	if (isl_stream_eat(s, '{'))
+		goto error;
+
+	space = isl_set_get_space(dom);
+
+	list = FN(LIST(EL),alloc)(s->ctx, 0);
+	space = read_tuple_space(s, v, space, 1, 0, &FN(read_el,BASE), &list);
+	multi = FN(FN(MULTI(BASE),from),LIST(BASE))(space, list);
+
+	if (isl_stream_eat(s, '}'))
+		goto error;
+
+	vars_free(v);
+	isl_set_free(dom);
+	return multi;
+error:
+	vars_free(v);
+	isl_set_free(dom);
+	FN(MULTI(BASE),free)(multi);
+	return NULL;
+}
+
+/* Read a multi expression from "str".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),read_from_str)(isl_ctx *ctx,
+	const char *str)
+{
+	MULTI(BASE) *multi;
+	isl_stream *s = isl_stream_new_str(ctx, str);
+	if (!s)
+		return NULL;
+	multi = FN(isl_stream_read_multi,BASE)(s);
+	isl_stream_free(s);
+	return multi;
+}

diff  --git a/polly/lib/External/isl/isl_multi_splice_templ.c b/polly/lib/External/isl/isl_multi_splice_templ.c
new file mode 100644
index 000000000000..8dca62089b72
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_splice_templ.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012      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/ctx.h>
+#include <isl/space.h>
+
+#include <isl_multi_macro.h>
+
+/* Given two multi expressions, "multi1"
+ *
+ *	[A1 A2] -> [B1 B2]
+ *
+ * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
+ * and "multi2"
+ *
+ *	[C] -> [D]
+ *
+ * return the multi expression
+ *
+ *	[A1 C A2] -> [B1 D B2]
+ *
+ * We first insert input dimensions to obtain
+ *
+ *	[A1 C A2] -> [B1 B2]
+ *
+ * and
+ *
+ *	[A1 C A2] -> [D]
+ *
+ * and then apply range_splice.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
+	__isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
+	__isl_take MULTI(BASE) *multi2)
+{
+	isl_size n_in1;
+	isl_size n_in2;
+
+	n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
+	n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
+	if (n_in1 < 0 || n_in2 < 0)
+		goto error;
+
+	if (FN(MULTI(BASE),check_range)(multi1, isl_dim_in, in_pos, 0) < 0)
+		goto error;
+
+	multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
+	multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
+						n_in1 - in_pos);
+	multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
+
+	return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
+error:
+	FN(MULTI(BASE),free)(multi1);
+	FN(MULTI(BASE),free)(multi2);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_multi_templ.c b/polly/lib/External/isl/isl_multi_templ.c
index 3403c502e807..3d48c9a41932 100644
--- a/polly/lib/External/isl/isl_multi_templ.c
+++ b/polly/lib/External/isl/isl_multi_templ.c
@@ -1,6 +1,6 @@
 /*
  * Copyright 2011      Sven Verdoolaege
- * Copyright 2012-2013 Ecole Normale Superieure
+ * Copyright 2012-2014 Ecole Normale Superieure
  *
  * Use of this software is governed by the MIT license
  *
@@ -10,15 +10,12 @@
 
 #include <isl/id.h>
 #include <isl_space_private.h>
-#include <isl_val_private.h>
 #include <isl/set.h>
 #include <isl_reordering.h>
 
 #include <isl_multi_macro.h>
 
 #define MULTI_NAME(BASE) "isl_multi_" #BASE
-#define xLIST(EL) EL ## _list
-#define LIST(EL) xLIST(EL)
 
 isl_ctx *FN(MULTI(BASE),get_ctx)(__isl_keep MULTI(BASE) *multi)
 {
@@ -37,18 +34,6 @@ __isl_give isl_space *FN(MULTI(BASE),get_space)(__isl_keep MULTI(BASE) *multi)
 	return isl_space_copy(FN(MULTI(BASE),peek_space)(multi));
 }
 
-/* Return the position of the dimension of the given type and name
- * in "multi".
- * Return -1 if no such dimension can be found.
- */
-int FN(MULTI(BASE),find_dim_by_name)(__isl_keep MULTI(BASE) *multi,
-	enum isl_dim_type type, const char *name)
-{
-	if (!multi)
-		return -1;
-	return isl_space_find_dim_by_name(multi->space, type, name);
-}
-
 __isl_give isl_space *FN(MULTI(BASE),get_domain_space)(
 	__isl_keep MULTI(BASE) *multi)
 {
@@ -64,14 +49,14 @@ __isl_give isl_space *FN(MULTI(BASE),get_domain_space)(
 __isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space)
 {
 	isl_ctx *ctx;
-	int n;
+	isl_size n;
 	MULTI(BASE) *multi;
 
-	if (!space)
-		return NULL;
+	n = isl_space_dim(space, isl_dim_out);
+	if (n < 0)
+		goto error;
 
 	ctx = isl_space_get_ctx(space);
-	n = isl_space_dim(space, isl_dim_out);
 	if (n > 0)
 		multi = isl_calloc(ctx, MULTI(BASE),
 			 sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
@@ -153,93 +138,42 @@ __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
 	return NULL;
 }
 
-unsigned FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
+isl_size FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
 	enum isl_dim_type type)
 {
-	return multi ? isl_space_dim(multi->space, type) : 0;
+	return isl_space_dim(FN(MULTI(BASE),peek_space)(multi), type);
 }
 
-/* Return the position of the first dimension of "type" with id "id".
- * Return -1 if there is no such dimension.
+/* Return the number of base expressions in "multi".
  */
-int FN(MULTI(BASE),find_dim_by_id)(__isl_keep MULTI(BASE) *multi,
-	enum isl_dim_type type, __isl_keep isl_id *id)
+isl_size FN(MULTI(BASE),size)(__isl_keep MULTI(BASE) *multi)
 {
-	if (!multi)
-		return -1;
-	return isl_space_find_dim_by_id(multi->space, type, id);
+	return multi ? multi->n : isl_size_error;
 }
 
-/* Return the id of the given dimension.
- */
-__isl_give isl_id *FN(MULTI(BASE),get_dim_id)(__isl_keep MULTI(BASE) *multi,
-	enum isl_dim_type type, unsigned pos)
-{
-	return multi ? isl_space_get_dim_id(multi->space, type, pos) : NULL;
-}
+#undef TYPE
+#define TYPE	MULTI(BASE)
+static
+#include "check_type_range_templ.c"
 
-__isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_name)(
-	__isl_take MULTI(BASE) *multi,
-	enum isl_dim_type type, unsigned pos, const char *s)
+/* Return a copy of the base expression at position "pos" in "multi".
+ */
+__isl_give EL *FN(MULTI(BASE),get_at)(__isl_keep MULTI(BASE) *multi, int pos)
 {
-	int i;
+	isl_ctx *ctx;
 
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
+	if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0)
 		return NULL;
-
-	multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
-	if (!multi->space)
-		return FN(MULTI(BASE),free)(multi);
-
-	if (type == isl_dim_out)
-		return multi;
-	for (i = 0; i < multi->n; ++i) {
-		multi->u.p[i] = FN(EL,set_dim_name)(multi->u.p[i],
-							type, pos, s);
-		if (!multi->u.p[i])
-			return FN(MULTI(BASE),free)(multi);
-	}
-
-	return multi;
-}
-
-const char *FN(MULTI(BASE),get_tuple_name)(__isl_keep MULTI(BASE) *multi,
-	enum isl_dim_type type)
-{
-	return multi ? isl_space_get_tuple_name(multi->space, type) : NULL;
-}
-
-/* Does the specified tuple have an id?
- */
-isl_bool FN(MULTI(BASE),has_tuple_id)(__isl_keep MULTI(BASE) *multi,
-	enum isl_dim_type type)
-{
-	if (!multi)
-		return isl_bool_error;
-	return isl_space_has_tuple_id(multi->space, type);
+	ctx = FN(MULTI(BASE),get_ctx)(multi);
+	return FN(EL,copy)(multi->u.p[pos]);
 }
 
-/* Return the id of the specified tuple.
+/* This is an alternative name for the function above.
  */
-__isl_give isl_id *FN(MULTI(BASE),get_tuple_id)(__isl_keep MULTI(BASE) *multi,
-	enum isl_dim_type type)
-{
-	return multi ? isl_space_get_tuple_id(multi->space, type) : NULL;
-}
-
 __isl_give EL *FN(FN(MULTI(BASE),get),BASE)(__isl_keep MULTI(BASE) *multi,
 	int pos)
 {
-	isl_ctx *ctx;
-
-	if (!multi)
-		return NULL;
-	ctx = FN(MULTI(BASE),get_ctx)(multi);
-	if (pos < 0 || pos >= multi->n)
-		isl_die(ctx, isl_error_invalid,
-			"index out of bounds", return NULL);
-	return FN(EL,copy)(multi->u.p[pos]);
+	return FN(MULTI(BASE),get_at)(multi, pos);
 }
 
 /* Set the element at position "pos" of "multi" to "el",
@@ -252,9 +186,8 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore)(
 	if (!multi || !el)
 		goto error;
 
-	if (pos < 0 || pos >= multi->n)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
-			"index out of bounds", goto error);
+	if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0)
+		goto error;
 
 	FN(EL,free)(multi->u.p[pos]);
 	multi->u.p[pos] = el;
@@ -282,7 +215,9 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_check_space)(
 	return FN(MULTI(BASE),restore)(multi, pos, el);
 }
 
-__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)(
+/* Replace the base expression at position "pos" in "multi" with "el".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_at)(
 	__isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
 {
 	isl_space *multi_space = NULL;
@@ -315,6 +250,14 @@ __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)(
 	return NULL;
 }
 
+/* This is an alternative name for the function above.
+ */
+__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)(
+	__isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
+{
+	return FN(MULTI(BASE),set_at)(multi, pos, el);
+}
+
 /* Reset the space of "multi".  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,
@@ -378,85 +321,6 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space)(
 	return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
 }
 
-/* Set the id of the given dimension of "multi" to "id".
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_id)(
-	__isl_take MULTI(BASE) *multi,
-	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
-{
-	isl_space *space;
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi || !id)
-		goto error;
-
-	space = FN(MULTI(BASE),get_space)(multi);
-	space = isl_space_set_dim_id(space, type, pos, id);
-
-	return FN(MULTI(BASE),reset_space)(multi, space);
-error:
-	isl_id_free(id);
-	FN(MULTI(BASE),free)(multi);
-	return NULL;
-}
-
-__isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
-	__isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
-	const char *s)
-{
-	isl_space *space;
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	space = FN(MULTI(BASE),get_space)(multi);
-	space = isl_space_set_tuple_name(space, type, s);
-
-	return FN(MULTI(BASE),reset_space)(multi, space);
-}
-
-__isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_id)(
-	__isl_take MULTI(BASE) *multi, enum isl_dim_type type,
-	__isl_take isl_id *id)
-{
-	isl_space *space;
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		goto error;
-
-	space = FN(MULTI(BASE),get_space)(multi);
-	space = isl_space_set_tuple_id(space, type, id);
-
-	return FN(MULTI(BASE),reset_space)(multi, space);
-error:
-	isl_id_free(id);
-	return NULL;
-}
-
-/* Drop the id on the specified tuple.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_tuple_id)(
-	__isl_take MULTI(BASE) *multi, enum isl_dim_type type)
-{
-	isl_space *space;
-
-	if (!multi)
-		return NULL;
-	if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
-		return multi;
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	space = FN(MULTI(BASE),get_space)(multi);
-	space = isl_space_reset_tuple_id(space, type);
-
-	return FN(MULTI(BASE),reset_space)(multi, space);
-}
-
 /* Reset the user pointer on all identifiers of parameters and tuples
  * of the space of "multi".
  */
@@ -560,16 +424,17 @@ __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
 	__isl_take isl_space *space, __isl_take LIST(EL) *list)
 {
 	int i;
-	int n;
+	isl_size n, dim;
 	isl_ctx *ctx;
 	MULTI(BASE) *multi;
 
-	if (!space || !list)
+	dim = isl_space_dim(space, isl_dim_out);
+	n = FN(FN(LIST(EL),n),BASE)(list);
+	if (dim < 0 || n < 0)
 		goto error;
 
 	ctx = isl_space_get_ctx(space);
-	n = FN(FN(LIST(EL),n),BASE)(list);
-	if (n != isl_space_dim(space, isl_dim_out))
+	if (n != dim)
 		isl_die(ctx, isl_error_invalid,
 			"invalid number of elements in list", goto error);
 
@@ -593,135 +458,15 @@ __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
 	return NULL;
 }
 
-#ifndef NO_IDENTITY
-/* Create a multi expression in the given space that maps each
- * input dimension to the corresponding output dimension.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),identity)(__isl_take isl_space *space)
-{
-	int i, n;
-	isl_local_space *ls;
-	MULTI(BASE) *multi;
-
-	if (!space)
-		return NULL;
-
-	if (isl_space_is_set(space))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"expecting map space", goto error);
-
-	n = isl_space_dim(space, isl_dim_out);
-	if (n != isl_space_dim(space, isl_dim_in))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"number of input and output dimensions needs to be "
-			"the same", goto error);
-
-	multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
-
-	if (!n) {
-		isl_space_free(space);
-		return multi;
-	}
-
-	space = isl_space_domain(space);
-	ls = isl_local_space_from_space(space);
-
-	for (i = 0; i < n; ++i) {
-		EL *el;
-		el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
-						isl_dim_set, i);
-		multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
-	}
-
-	isl_local_space_free(ls);
-
-	return multi;
-error:
-	isl_space_free(space);
-	return NULL;
-}
-#endif
-
-#ifndef NO_ZERO
-/* Construct a multi expression in the given space with value zero in
- * each of the output dimensions.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
-{
-	int n;
-	MULTI(BASE) *multi;
-
-	if (!space)
-		return NULL;
-
-	n = isl_space_dim(space , isl_dim_out);
-	multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
-
-	if (!n)
-		isl_space_free(space);
-	else {
-		int i;
-		isl_local_space *ls;
-		EL *el;
-
-		space = isl_space_domain(space);
-		ls = isl_local_space_from_space(space);
-		el = FN(EL,zero_on_domain)(ls);
-
-		for (i = 0; i < n; ++i)
-			multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
-							    FN(EL,copy)(el));
-
-		FN(EL,free)(el);
-	}
-
-	return multi;
-}
-#endif
-
-#ifndef NO_FROM_BASE
-/* Create a multiple expression with a single output/set dimension
- * equal to "el".
- * For most multiple expression types, the base type has a single
- * output/set dimension and the space of the result is therefore
- * the same as the space of the input.
- * In the case of isl_multi_union_pw_aff, however, the base type
- * lives in a parameter space and we therefore need to add
- * a single set dimension.
- */
-__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
-{
-	isl_space *space;
-	MULTI(BASE) *multi;
-
-	space = FN(EL,get_space(el));
-	if (isl_space_is_params(space)) {
-		space = isl_space_set_from_params(space);
-		space = isl_space_add_dims(space, isl_dim_set, 1);
-	}
-	multi = FN(MULTI(BASE),alloc)(space);
-	multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
-
-	return multi;
-}
-#endif
-
 __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
 	__isl_take MULTI(BASE) *multi,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
 	int i;
-	unsigned dim;
 
 	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	dim = FN(MULTI(BASE),dim)(multi, type);
-	if (first + n > dim || first + n < first)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
-			"index out of bounds",
-			return FN(MULTI(BASE),free)(multi));
+	if (FN(MULTI(BASE),check_range)(multi, type, first, n) < 0)
+		return FN(MULTI(BASE),free)(multi);
 
 	multi->space = isl_space_drop_dims(multi->space, type, first, n);
 	if (!multi->space)
@@ -754,65 +499,38 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
 	return multi;
 }
 
-/* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
- */
-static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_multi_and)(
-	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
-	__isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi1,
-		__isl_take MULTI(BASE) *multi2))
-{
-	isl_ctx *ctx;
-	isl_bool equal_params;
+#undef TYPE
+#define TYPE MULTI(BASE)
 
-	if (!multi1 || !multi2)
-		goto error;
-	equal_params = isl_space_has_equal_params(multi1->space, multi2->space);
-	if (equal_params < 0)
-		goto error;
-	if (equal_params)
-		return fn(multi1, multi2);
-	ctx = FN(MULTI(BASE),get_ctx)(multi1);
-	if (!isl_space_has_named_params(multi1->space) ||
-	    !isl_space_has_named_params(multi2->space))
-		isl_die(ctx, isl_error_invalid,
-			"unaligned unnamed parameters", goto error);
-	multi1 = FN(MULTI(BASE),align_params)(multi1,
-					    FN(MULTI(BASE),get_space)(multi2));
-	multi2 = FN(MULTI(BASE),align_params)(multi2,
-					    FN(MULTI(BASE),get_space)(multi1));
-	return fn(multi1, multi2);
-error:
-	FN(MULTI(BASE),free)(multi1);
-	FN(MULTI(BASE),free)(multi2);
-	return NULL;
-}
+#include "isl_check_named_params_templ.c"
+static
+#include "isl_align_params_bin_templ.c"
 
 /* Given two MULTI(BASE)s A -> B and C -> D,
  * construct a MULTI(BASE) (A * C) -> [B -> D].
  *
- * The parameters are assumed to have been aligned.
- *
  * If "multi1" and/or "multi2" has an explicit domain, then
  * intersect the domain of the result with these explicit domains.
  */
-static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
+__isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
 	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
 {
-	int i, n1, n2;
+	int i;
+	isl_size n1, n2;
 	EL *el;
 	isl_space *space;
 	MULTI(BASE) *res;
 
-	if (!multi1 || !multi2)
+	FN(MULTI(BASE),align_params_bin)(&multi1, &multi2);
+	n1 = FN(MULTI(BASE),size)(multi1);
+	n2 = FN(MULTI(BASE),size)(multi2);
+	if (n1 < 0 || n2 < 0)
 		goto error;
 
 	space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1),
 					FN(MULTI(BASE),get_space)(multi2));
 	res = FN(MULTI(BASE),alloc)(space);
 
-	n1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
-	n2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
-
 	for (i = 0; i < n1; ++i) {
 		el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
 		res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
@@ -837,16 +555,6 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
 	return NULL;
 }
 
-/* Given two MULTI(BASE)s A -> B and C -> D,
- * construct a MULTI(BASE) (A * C) -> [B -> D].
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
-	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
-{
-	return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
-					&FN(MULTI(BASE),range_product_aligned));
-}
-
 /* Is the range of "multi" a wrapped relation?
  */
 isl_bool FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi)
@@ -862,19 +570,21 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)(
 	__isl_take MULTI(BASE) *multi)
 {
 	isl_space *space;
-	int total, keep;
+	isl_size total, keep;
 
-	if (!multi)
-		return NULL;
+	total = FN(MULTI(BASE),dim)(multi, isl_dim_out);
+	if (total < 0)
+		return FN(MULTI(BASE),free)(multi);
 	if (!isl_space_range_is_wrapping(multi->space))
 		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
 			"range is not a product",
 			return FN(MULTI(BASE),free)(multi));
 
 	space = FN(MULTI(BASE),get_space)(multi);
-	total = isl_space_dim(space, isl_dim_out);
 	space = isl_space_range_factor_domain(space);
 	keep = isl_space_dim(space, isl_dim_out);
+	if (keep < 0)
+		multi = FN(MULTI(BASE),free)(multi);
 	multi = FN(MULTI(BASE),drop_dims)(multi,
 					isl_dim_out, keep, total - keep);
 	multi = FN(MULTI(BASE),reset_space)(multi, space);
@@ -888,19 +598,21 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
 	__isl_take MULTI(BASE) *multi)
 {
 	isl_space *space;
-	int total, keep;
+	isl_size total, keep;
 
-	if (!multi)
-		return NULL;
+	total = FN(MULTI(BASE),dim)(multi, isl_dim_out);
+	if (total < 0)
+		return FN(MULTI(BASE),free)(multi);
 	if (!isl_space_range_is_wrapping(multi->space))
 		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
 			"range is not a product",
 			return FN(MULTI(BASE),free)(multi));
 
 	space = FN(MULTI(BASE),get_space)(multi);
-	total = isl_space_dim(space, isl_dim_out);
 	space = isl_space_range_factor_range(space);
 	keep = isl_space_dim(space, isl_dim_out);
+	if (keep < 0)
+		multi = FN(MULTI(BASE),free)(multi);
 	multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
 	multi = FN(MULTI(BASE),reset_space)(multi, space);
 
@@ -913,87 +625,26 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
 	__isl_take MULTI(BASE) *multi)
 {
 	isl_space *space;
-	int total, keep;
+	isl_size total, keep;
 
-	if (!multi)
-		return NULL;
+	total = FN(MULTI(BASE),dim)(multi, isl_dim_set);
+	if (total < 0)
+		return FN(MULTI(BASE),free)(multi);
 	if (!isl_space_is_wrapping(multi->space))
 		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
 			"not a product", return FN(MULTI(BASE),free)(multi));
 
 	space = FN(MULTI(BASE),get_space)(multi);
-	total = isl_space_dim(space, isl_dim_out);
 	space = isl_space_factor_range(space);
-	keep = isl_space_dim(space, isl_dim_out);
-	multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
+	keep = isl_space_dim(space, isl_dim_set);
+	if (keep < 0)
+		multi = FN(MULTI(BASE),free)(multi);
+	multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_set, 0, total - keep);
 	multi = FN(MULTI(BASE),reset_space)(multi, space);
 
 	return multi;
 }
 
-#ifndef NO_PRODUCT
-/* Given two MULTI(BASE)s A -> B and C -> D,
- * construct a MULTI(BASE) [A -> C] -> [B -> D].
- *
- * The parameters are assumed to have been aligned.
- *
- * If "multi1" and/or "multi2" has an explicit domain, then
- * intersect the domain of the result with these explicit domains.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
-	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
-{
-	int i;
-	EL *el;
-	isl_space *space;
-	MULTI(BASE) *res;
-	int in1, in2, out1, out2;
-
-	in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
-	in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
-	out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
-	out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
-	space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
-				  FN(MULTI(BASE),get_space)(multi2));
-	res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
-	space = isl_space_domain(space);
-
-	for (i = 0; i < out1; ++i) {
-		el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
-		el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
-		el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
-		res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
-	}
-
-	for (i = 0; i < out2; ++i) {
-		el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
-		el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
-		el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
-		res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
-	}
-
-	if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
-	    FN(MULTI(BASE),has_explicit_domain)(multi2))
-		res = FN(MULTI(BASE),intersect_explicit_domain_product)(res,
-								multi1, multi2);
-
-	isl_space_free(space);
-	FN(MULTI(BASE),free)(multi1);
-	FN(MULTI(BASE),free)(multi2);
-	return res;
-}
-
-/* Given two MULTI(BASE)s A -> B and C -> D,
- * construct a MULTI(BASE) [A -> C] -> [B -> D].
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
-	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
-{
-	return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
-					&FN(MULTI(BASE),product_aligned));
-}
-#endif
-
 __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
 	__isl_take MULTI(BASE) *multi)
 {
@@ -1044,15 +695,14 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
 	__isl_take MULTI(BASE) *multi2)
 {
 	MULTI(BASE) *res;
-	unsigned dim;
+	isl_size dim;
 
-	if (!multi1 || !multi2)
+	dim = FN(MULTI(BASE),size)(multi1);
+	if (dim < 0 || !multi2)
 		goto error;
 
-	dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
-	if (pos > dim)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
-			"index out of bounds", goto error);
+	if (FN(MULTI(BASE),check_range)(multi1, isl_dim_out, pos, 0) < 0)
+		goto error;
 
 	res = FN(MULTI(BASE),copy)(multi1);
 	res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos);
@@ -1068,80 +718,13 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
 	return NULL;
 }
 
-#ifndef NO_SPLICE
-/* Given two multi expressions, "multi1"
- *
- *	[A1 A2] -> [B1 B2]
- *
- * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
- * and "multi2"
- *
- *	[C] -> [D]
- *
- * return the multi expression
- *
- *	[A1 C A2] -> [B1 D B2]
- *
- * We first insert input dimensions to obtain
- *
- *	[A1 C A2] -> [B1 B2]
- *
- * and
- *
- *	[A1 C A2] -> [D]
- *
- * and then apply range_splice.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
-	__isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
-	__isl_take MULTI(BASE) *multi2)
-{
-	unsigned n_in1;
-	unsigned n_in2;
-
-	if (!multi1 || !multi2)
-		goto error;
-
-	n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
-	if (in_pos > n_in1)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
-			"index out of bounds", goto error);
-
-	n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
-
-	multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
-	multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
-						n_in1 - in_pos);
-	multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
-
-	return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
-error:
-	FN(MULTI(BASE),free)(multi1);
-	FN(MULTI(BASE),free)(multi2);
-	return NULL;
-}
-#endif
-
-/* Check that "multi1" and "multi2" live in the same space,
- * reporting an error if they do not.
- */
-static isl_stat FN(MULTI(BASE),check_equal_space)(
-	__isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
-{
-	isl_bool equal;
-
-	if (!multi1 || !multi2)
-		return isl_stat_error;
+#undef TYPE
+#define TYPE	MULTI(BASE)
 
-	equal = isl_space_is_equal(multi1->space, multi2->space);
-	if (equal < 0)
-		return isl_stat_error;
-	if (!equal)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
-			"spaces don't match", return isl_stat_error);
-
-	return isl_stat_ok;
-}
+static
+#include "isl_type_has_equal_space_bin_templ.c"
+static
+#include "isl_type_check_equal_space_templ.c"
 
 /* This function is currently only used from isl_aff.c
  */
@@ -1185,291 +768,57 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
 	return NULL;
 }
 
-/* Add "multi2" from "multi1" and return the result.
- *
- * The parameters of "multi1" and "multi2" are assumed to have been aligned.
- */
-static __isl_give MULTI(BASE) *FN(MULTI(BASE),add_aligned)(
-	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
-{
-	return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
-}
-
-/* Add "multi2" from "multi1" and return the result.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
-	__isl_take MULTI(BASE) *multi2)
-{
-	return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
-						&FN(MULTI(BASE),add_aligned));
-}
-
-/* Subtract "multi2" from "multi1" and return the result.
- *
- * The parameters of "multi1" and "multi2" are assumed to have been aligned.
- */
-static __isl_give MULTI(BASE) *FN(MULTI(BASE),sub_aligned)(
-	__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
-{
-	return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
-}
-
-/* Subtract "multi2" from "multi1" and return the result.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
-	__isl_take MULTI(BASE) *multi2)
-{
-	return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
-						&FN(MULTI(BASE),sub_aligned));
-}
-
-/* Multiply the elements of "multi" by "v" and return the result.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
-	__isl_take isl_val *v)
-{
-	int i;
-
-	if (!multi || !v)
-		goto error;
-
-	if (isl_val_is_one(v)) {
-		isl_val_free(v);
-		return multi;
-	}
-
-	if (!isl_val_is_rat(v))
-		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational factor", goto error);
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	for (i = 0; i < multi->n; ++i) {
-		multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
-						isl_val_copy(v));
-		if (!multi->u.p[i])
-			goto error;
-	}
-
-	isl_val_free(v);
-	return multi;
-error:
-	isl_val_free(v);
-	return FN(MULTI(BASE),free)(multi);
-}
-
-/* Divide the elements of "multi" by "v" and return the result.
+/* Only used on some multi-expressions.
  */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
-	__isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
-{
-	int i;
-
-	if (!multi || !v)
-		goto error;
-
-	if (isl_val_is_one(v)) {
-		isl_val_free(v);
-		return multi;
-	}
-
-	if (!isl_val_is_rat(v))
-		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational factor", goto error);
-	if (isl_val_is_zero(v))
-		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"cannot scale down by zero", goto error);
+static isl_bool FN(MULTI(BASE),any)(__isl_keep MULTI(BASE) *multi,
+	isl_bool (*test)(__isl_keep EL *)) __attribute__ ((unused));
 
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	for (i = 0; i < multi->n; ++i) {
-		multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
-						    isl_val_copy(v));
-		if (!multi->u.p[i])
-			goto error;
-	}
-
-	isl_val_free(v);
-	return multi;
-error:
-	isl_val_free(v);
-	return FN(MULTI(BASE),free)(multi);
-}
-
-/* Multiply the elements of "multi" by the corresponding element of "mv"
- * and return the result.
+/* Does "test" succeed on any base expression of "multi"?
  */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
-	__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+static isl_bool FN(MULTI(BASE),any)(__isl_keep MULTI(BASE) *multi,
+	isl_bool (*test)(__isl_keep EL *))
 {
+	isl_size n;
 	int i;
 
-	if (!multi || !mv)
-		goto error;
-
-	if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
-					mv->space, isl_dim_set))
-		isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
-			"spaces don't match", goto error);
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		goto error;
-
-	for (i = 0; i < multi->n; ++i) {
-		isl_val *v;
-
-		v = isl_multi_val_get_val(mv, i);
-		multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
-		if (!multi->u.p[i])
-			goto error;
-	}
-
-	isl_multi_val_free(mv);
-	return multi;
-error:
-	isl_multi_val_free(mv);
-	return FN(MULTI(BASE),free)(multi);
-}
-
-/* Divide the elements of "multi" by the corresponding element of "mv"
- * and return the result.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
-	__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
-{
-	int i;
-
-	if (!multi || !mv)
-		goto error;
-
-	if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
-					mv->space, isl_dim_set))
-		isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
-			"spaces don't match", goto error);
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	for (i = 0; i < multi->n; ++i) {
-		isl_val *v;
+	n = FN(MULTI(BASE),size)(multi);
+	if (n < 0)
+		return isl_bool_error;
 
-		v = isl_multi_val_get_val(mv, i);
-		multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
-		if (!multi->u.p[i])
-			goto error;
+	for (i = 0; i < n; ++i) {
+		isl_bool any = test(multi->u.p[i]);
+		if (any < 0 || any)
+			return any;
 	}
 
-	isl_multi_val_free(mv);
-	return multi;
-error:
-	isl_multi_val_free(mv);
-	return FN(MULTI(BASE),free)(multi);
+	return isl_bool_false;
 }
 
-/* Compute the residues of the elements of "multi" modulo
- * the corresponding element of "mv" and return the result.
+/* Only used on some multi-expressions.
  */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
-	__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
-{
-	int i;
-
-	if (!multi || !mv)
-		goto error;
-
-	if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
-					mv->space, isl_dim_set))
-		isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
-			"spaces don't match", goto error);
+static isl_bool FN(MULTI(BASE),every)(__isl_keep MULTI(BASE) *multi,
+	isl_bool (*test)(__isl_keep EL *)) __attribute__ ((unused));
 
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		goto error;
-
-	for (i = 0; i < multi->n; ++i) {
-		isl_val *v;
-
-		v = isl_multi_val_get_val(mv, i);
-		multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
-		if (!multi->u.p[i])
-			goto error;
-	}
-
-	isl_multi_val_free(mv);
-	return multi;
-error:
-	isl_multi_val_free(mv);
-	return FN(MULTI(BASE),free)(multi);
-}
-
-#ifndef NO_MOVE_DIMS
-/* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
- * to dimensions of "dst_type" at "dst_pos".
- *
- * We only support moving input dimensions to parameters and vice versa.
+/* Does "test" succeed on every base expression of "multi"?
  */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
-	enum isl_dim_type dst_type, unsigned dst_pos,
-	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+static isl_bool FN(MULTI(BASE),every)(__isl_keep MULTI(BASE) *multi,
+	isl_bool (*test)(__isl_keep EL *))
 {
+	isl_size n;
 	int i;
 
-	if (!multi)
-		return NULL;
-
-	if (n == 0 &&
-	    !isl_space_is_named_or_nested(multi->space, src_type) &&
-	    !isl_space_is_named_or_nested(multi->space, dst_type))
-		return multi;
-
-	if (dst_type == isl_dim_out || src_type == isl_dim_out)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
-			"cannot move output/set dimension",
-			return FN(MULTI(BASE),free)(multi));
-	if (dst_type == isl_dim_div || src_type == isl_dim_div)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
-			"cannot move divs",
-			return FN(MULTI(BASE),free)(multi));
-	if (src_pos + n > isl_space_dim(multi->space, src_type))
-		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
-			"range out of bounds",
-			return FN(MULTI(BASE),free)(multi));
-	if (dst_type == src_type)
-		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
-			"moving dims within the same type not supported",
-			return FN(MULTI(BASE),free)(multi));
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
-						src_type, src_pos, n);
-	if (!multi->space)
-		return FN(MULTI(BASE),free)(multi);
-	if (FN(MULTI(BASE),has_explicit_domain)(multi))
-		multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
-				dst_type, dst_pos, src_type, src_pos, n);
-	if (!multi)
-		return NULL;
+	n = FN(MULTI(BASE),size)(multi);
+	if (n < 0)
+		return isl_bool_error;
 
-	for (i = 0; i < multi->n; ++i) {
-		multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
-						dst_type, dst_pos,
-						src_type, src_pos, n);
-		if (!multi->u.p[i])
-			return FN(MULTI(BASE),free)(multi);
+	for (i = 0; i < n; ++i) {
+		isl_bool every = test(multi->u.p[i]);
+		if (every < 0 || !every)
+			return every;
 	}
 
-	return multi;
+	return isl_bool_true;
 }
-#endif
 
 /* Convert a multiple expression defined over a parameter domain
  * into one that is defined over a zero-dimensional set.
@@ -1524,76 +873,3 @@ isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
 
 	return isl_bool_true;
 }
-
-/* Does "multi" involve any NaNs?
- */
-isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
-{
-	int i;
-
-	if (!multi)
-		return isl_bool_error;
-	if (multi->n == 0)
-		return isl_bool_false;
-
-	for (i = 0; i < multi->n; ++i) {
-		isl_bool has_nan = FN(EL,involves_nan)(multi->u.p[i]);
-		if (has_nan < 0 || has_nan)
-			return has_nan;
-	}
-
-	return isl_bool_false;
-}
-
-#ifndef NO_DOMAIN
-/* Return the shared domain of the elements of "multi".
- *
- * If "multi" has an explicit domain, then return this domain.
- */
-__isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
-{
-	int i;
-	isl_set *dom;
-
-	if (!multi)
-		return NULL;
-
-	if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
-		dom = FN(MULTI(BASE),get_explicit_domain)(multi);
-		FN(MULTI(BASE),free)(multi);
-		return dom;
-	}
-
-	dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
-	for (i = 0; i < multi->n; ++i) {
-		isl_set *dom_i;
-
-		dom_i = FN(EL,domain)(FN(FN(MULTI(BASE),get),BASE)(multi, i));
-		dom = isl_set_intersect(dom, dom_i);
-	}
-
-	FN(MULTI(BASE),free)(multi);
-	return dom;
-}
-#endif
-
-#ifndef NO_NEG
-/* Return the opposite of "multi".
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
-{
-	int i;
-
-	multi = FN(MULTI(BASE),cow)(multi);
-	if (!multi)
-		return NULL;
-
-	for (i = 0; i < multi->n; ++i) {
-		multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
-		if (!multi->u.p[i])
-			return FN(MULTI(BASE),free)(multi);
-	}
-
-	return multi;
-}
-#endif

diff  --git a/polly/lib/External/isl/isl_multi_tuple_id_templ.c b/polly/lib/External/isl/isl_multi_tuple_id_templ.c
new file mode 100644
index 000000000000..03f74d479176
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_tuple_id_templ.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011      Sven Verdoolaege
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/space.h>
+
+#include <isl_multi_macro.h>
+
+const char *FN(MULTI(BASE),get_tuple_name)(__isl_keep MULTI(BASE) *multi,
+	enum isl_dim_type type)
+{
+	return multi ? isl_space_get_tuple_name(multi->space, type) : NULL;
+}
+
+/* Does the specified tuple have an id?
+ */
+isl_bool FN(MULTI(BASE),has_tuple_id)(__isl_keep MULTI(BASE) *multi,
+	enum isl_dim_type type)
+{
+	if (!multi)
+		return isl_bool_error;
+	return isl_space_has_tuple_id(multi->space, type);
+}
+
+/* Return the id of the specified tuple.
+ */
+__isl_give isl_id *FN(MULTI(BASE),get_tuple_id)(__isl_keep MULTI(BASE) *multi,
+	enum isl_dim_type type)
+{
+	return multi ? isl_space_get_tuple_id(multi->space, type) : NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
+	__isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
+	const char *s)
+{
+	isl_space *space;
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	space = FN(MULTI(BASE),get_space)(multi);
+	space = isl_space_set_tuple_name(space, type, s);
+
+	return FN(MULTI(BASE),reset_space)(multi, space);
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_id)(
+	__isl_take MULTI(BASE) *multi, enum isl_dim_type type,
+	__isl_take isl_id *id)
+{
+	isl_space *space;
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		goto error;
+
+	space = FN(MULTI(BASE),get_space)(multi);
+	space = isl_space_set_tuple_id(space, type, id);
+
+	return FN(MULTI(BASE),reset_space)(multi, space);
+error:
+	isl_id_free(id);
+	return NULL;
+}
+
+/* Drop the id on the specified tuple.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_tuple_id)(
+	__isl_take MULTI(BASE) *multi, enum isl_dim_type type)
+{
+	isl_space *space;
+
+	if (!multi)
+		return NULL;
+	if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
+		return multi;
+
+	multi = FN(MULTI(BASE),cow)(multi);
+	if (!multi)
+		return NULL;
+
+	space = FN(MULTI(BASE),get_space)(multi);
+	space = isl_space_reset_tuple_id(space, type);
+
+	return FN(MULTI(BASE),reset_space)(multi, space);
+}

diff  --git a/polly/lib/External/isl/isl_multi_zero_templ.c b/polly/lib/External/isl/isl_multi_zero_templ.c
new file mode 100644
index 000000000000..2dbc5820727f
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_zero_templ.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012      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/space.h>
+#include <isl/local_space.h>
+
+#include <isl_multi_macro.h>
+
+/* Construct a multi expression in the given space with value zero in
+ * each of the output dimensions.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
+{
+	isl_size n;
+	MULTI(BASE) *multi;
+
+	n = isl_space_dim(space , isl_dim_out);
+	if (n < 0)
+		goto error;
+
+	multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
+
+	if (!n)
+		isl_space_free(space);
+	else {
+		int i;
+		isl_local_space *ls;
+		EL *el;
+
+		space = isl_space_domain(space);
+		ls = isl_local_space_from_space(space);
+		el = FN(EL,zero_on_domain)(ls);
+
+		for (i = 0; i < n; ++i)
+			multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
+							    FN(EL,copy)(el));
+
+		FN(EL,free)(el);
+	}
+
+	return multi;
+error:
+	isl_space_free(space);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_options.c b/polly/lib/External/isl/isl_options.c
index ea8fe78077b6..f9d253b66cb6 100644
--- a/polly/lib/External/isl/isl_options.c
+++ b/polly/lib/External/isl/isl_options.c
@@ -167,7 +167,7 @@ ISL_ARG_BOOL(struct isl_options, schedule_separate_components, 0,
 	"schedule-separate-components", 1,
 	"separate components in dependence graph")
 ISL_ARG_BOOL(struct isl_options, schedule_whole_component, 0,
-	"schedule-whole-component", 1,
+	"schedule-whole-component", 0,
 	"try and compute schedule for entire component first")
 ISL_ARG_CHOICE(struct isl_options, schedule_algorithm, 0,
 	"schedule-algorithm", isl_schedule_algorithm_choice,

diff  --git a/polly/lib/External/isl/isl_output.c b/polly/lib/External/isl/isl_output.c
index 338077bc14ef..866932ed8839 100644
--- a/polly/lib/External/isl/isl_output.c
+++ b/polly/lib/External/isl/isl_output.c
@@ -2,6 +2,7 @@
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  * Copyright 2010      INRIA Saclay
  * Copyright 2012-2013 Ecole Normale Superieure
+ * Copyright 2019      Cerebras Systems
  *
  * Use of this software is governed by the MIT license
  *
@@ -9,7 +10,8 @@
  * 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
+ * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
  */
 
 #include <stdlib.h>
@@ -26,8 +28,10 @@
 #include <isl/union_set.h>
 #include <isl/union_map.h>
 #include <isl/constraint.h>
+#include <isl_local.h>
 #include <isl_local_space_private.h>
 #include <isl_aff_private.h>
+#include <isl_id_private.h>
 #include <isl_val_private.h>
 #include <isl_constraint_private.h>
 #include <isl/ast_build.h>
@@ -60,11 +64,14 @@ static __isl_give isl_printer *print_constraint_polylib(
 	struct isl_basic_map *bmap, int ineq, int n, __isl_take isl_printer *p)
 {
 	int i;
-	unsigned n_in = isl_basic_map_dim(bmap, isl_dim_in);
-	unsigned n_out = isl_basic_map_dim(bmap, isl_dim_out);
-	unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	isl_size n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	isl_size n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	isl_size nparam = isl_basic_map_dim(bmap, isl_dim_param);
 	isl_int *c = ineq ? bmap->ineq[n] : bmap->eq[n];
 
+	if (n_in < 0 || n_out < 0 || nparam < 0)
+		return isl_printer_free(p);
+
 	p = isl_printer_start_line(p);
 	p = isl_printer_print_int(p, ineq);
 	for (i = 0; i < n_out; ++i) {
@@ -113,24 +120,32 @@ static __isl_give isl_printer *bset_print_constraints_polylib(
 static __isl_give isl_printer *isl_basic_map_print_polylib(
 	__isl_keep isl_basic_map *bmap, __isl_take isl_printer *p, int ext)
 {
-	unsigned total = isl_basic_map_total_dim(bmap);
+	isl_size total;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_printer_free(p);
 	p = isl_printer_start_line(p);
 	p = isl_printer_print_int(p, bmap->n_eq + bmap->n_ineq);
 	p = isl_printer_print_str(p, " ");
 	p = isl_printer_print_int(p, 1 + total + 1);
 	if (ext) {
+		isl_size n_in = isl_basic_map_dim(bmap, isl_dim_in);
+		isl_size n_out = isl_basic_map_dim(bmap, isl_dim_out);
+		isl_size n_div = isl_basic_map_dim(bmap, isl_dim_div);
+		isl_size nparam = isl_basic_map_dim(bmap, isl_dim_param);
+
+		if (n_in < 0 || n_out < 0 || n_div < 0 || nparam < 0)
+			return isl_printer_free(p);
+
 		p = isl_printer_print_str(p, " ");
-		p = isl_printer_print_int(p,
-				    isl_basic_map_dim(bmap, isl_dim_out));
+		p = isl_printer_print_int(p, n_out);
 		p = isl_printer_print_str(p, " ");
-		p = isl_printer_print_int(p,
-				    isl_basic_map_dim(bmap, isl_dim_in));
+		p = isl_printer_print_int(p, n_in);
 		p = isl_printer_print_str(p, " ");
-		p = isl_printer_print_int(p,
-				    isl_basic_map_dim(bmap, isl_dim_div));
+		p = isl_printer_print_int(p, n_div);
 		p = isl_printer_print_str(p, " ");
-		p = isl_printer_print_int(p,
-				    isl_basic_map_dim(bmap, isl_dim_param));
+		p = isl_printer_print_int(p, nparam);
 	}
 	p = isl_printer_end_line(p);
 	return print_constraints_polylib(bmap, p);
@@ -164,17 +179,20 @@ static __isl_give isl_printer *isl_set_print_polylib(__isl_keep isl_set *set,
 	return isl_map_print_polylib(set_to_map(set), p, ext);
 }
 
-static int count_same_name(__isl_keep isl_space *dim,
+static isl_size count_same_name(__isl_keep isl_space *space,
 	enum isl_dim_type type, unsigned pos, const char *name)
 {
 	enum isl_dim_type t;
-	unsigned p, s;
+	int p;
+	isl_size s;
 	int count = 0;
 
 	for (t = isl_dim_param; t <= type && t <= isl_dim_out; ++t) {
-		s = t == type ? pos : isl_space_dim(dim, t);
+		s = t == type ? pos : isl_space_dim(space, t);
+		if (s < 0)
+			return isl_size_error;
 		for (p = 0; p < s; ++p) {
-			const char *n = isl_space_get_dim_name(dim, t, p);
+			const char *n = isl_space_get_dim_name(space, t, p);
 			if (n && !strcmp(n, name))
 				count++;
 		}
@@ -191,7 +209,7 @@ static __isl_give isl_printer *print_name(__isl_keep isl_space *space,
 {
 	const char *name;
 	char buffer[20];
-	int primes;
+	isl_size primes;
 
 	name = type == isl_dim_div ? NULL
 				   : isl_space_get_dim_name(space, type, pos);
@@ -211,34 +229,39 @@ static __isl_give isl_printer *print_name(__isl_keep isl_space *space,
 	}
 	primes = count_same_name(space, name == buffer ? isl_dim_div : type,
 				 pos, name);
+	if (primes < 0)
+		return isl_printer_free(p);
 	p = isl_printer_print_str(p, name);
 	while (primes-- > 0)
 		p = isl_printer_print_str(p, "'");
 	return p;
 }
 
-static enum isl_dim_type pos2type(__isl_keep isl_space *dim, unsigned *pos)
+static isl_stat pos2type(__isl_keep isl_space *space,
+	enum isl_dim_type *type, unsigned *pos)
 {
-	enum isl_dim_type type;
-	unsigned n_in = isl_space_dim(dim, isl_dim_in);
-	unsigned n_out = isl_space_dim(dim, isl_dim_out);
-	unsigned nparam = isl_space_dim(dim, isl_dim_param);
+	isl_size n_in = isl_space_dim(space, isl_dim_in);
+	isl_size n_out = isl_space_dim(space, isl_dim_out);
+	isl_size nparam = isl_space_dim(space, isl_dim_param);
+
+	if (n_in < 0 || n_out < 0 || nparam < 0)
+		return isl_stat_error;
 
 	if (*pos < 1 + nparam) {
-		type = isl_dim_param;
+		*type = isl_dim_param;
 		*pos -= 1;
 	} else if (*pos < 1 + nparam + n_in) {
-		type = isl_dim_in;
+		*type = isl_dim_in;
 		*pos -= 1 + nparam;
 	} else if (*pos < 1 + nparam + n_in + n_out) {
-		type = isl_dim_out;
+		*type = isl_dim_out;
 		*pos -= 1 + nparam + n_in;
 	} else {
-		type = isl_dim_div;
+		*type = isl_dim_div;
 		*pos -= 1 + nparam + n_in + n_out;
 	}
 
-	return type;
+	return isl_stat_ok;
 }
 
 /* Can the div expression of the integer division at position "row" of "div"
@@ -255,7 +278,7 @@ static isl_bool can_print_div_expr(__isl_keep isl_printer *p,
 		return isl_bool_false;
 	if (!div)
 		return isl_bool_false;
-	return !isl_int_is_zero(div->row[pos][0]);
+	return isl_bool_not(isl_local_div_is_marked_unknown(div, pos));
 }
 
 static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
@@ -274,7 +297,8 @@ static __isl_give isl_printer *print_term(__isl_keep isl_space *space,
 	if (pos == 0)
 		return isl_printer_print_isl_int(p, c);
 
-	type = pos2type(space, &pos);
+	if (pos2type(space, &type, &pos) < 0)
+		return isl_printer_free(p);
 	print_div_def = type == isl_dim_div && can_print_div_expr(p, div, pos);
 
 	if (isl_int_is_one(c))
@@ -329,28 +353,33 @@ static __isl_give isl_printer *print_affine_of_len(__isl_keep isl_space *dim,
 static __isl_give isl_printer *print_affine(__isl_take isl_printer *p,
 	__isl_keep isl_space *space, __isl_keep isl_mat *div, isl_int *c)
 {
-	unsigned n_div;
+	isl_size n_div, total;
 	unsigned len;
 
-	if (!space || !div)
-		return isl_printer_free(p);
+	total = isl_space_dim(space, isl_dim_all);
 	n_div = isl_mat_rows(div);
-	len = 1 + isl_space_dim(space, isl_dim_all) + n_div;
+	if (total < 0 || n_div < 0)
+		return isl_printer_free(p);
+	len = 1 + total + n_div;
 	return print_affine_of_len(space, div, p, c, len);
 }
 
-/* offset is the offset of local_dim inside data->type of data->space.
+/* offset is the offset of local_space inside data->type of data->space.
  */
 static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p,
-	__isl_keep isl_space *local_dim, enum isl_dim_type local_type,
+	__isl_keep isl_space *local_space, enum isl_dim_type local_type,
 	struct isl_print_space_data *data, int offset)
 {
 	int i;
+	isl_size dim;
 
-	if (data->space != local_dim && local_type == isl_dim_out)
-		offset += local_dim->n_in;
+	if (data->space != local_space && local_type == isl_dim_out)
+		offset += local_space->n_in;
 
-	for (i = 0; i < isl_space_dim(local_dim, local_type); ++i) {
+	dim = isl_space_dim(local_space, local_type);
+	if (dim < 0)
+		return isl_printer_free(p);
+	for (i = 0; i < dim; ++i) {
 		if (i)
 			p = isl_printer_print_str(p, ", ");
 		if (data->print_dim)
@@ -375,13 +404,16 @@ static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
 	struct isl_print_space_data *data, int offset);
 
 static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
-	__isl_keep isl_space *local_dim, enum isl_dim_type local_type,
+	__isl_keep isl_space *local_space, enum isl_dim_type local_type,
 	struct isl_print_space_data *data, int offset)
 {
 	const char *name = NULL;
-	unsigned n = isl_space_dim(local_dim, local_type);
+	isl_size n = isl_space_dim(local_space, local_type);
+
+	if (n < 0)
+		return isl_printer_free(p);
 	if ((local_type == isl_dim_in || local_type == isl_dim_out)) {
-		name = isl_space_get_tuple_name(local_dim, local_type);
+		name = isl_space_get_tuple_name(local_space, local_type);
 		if (name) {
 			if (data->latex)
 				p = isl_printer_print_str(p, "\\mathrm{");
@@ -393,14 +425,14 @@ static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
 	if (!data->latex || n != 1 || name)
 		p = isl_printer_print_str(p, s_open_list[data->latex]);
 	if ((local_type == isl_dim_in || local_type == isl_dim_out) &&
-	    local_dim->nested[local_type - isl_dim_in]) {
-		if (data->space != local_dim && local_type == isl_dim_out)
-			offset += local_dim->n_in;
+	    local_space->nested[local_type - isl_dim_in]) {
+		if (data->space != local_space && local_type == isl_dim_out)
+			offset += local_space->n_in;
 		p = print_nested_map_dim(p,
-				local_dim->nested[local_type - isl_dim_in],
+				local_space->nested[local_type - isl_dim_in],
 				data, offset);
 	} else
-		p = print_nested_var_list(p, local_dim, local_type, data,
+		p = print_nested_var_list(p, local_space, local_type, data,
 					  offset);
 	if (!data->latex || n != 1 || name)
 		p = isl_printer_print_str(p, s_close_list[data->latex]);
@@ -446,15 +478,19 @@ __isl_give isl_printer *isl_print_space(__isl_keep isl_space *space,
 	return p;
 }
 
-static __isl_give isl_printer *print_omega_parameters(__isl_keep isl_space *dim,
-	__isl_take isl_printer *p)
+static __isl_give isl_printer *print_omega_parameters(
+	__isl_keep isl_space *space, __isl_take isl_printer *p)
 {
-	if (isl_space_dim(dim, isl_dim_param) == 0)
+	isl_size nparam = isl_space_dim(space, isl_dim_param);
+
+	if (nparam < 0)
+		return isl_printer_free(p);
+	if (nparam == 0)
 		return p;
 
 	p = isl_printer_start_line(p);
 	p = isl_printer_print_str(p, "symbolic ");
-	p = print_var_list(p, dim, isl_dim_param);
+	p = print_var_list(p, space, isl_dim_param);
 	p = isl_printer_print_str(p, ";");
 	p = isl_printer_end_line(p);
 	return p;
@@ -466,26 +502,31 @@ static __isl_give isl_printer *print_omega_parameters(__isl_keep isl_space *dim,
  * If the next constraint is a div constraint, then it is ignored
  * since div constraints are not printed.
  */
-static int next_is_opposite(__isl_keep isl_basic_map *bmap, int i, int last)
+static isl_bool next_is_opposite(__isl_keep isl_basic_map *bmap, int i,
+	int last)
 {
-	unsigned total = isl_basic_map_total_dim(bmap);
+	int r;
+	isl_size total = isl_basic_map_dim(bmap, isl_dim_all);
 	unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div);
 
+	if (total < 0)
+		return isl_bool_error;
 	if (i + 1 >= bmap->n_ineq)
-		return 0;
+		return isl_bool_false;
 	if (isl_seq_last_non_zero(bmap->ineq[i + 1], 1 + total) != last)
-		return 0;
+		return isl_bool_false;
 	if (last >= o_div) {
 		isl_bool is_div;
 		is_div = isl_basic_map_is_div_constraint(bmap,
 					    bmap->ineq[i + 1], last - o_div);
 		if (is_div < 0)
-			return -1;
+			return isl_bool_error;
 		if (is_div)
-			return 0;
+			return isl_bool_false;
 	}
-	return isl_int_abs_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]) &&
-		!isl_int_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]);
+	r = isl_int_abs_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]) &&
+	    !isl_int_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]);
+	return isl_bool_ok(r);
 }
 
 /* Return a string representation of the operator used when
@@ -584,40 +625,41 @@ static __isl_give isl_printer *print_mod(__isl_take isl_printer *p,
 	return p;
 }
 
-/* Can the equality constraints "c" be printed as a modulo constraint?
- * In particular, is of the form
+/* Given an equality constraint with a non-zero coefficient "c"
+ * in position "pos", is this term of the form
  *
- *	f - a m floor(g/m) = 0,
+ *	a m floor(g/m),
  *
- * with c = -a m the coefficient at position "pos"?
+ * with c = a m?
  * Return the position of the corresponding integer division if so.
  * Return the number of integer divisions if not.
- * Return -1 on error.
+ * Return isl_size_error on error.
  *
  * Modulo constraints are currently not printed in C format.
  * Other than that, "pos" needs to correspond to an integer division
  * with explicit representation and "c" needs to be a multiple
  * of the denominator of the integer division.
  */
-static int print_as_modulo_pos(__isl_keep isl_printer *p,
+static isl_size print_as_modulo_pos(__isl_keep isl_printer *p,
 	__isl_keep isl_space *space, __isl_keep isl_mat *div, unsigned pos,
 	isl_int c)
 {
 	isl_bool can_print;
-	unsigned n_div;
+	isl_size n_div;
 	enum isl_dim_type type;
 
-	if (!p || !space)
-		return -1;
 	n_div = isl_mat_rows(div);
+	if (!p || !space || n_div < 0)
+		return isl_size_error;
 	if (p->output_format == ISL_FORMAT_C)
 		return n_div;
-	type = pos2type(space, &pos);
+	if (pos2type(space, &type, &pos) < 0)
+		return isl_size_error;
 	if (type != isl_dim_div)
 		return n_div;
 	can_print = can_print_div_expr(p, div, pos);
 	if (can_print < 0)
-		return -1;
+		return isl_size_error;
 	if (!can_print)
 		return n_div;
 	if (!isl_int_is_divisible_by(c, div->row[pos][0]))
@@ -679,12 +721,12 @@ static __isl_give isl_printer *print_eq_constraint(__isl_take isl_printer *p,
 	__isl_keep isl_space *space, __isl_keep isl_mat *div, isl_int *c,
 	int last, int latex)
 {
-	unsigned n_div;
-	int div_pos;
+	isl_size n_div;
+	isl_size div_pos;
 
 	n_div = isl_mat_rows(div);
 	div_pos = print_as_modulo_pos(p, space, div, last, c[last]);
-	if (div_pos < 0)
+	if (n_div < 0 || div_pos < 0)
 		return isl_printer_free(p);
 	if (div_pos < n_div)
 		return print_eq_mod_constraint(p, space, div, div_pos,
@@ -739,13 +781,13 @@ static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
 	int i;
 	isl_vec *c = NULL;
 	int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
-	unsigned total = isl_basic_map_total_dim(bmap);
+	isl_size total = isl_basic_map_dim(bmap, isl_dim_all);
 	unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div);
 	int first = 1;
 	int dump;
 
-	if (!p)
-		return NULL;
+	if (total < 0 || !p)
+		return isl_printer_free(p);
 	bmap = isl_basic_map_copy(bmap);
 	dump = p->dump;
 	if (!dump)
@@ -775,6 +817,7 @@ static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
 		first = 0;
 	}
 	for (i = 0; i < bmap->n_ineq; ++i) {
+		isl_bool combine;
 		int l = isl_seq_last_non_zero(bmap->ineq[i], 1 + total);
 		int strict;
 		int s;
@@ -801,7 +844,10 @@ static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
 			isl_seq_neg(c->el, bmap->ineq[i], 1 + total);
 		if (strict)
 			isl_int_set_si(c->el[0], 0);
-		if (!dump && next_is_opposite(bmap, i, l)) {
+		combine = dump ? isl_bool_false : next_is_opposite(bmap, i, l);
+		if (combine < 0)
+			goto error;
+		if (combine) {
 			op = constraint_op(-s, strict, latex);
 			p = print_half_constraint(p, space, div, c->el, l,
 						op, latex);
@@ -854,12 +900,11 @@ static __isl_give isl_printer *print_div_list(__isl_take isl_printer *p,
 {
 	int i;
 	int first = 1;
-	unsigned n_div;
-
-	if (!p || !space || !div)
-		return isl_printer_free(p);
+	isl_size n_div;
 
 	n_div = isl_mat_rows(div);
+	if (!p || !space || n_div < 0)
+		return isl_printer_free(p);
 
 	for (i = 0; i < n_div; ++i) {
 		if (!print_defined_divs && can_print_div_expr(p, div, i))
@@ -885,11 +930,12 @@ static __isl_give isl_printer *print_div_list(__isl_take isl_printer *p,
  */
 static isl_bool need_exists(__isl_keep isl_printer *p, __isl_keep isl_mat *div)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!p || !div)
-		return isl_bool_error;
 	n = isl_mat_rows(div);
+	if (!p || n < 0)
+		return isl_bool_error;
 	if (n == 0)
 		return isl_bool_false;
 	if (p->dump)
@@ -927,12 +973,13 @@ static __isl_give isl_printer *open_exists(__isl_take isl_printer *p,
  */
 static __isl_give isl_mat *mark_all_unknown(__isl_take isl_mat *div)
 {
-	int i, n_div;
-
-	if (!div)
-		return NULL;
+	int i;
+	isl_size n_div;
 
 	n_div = isl_mat_rows(div);
+	if (n_div < 0)
+		return isl_mat_free(div);
+
 	for (i = 0; i < n_div; ++i)
 		div = isl_mat_set_element_si(div, i, 0, 0);
 	return div;
@@ -1042,9 +1089,12 @@ static __isl_give isl_printer *isl_set_print_omega(__isl_keep isl_set *set,
 static __isl_give isl_printer *print_param_tuple(__isl_take isl_printer *p,
 	__isl_keep isl_space *space, struct isl_print_space_data *data)
 {
-	if (!p || !space)
+	isl_size nparam;
+
+	nparam = isl_space_dim(space, isl_dim_param);
+	if (!p || nparam < 0)
 		return isl_printer_free(p);
-	if (isl_space_dim(space, isl_dim_param) == 0)
+	if (nparam == 0)
 		return p;
 
 	p = print_tuple(space, p, isl_dim_param, data);
@@ -1212,18 +1262,20 @@ static void free_split(__isl_take struct isl_aff_split *split, int n)
 static __isl_give isl_basic_map *get_aff(__isl_take isl_basic_map *bmap)
 {
 	int i, j;
-	unsigned nparam, n_in, n_out, total;
+	isl_size nparam, n_in, n_out, total;
 
 	bmap = isl_basic_map_cow(bmap);
 	if (!bmap)
 		return NULL;
-	if (isl_basic_map_free_inequality(bmap, bmap->n_ineq) < 0)
-		goto error;
+	bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
 
 	nparam = isl_basic_map_dim(bmap, isl_dim_param);
 	n_in = isl_basic_map_dim(bmap, isl_dim_in);
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
 	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (n_in < 0 || n_out < 0 || nparam < 0 || total < 0)
+		return isl_basic_map_free(bmap);
+
 	for (i = bmap->n_eq - 1; i >= 0; --i) {
 		j = isl_seq_last_non_zero(bmap->eq[i] + 1, total);
 		if (j >= nparam && j < nparam + n_in + n_out &&
@@ -1255,20 +1307,19 @@ static __isl_give isl_basic_map *drop_aff(__isl_take isl_basic_map *bmap,
 	__isl_keep isl_basic_map *aff)
 {
 	int i, j;
-	unsigned total;
+	isl_size v_div;
 
-	if (!bmap || !aff)
+	v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	if (v_div < 0 || !aff)
 		goto error;
 
-	total = isl_space_dim(bmap->dim, isl_dim_all);
-
 	for (i = bmap->n_eq - 1; i >= 0; --i) {
-		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total,
+		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + v_div,
 					    bmap->n_div) != -1)
 			continue;
 		for (j = 0; j < aff->n_eq; ++j) {
-			if (!isl_seq_eq(bmap->eq[i], aff->eq[j], 1 + total) &&
-			    !isl_seq_is_neg(bmap->eq[i], aff->eq[j], 1 + total))
+			if (!isl_seq_eq(bmap->eq[i], aff->eq[j], 1 + v_div) &&
+			    !isl_seq_is_neg(bmap->eq[i], aff->eq[j], 1 + v_div))
 				continue;
 			if (isl_basic_map_drop_equality(bmap, i) < 0)
 				goto error;
@@ -1333,13 +1384,13 @@ static int defining_equality(__isl_keep isl_basic_map *eq,
 	__isl_keep isl_space *dim, enum isl_dim_type type, int pos)
 {
 	int i;
-	unsigned total;
+	isl_size total;
 
-	if (!eq)
+	total = isl_basic_map_dim(eq, isl_dim_all);
+	if (total < 0)
 		return -1;
 
 	pos += isl_space_offset(dim, type);
-	total = isl_basic_map_total_dim(eq);
 
 	for (i = 0; i < eq->n_eq; ++i) {
 		if (isl_seq_last_non_zero(eq->eq[i] + 1, total) != pos)
@@ -1684,25 +1735,33 @@ __isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,
 	return NULL;
 }
 
-static int upoly_rec_n_non_zero(__isl_keep struct isl_upoly_rec *rec)
+static isl_size poly_rec_n_non_zero(__isl_keep isl_poly_rec *rec)
 {
 	int i;
 	int n;
 
-	for (i = 0, n = 0; i < rec->n; ++i)
-		if (!isl_upoly_is_zero(rec->p[i]))
+	if (!rec)
+		return isl_size_error;
+
+	for (i = 0, n = 0; i < rec->n; ++i) {
+		isl_bool is_zero = isl_poly_is_zero(rec->p[i]);
+
+		if (is_zero < 0)
+			return isl_size_error;
+		if (!is_zero)
 			++n;
+	}
 
 	return n;
 }
 
-static __isl_give isl_printer *upoly_print_cst(__isl_keep struct isl_upoly *up,
+static __isl_give isl_printer *poly_print_cst(__isl_keep isl_poly *poly,
 	__isl_take isl_printer *p, int first)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 	int neg;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
 		goto error;
 	neg = !first && isl_int_is_neg(cst->n);
@@ -1729,15 +1788,17 @@ static __isl_give isl_printer *upoly_print_cst(__isl_keep struct isl_upoly *up,
 }
 
 static __isl_give isl_printer *print_base(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim, __isl_keep isl_mat *div, int var)
+	__isl_keep isl_space *space, __isl_keep isl_mat *div, int var)
 {
-	unsigned total;
+	isl_size total;
 
-	total = isl_space_dim(dim, isl_dim_all);
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0)
+		return isl_printer_free(p);
 	if (var < total)
-		p = print_term(dim, NULL, dim->ctx->one, 1 + var, p, 0);
+		p = print_term(space, NULL, space->ctx->one, 1 + var, p, 0);
 	else
-		p = print_div(dim, div, var - total, p);
+		p = print_div(space, div, var - total, p);
 	return p;
 }
 
@@ -1760,55 +1821,63 @@ static __isl_give isl_printer *print_pow(__isl_take isl_printer *p,
 	return p;
 }
 
-/* Print the polynomial "up" defined over the domain space "space" and
+/* Print the polynomial "poly" defined over the domain space "space" and
  * local variables defined by "div" to "p".
  */
-static __isl_give isl_printer *upoly_print(__isl_keep struct isl_upoly *up,
+static __isl_give isl_printer *poly_print(__isl_keep isl_poly *poly,
 	__isl_keep isl_space *space, __isl_keep isl_mat *div,
 	__isl_take isl_printer *p)
 {
-	int i, n, first, print_parens;
-	struct isl_upoly_rec *rec;
+	int i, first, print_parens;
+	isl_size n;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (!p || !up || !space || !div)
+	is_cst = isl_poly_is_cst(poly);
+	if (!p || is_cst < 0 || !space || !div)
 		goto error;
 
-	if (isl_upoly_is_cst(up))
-		return upoly_print_cst(up, p, 1);
+	if (is_cst)
+		return poly_print_cst(poly, p, 1);
 
-	rec = isl_upoly_as_rec(up);
-	if (!rec)
-		goto error;
-	n = upoly_rec_n_non_zero(rec);
+	rec = isl_poly_as_rec(poly);
+	n = poly_rec_n_non_zero(rec);
+	if (n < 0)
+		return isl_printer_free(p);
 	print_parens = n > 1;
 	if (print_parens)
 		p = isl_printer_print_str(p, "(");
 	for (i = 0, first = 1; i < rec->n; ++i) {
-		if (isl_upoly_is_zero(rec->p[i]))
+		isl_bool is_zero = isl_poly_is_zero(rec->p[i]);
+		isl_bool is_one = isl_poly_is_one(rec->p[i]);
+		isl_bool is_negone = isl_poly_is_negone(rec->p[i]);
+		isl_bool is_cst = isl_poly_is_cst(rec->p[i]);
+
+		if (is_zero < 0 || is_one < 0 || is_negone < 0)
+			return isl_printer_free(p);
+		if (is_zero)
 			continue;
-		if (isl_upoly_is_negone(rec->p[i])) {
+		if (is_negone) {
 			if (!i)
 				p = isl_printer_print_str(p, "-1");
 			else if (first)
 				p = isl_printer_print_str(p, "-");
 			else
 				p = isl_printer_print_str(p, " - ");
-		} else if (isl_upoly_is_cst(rec->p[i]) &&
-				!isl_upoly_is_one(rec->p[i]))
-			p = upoly_print_cst(rec->p[i], p, first);
+		} else if (is_cst && !is_one)
+			p = poly_print_cst(rec->p[i], p, first);
 		else {
 			if (!first)
 				p = isl_printer_print_str(p, " + ");
-			if (i == 0 || !isl_upoly_is_one(rec->p[i]))
-				p = upoly_print(rec->p[i], space, div, p);
+			if (i == 0 || !is_one)
+				p = poly_print(rec->p[i], space, div, p);
 		}
 		first = 0;
 		if (i == 0)
 			continue;
-		if (!isl_upoly_is_one(rec->p[i]) &&
-		    !isl_upoly_is_negone(rec->p[i]))
+		if (!is_one && !is_negone)
 			p = isl_printer_print_str(p, " * ");
-		p = print_pow(p, space, div, rec->up.var, i);
+		p = print_pow(p, space, div, rec->poly.var, i);
 	}
 	if (print_parens)
 		p = isl_printer_print_str(p, ")");
@@ -1823,7 +1892,7 @@ static __isl_give isl_printer *print_qpolynomial(__isl_take isl_printer *p,
 {
 	if (!p || !qp)
 		goto error;
-	p = upoly_print(qp->upoly, qp->dim, qp->div, p);
+	p = poly_print(qp->poly, qp->dim, qp->div, p);
 	return p;
 error:
 	isl_printer_free(p);
@@ -1858,28 +1927,27 @@ static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p,
 static __isl_give isl_printer *print_qpolynomial_c(__isl_take isl_printer *p,
 	__isl_keep isl_space *space, __isl_keep isl_qpolynomial *qp)
 {
-	isl_int den;
+	isl_bool is_one;
+	isl_val *den;
 
-	isl_int_init(den);
-	isl_qpolynomial_get_den(qp, &den);
-	if (!isl_int_is_one(den)) {
-		isl_qpolynomial *f;
+	den = isl_qpolynomial_get_den(qp);
+	qp = isl_qpolynomial_copy(qp);
+	qp = isl_qpolynomial_scale_val(qp, isl_val_copy(den));
+	is_one = isl_val_is_one(den);
+	if (is_one < 0)
+		p = isl_printer_free(p);
+	if (!is_one)
 		p = isl_printer_print_str(p, "(");
-		qp = isl_qpolynomial_copy(qp);
-		f = isl_qpolynomial_rat_cst_on_domain(isl_space_copy(qp->dim),
-						den, qp->dim->ctx->one);
-		qp = isl_qpolynomial_mul(qp, f);
-	}
 	if (qp)
-		p = upoly_print(qp->upoly, space, qp->div, p);
+		p = poly_print(qp->poly, space, qp->div, p);
 	else
 		p = isl_printer_free(p);
-	if (!isl_int_is_one(den)) {
+	if (!is_one) {
 		p = isl_printer_print_str(p, ")/");
-		p = isl_printer_print_isl_int(p, den);
-		isl_qpolynomial_free(qp);
+		p = isl_printer_print_val(p, den);
 	}
-	isl_int_clear(den);
+	isl_qpolynomial_free(qp);
+	isl_val_free(den);
 	return p;
 }
 
@@ -2058,90 +2126,8 @@ static __isl_give isl_printer *print_pw_qpolynomial_fold_isl(
 	return p;
 }
 
-static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c);
-
-static __isl_give isl_printer *print_name_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim,
-	__isl_keep isl_basic_set *bset, enum isl_dim_type type, unsigned pos)
-{
-	if (type == isl_dim_div) {
-		p = isl_printer_print_str(p, "floord(");
-		p = print_affine_c(p, dim, bset, bset->div[pos] + 1);
-		p = isl_printer_print_str(p, ", ");
-		p = isl_printer_print_isl_int(p, bset->div[pos][0]);
-		p = isl_printer_print_str(p, ")");
-	} else {
-		const char *name;
-
-		name = isl_space_get_dim_name(dim, type, pos);
-		if (!name)
-			name = "UNNAMED";
-		p = isl_printer_print_str(p, name);
-	}
-	return p;
-}
-
-static __isl_give isl_printer *print_term_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *space,
-	__isl_keep isl_basic_set *bset, isl_int c, unsigned pos)
-{
-	enum isl_dim_type type;
-
-	if (!p || !space)
-		return isl_printer_free(p);
-
-	if (pos == 0)
-		return isl_printer_print_isl_int(p, c);
-
-	if (isl_int_is_one(c))
-		;
-	else if (isl_int_is_negone(c))
-		p = isl_printer_print_str(p, "-");
-	else {
-		p = isl_printer_print_isl_int(p, c);
-		p = isl_printer_print_str(p, "*");
-	}
-	type = pos2type(space, &pos);
-	p = print_name_c(p, space, bset, type, pos);
-	return p;
-}
-
-static __isl_give isl_printer *print_partial_affine_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim,
-	__isl_keep isl_basic_set *bset, isl_int *c, unsigned len)
-{
-	int i;
-	int first;
-
-	for (i = 0, first = 1; i < len; ++i) {
-		int flip = 0;
-		if (isl_int_is_zero(c[i]))
-			continue;
-		if (!first) {
-			if (isl_int_is_neg(c[i])) {
-				flip = 1;
-				isl_int_neg(c[i], c[i]);
-				p = isl_printer_print_str(p, " - ");
-			} else 
-				p = isl_printer_print_str(p, " + ");
-		}
-		first = 0;
-		p = print_term_c(p, dim, bset, c[i], i);
-		if (flip)
-			isl_int_neg(c[i], c[i]);
-	}
-	if (first)
-		p = isl_printer_print_str(p, "0");
-	return p;
-}
-
-static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c)
-{
-	unsigned len = 1 + isl_basic_set_total_dim(bset);
-	return print_partial_affine_c(p, dim, bset, c, len);
-}
+static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
+	__isl_keep isl_local_space *ls, isl_int *c);
 
 /* We skip the constraint if it is implied by the div expression.
  *
@@ -2149,18 +2135,19 @@ static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
  * is updated if the constraint is actually printed.
  */
 static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim,
-	__isl_keep isl_basic_set *bset, isl_int *c, const char *op, int *first)
+	__isl_keep isl_local_space *ls, isl_int *c, const char *op, int *first)
 {
 	unsigned o_div;
-	unsigned n_div;
+	isl_size n_div;
 	int div;
 
-	o_div = isl_basic_set_offset(bset, isl_dim_div);
-	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	o_div = isl_local_space_offset(ls, isl_dim_div);
+	n_div = isl_local_space_dim(ls, isl_dim_div);
+	if (n_div < 0)
+		return isl_printer_free(p);
 	div = isl_seq_last_non_zero(c + o_div, n_div);
 	if (div >= 0) {
-		isl_bool is_div = isl_basic_set_is_div_constraint(bset, c, div);
+		isl_bool is_div = isl_local_space_is_div_constraint(ls, c, div);
 		if (is_div < 0)
 			return isl_printer_free(p);
 		if (is_div)
@@ -2170,7 +2157,7 @@ static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,
 	if (!*first)
 		p = isl_printer_print_str(p, " && ");
 
-	p = print_affine_c(p, dim, bset, c);
+	p = print_ls_affine_c(p, ls, c);
 	p = isl_printer_print_str(p, " ");
 	p = isl_printer_print_str(p, op);
 	p = isl_printer_print_str(p, " 0");
@@ -2180,24 +2167,36 @@ static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,
 	return p;
 }
 
+static __isl_give isl_printer *print_ls_partial_affine_c(
+	__isl_take isl_printer *p, __isl_keep isl_local_space *ls,
+	isl_int *c, unsigned len);
+
 static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim, __isl_keep isl_basic_set *bset)
+	__isl_keep isl_space *space, __isl_keep isl_basic_set *bset)
 {
 	int i, j;
 	int first = 1;
-	unsigned n_div = isl_basic_set_dim(bset, isl_dim_div);
-	unsigned total = isl_basic_set_total_dim(bset) - n_div;
+	isl_size n_div = isl_basic_set_dim(bset, isl_dim_div);
+	isl_size total = isl_basic_set_dim(bset, isl_dim_all);
+	isl_mat *div;
+	isl_local_space *ls;
+
+	if (n_div < 0 || total < 0)
+		return isl_printer_free(p);
 
+	total -= n_div;
+	div = isl_basic_set_get_divs(bset);
+	ls = isl_local_space_alloc_div(isl_space_copy(space), div);
 	for (i = 0; i < bset->n_eq; ++i) {
 		j = isl_seq_last_non_zero(bset->eq[i] + 1 + total, n_div);
 		if (j < 0)
-			p = print_constraint_c(p, dim, bset,
+			p = print_constraint_c(p, ls,
 						bset->eq[i], "==", &first);
 		else {
 			if (i)
 				p = isl_printer_print_str(p, " && ");
 			p = isl_printer_print_str(p, "(");
-			p = print_partial_affine_c(p, dim, bset, bset->eq[i],
+			p = print_ls_partial_affine_c(p, ls, bset->eq[i],
 						   1 + total + j);
 			p = isl_printer_print_str(p, ") % ");
 			p = isl_printer_print_isl_int(p,
@@ -2207,13 +2206,13 @@ static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p,
 		}
 	}
 	for (i = 0; i < bset->n_ineq; ++i)
-		p = print_constraint_c(p, dim, bset, bset->ineq[i], ">=",
-					&first);
+		p = print_constraint_c(p, ls, bset->ineq[i], ">=", &first);
+	isl_local_space_free(ls);
 	return p;
 }
 
 static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p,
-	__isl_keep isl_space *dim, __isl_keep isl_set *set)
+	__isl_keep isl_space *space, __isl_keep isl_set *set)
 {
 	int i;
 
@@ -2228,7 +2227,7 @@ static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p,
 			p = isl_printer_print_str(p, " || ");
 		if (set->n > 1)
 			p = isl_printer_print_str(p, "(");
-		p = print_basic_set_c(p, dim, set->p[i]);
+		p = print_basic_set_c(p, space, set->p[i]);
 		if (set->n > 1)
 			p = isl_printer_print_str(p, ")");
 	}
@@ -2569,15 +2568,15 @@ __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
 	__isl_keep isl_local_space *ls)
 {
 	struct isl_print_space_data data = { 0 };
-	unsigned n_div;
+	isl_size n_div;
 
-	if (!ls)
+	n_div = isl_local_space_dim(ls, isl_dim_div);
+	if (n_div < 0)
 		goto error;
 
 	p = print_param_tuple(p, ls->dim, &data);
 	p = isl_printer_print_str(p, "{ ");
 	p = isl_print_space(ls->dim, p, 0, &data);
-	n_div = isl_local_space_dim(ls, isl_dim_div);
 	if (n_div > 0) {
 		p = isl_printer_print_str(p, " : ");
 		p = isl_printer_print_str(p, s_open_exists[0]);
@@ -2592,21 +2591,193 @@ __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
 	return NULL;
 }
 
+/* Look for the last of the "n" integer divisions that is used in "aff" and
+ * that can be printed as a modulo and
+ * return the position of this integer division.
+ * Return "n" if no such integer division can be found.
+ * Return isl_size_error on error.
+ *
+ * In particular, look for an integer division that appears in "aff"
+ * with a coefficient that is a multiple of the denominator
+ * of the integer division.
+ * That is, check if the numerator of "aff" is of the form
+ *
+ *	f(...) + a m floor(g/m)
+ *
+ * and return the position of "floor(g/m)".
+ *
+ * Note that, unlike print_as_modulo_pos, no check needs to be made
+ * for whether the integer division can be printed, since it will
+ * need to be printed as an integer division anyway if it is not printed
+ * as a modulo.
+ */
+static isl_size last_modulo(__isl_keep isl_printer *p, __isl_keep isl_aff *aff,
+	unsigned n)
+{
+	isl_size o_div;
+	int i;
+
+	if (n == 0)
+		return n;
+	o_div = isl_aff_domain_offset(aff, isl_dim_div);
+	if (o_div < 0)
+		return isl_size_error;
+	for (i = n - 1; i >= 0; --i) {
+		if (isl_int_is_zero(aff->v->el[1 + o_div + i]))
+			continue;
+		if (isl_int_is_divisible_by(aff->v->el[1 + o_div + i],
+					    aff->ls->div->row[i][0]))
+			return i;
+	}
+
+	return n;
+}
+
+/* Print the numerator of the affine expression "aff" to "p",
+ * with the variable names taken from "space".
+ */
+static __isl_give isl_printer *print_aff_num_base(__isl_take isl_printer *p,
+	__isl_keep isl_space *space, __isl_keep isl_aff *aff)
+{
+	isl_size total;
+
+	total = isl_aff_domain_dim(aff, isl_dim_all);
+	if (total < 0)
+		return isl_printer_free(p);
+	p = print_affine_of_len(space, aff->ls->div, p,
+				aff->v->el + 1, 1 + total);
+
+	return p;
+}
+
+static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p,
+	__isl_keep isl_space *space, __isl_keep isl_aff *aff);
+
+/* Print the modulo term "c" * ("aff" mod "mod") to "p",
+ * with the variable names taken from "space".
+ * If "first" is set, then this is the first term of an expression.
+ */
+static __isl_give isl_printer *print_mod_term(__isl_take isl_printer *p,
+	__isl_keep isl_space *space, __isl_keep isl_aff *aff, int first,
+	__isl_take isl_val *c, __isl_keep isl_val *mod)
+{
+	isl_bool is_one, is_neg;
+
+	is_neg = isl_val_is_neg(c);
+	if (is_neg < 0)
+		p = isl_printer_free(p);
+	if (!first) {
+		if (is_neg)
+			c = isl_val_neg(c);
+		p = isl_printer_print_str(p, is_neg ? " - " : " + ");
+	}
+	is_one = isl_val_is_one(c);
+	if (is_one < 0)
+		p = isl_printer_free(p);
+	if (!is_one) {
+		p = isl_printer_print_val(p, c);
+		p = isl_printer_print_str(p, "*(");
+	}
+	p = isl_printer_print_str(p, "(");
+	p = print_aff_num(p, space, aff);
+	p = isl_printer_print_str(p, ")");
+	p = isl_printer_print_str(p, " mod ");
+	p = isl_printer_print_val(p, mod);
+	if (!is_one)
+		p = isl_printer_print_str(p, ")");
+
+	isl_val_free(c);
+
+	return p;
+}
+
+/* Print the numerator of the affine expression "aff" to "p",
+ * with the variable names taken from "space",
+ * given that the numerator of "aff" is of the form
+ *
+ *	f(...) + a m floor(g/m)
+ *
+ * with "floor(g/m)" the integer division at position "last".
+ *
+ * First replace "aff" by its numerator and rewrite it as
+ *
+ *	f(...) + a g - a (g mod m)
+ *
+ * Recursively write out (the numerator of) "f(...) + a g"
+ * (which may involve other modulo expressions) and
+ * then write out "- a (g mod m)".
+ */
+static __isl_give isl_printer *print_aff_num_mod(__isl_take isl_printer *p,
+	__isl_keep isl_space *space, __isl_keep isl_aff *aff, unsigned last)
+{
+	isl_bool is_zero;
+	isl_val *a, *m;
+	isl_aff *div, *term;
+
+	aff = isl_aff_copy(aff);
+	aff = isl_aff_scale_val(aff, isl_aff_get_denominator_val(aff));
+	a = isl_aff_get_coefficient_val(aff, isl_dim_div, last);
+	aff = isl_aff_set_coefficient_si(aff, isl_dim_div, last, 0);
+	div = isl_aff_get_div(aff, last);
+	m = isl_aff_get_denominator_val(div);
+	a = isl_val_div(a, isl_val_copy(m));
+	div = isl_aff_scale_val(div, isl_val_copy(m));
+	term = isl_aff_scale_val(isl_aff_copy(div), isl_val_copy(a));
+	aff = isl_aff_add(aff, term);
+
+	is_zero = isl_aff_plain_is_zero(aff);
+	if (is_zero < 0) {
+		p = isl_printer_free(p);
+	} else {
+		if (!is_zero)
+			p = print_aff_num(p, space, aff);
+		a = isl_val_neg(a);
+		p = print_mod_term(p, space, div, is_zero, isl_val_copy(a), m);
+	}
+
+	isl_val_free(a);
+	isl_val_free(m);
+	isl_aff_free(aff);
+	isl_aff_free(div);
+
+	return p;
+}
+
+/* Print the numerator of the affine expression "aff" to "p",
+ * with the variable names taken from "space",
+ * separating out any (obvious) modulo expressions.
+ *
+ * In particular, look for modulo expressions in "aff",
+ * separating them out if found and simply printing out "aff" otherwise.
+ */
+static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p,
+	__isl_keep isl_space *space, __isl_keep isl_aff *aff)
+{
+	isl_size n_div, mod;
+
+	n_div = isl_aff_dim(aff, isl_dim_div);
+	if (n_div < 0)
+		return isl_printer_free(p);
+	mod = last_modulo(p, aff, n_div);
+	if (mod < 0)
+		return isl_printer_free(p);
+	if (mod < n_div)
+		return print_aff_num_mod(p, space, aff, mod);
+	else
+		return print_aff_num_base(p, space, aff);
+}
+
 /* Print the (potentially rational) affine expression "aff" to "p",
  * with the variable names taken from "space".
  */
 static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
 	__isl_keep isl_space *space, __isl_keep isl_aff *aff)
 {
-	unsigned total;
-
 	if (isl_aff_is_nan(aff))
 		return isl_printer_print_str(p, "NaN");
 
-	total = isl_local_space_dim(aff->ls, isl_dim_all);
 	p = isl_printer_print_str(p, "(");
-	p = print_affine_of_len(space, aff->ls->div, p,
-				aff->v->el + 1, 1 + total);
+	p = print_aff_num(p, space, aff);
 	if (isl_int_is_one(aff->v->el[0]))
 		p = isl_printer_print_str(p, ")");
 	else {
@@ -2696,9 +2867,6 @@ static __isl_give isl_printer *print_pw_aff_isl(__isl_take isl_printer *p,
 	return NULL;
 }
 
-static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
-	__isl_keep isl_local_space *ls, isl_int *c);
-
 static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p,
 	__isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos)
 {
@@ -2738,7 +2906,8 @@ static __isl_give isl_printer *print_ls_term_c(__isl_take isl_printer *p,
 		p = isl_printer_print_isl_int(p, c);
 		p = isl_printer_print_str(p, "*");
 	}
-	type = pos2type(ls->dim, &pos);
+	if (pos2type(ls->dim, &type, &pos) < 0)
+		return isl_printer_free(p);
 	p = print_ls_name_c(p, ls, type, pos);
 	return p;
 }
@@ -2775,16 +2944,21 @@ static __isl_give isl_printer *print_ls_partial_affine_c(
 static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
 	__isl_keep isl_local_space *ls, isl_int *c)
 {
-	unsigned len = 1 + isl_local_space_dim(ls, isl_dim_all);
-	return print_ls_partial_affine_c(p, ls, c, len);
+	isl_size total = isl_local_space_dim(ls, isl_dim_all);
+
+	if (total < 0)
+		return isl_printer_free(p);
+	return print_ls_partial_affine_c(p, ls, c, 1 + total);
 }
 
 static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p,
 	__isl_keep isl_aff *aff)
 {
-	unsigned total;
+	isl_size total;
 
-	total = isl_local_space_dim(aff->ls, isl_dim_all);
+	total = isl_aff_domain_dim(aff, isl_dim_all);
+	if (total < 0)
+		return isl_printer_free(p);
 	if (!isl_int_is_one(aff->v->el[0]))
 		p = isl_printer_print_str(p, "(");
 	p = print_ls_partial_affine_c(p, aff->ls, aff->v->el + 1, 1 + total);
@@ -2891,7 +3065,7 @@ static __isl_give isl_printer *print_union_pw_aff_body(
 	data.p = p;
 	if (isl_union_pw_aff_foreach_pw_aff(upa,
 					    &print_pw_aff_body_wrap, &data) < 0)
-		data.p = isl_printer_free(p);
+		data.p = isl_printer_free(data.p);
 	p = data.p;
 	p = isl_printer_print_str(p, s_close_set[0]);
 
@@ -2937,21 +3111,26 @@ __isl_give isl_printer *isl_printer_print_union_pw_aff(
  *
  * If the current dimension is an output dimension, then print
  * the corresponding expression.  Otherwise, print the name of the dimension.
+ * Make sure to use the domain space for printing names as
+ * that is the space that will be used for printing constraints (if any).
  */
 static __isl_give isl_printer *print_dim_ma(__isl_take isl_printer *p,
 	struct isl_print_space_data *data, unsigned pos)
 {
 	isl_multi_aff *ma = data->user;
+	isl_space *space;
 
+	space = isl_multi_aff_get_domain_space(ma);
 	if (data->type == isl_dim_out) {
-		isl_space *space;
-
-		space = isl_multi_aff_get_domain_space(ma);
 		p = print_aff_body(p, space, ma->u.p[pos]);
-		isl_space_free(space);
 	} else {
-		p = print_name(data->space, p, data->type, pos, data->latex);
+		enum isl_dim_type type = data->type;
+
+		if (type == isl_dim_in)
+			type = isl_dim_set;
+		p = print_name(space, p, type, pos, data->latex);
 	}
+	isl_space_free(space);
 
 	return p;
 }
@@ -3066,7 +3245,7 @@ static __isl_give isl_printer *print_unnamed_pw_multi_aff_c(
 static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,
 	__isl_keep isl_pw_multi_aff *pma)
 {
-	int n;
+	isl_size n;
 	const char *name;
 
 	if (!pma)
@@ -3075,8 +3254,11 @@ static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,
 		isl_die(p->ctx, isl_error_unsupported,
 			"cannot print empty isl_pw_multi_aff in C format",
 			goto error);
+	n = isl_pw_multi_aff_dim(pma, isl_dim_out);
+	if (n < 0)
+		return isl_printer_free(p);
 	name = isl_pw_multi_aff_get_tuple_name(pma, isl_dim_out);
-	if (!name && isl_pw_multi_aff_dim(pma, isl_dim_out) == 1)
+	if (!name && n == 1)
 		return print_unnamed_pw_multi_aff_c(p, pma);
 	if (!name)
 		isl_die(p->ctx, isl_error_unsupported,
@@ -3084,7 +3266,6 @@ static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,
 			goto error);
 
 	p = isl_printer_print_str(p, name);
-	n = isl_pw_multi_aff_dim(pma, isl_dim_out);
 	if (n != 0)
 		isl_die(p->ctx, isl_error_unsupported,
 			"not supported yet", goto error);
@@ -3170,6 +3351,9 @@ __isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
  * If the current dimension is an output dimension, then print
  * the corresponding piecewise affine expression.
  * Otherwise, print the name of the dimension.
+ * Make sure to use the same space in both cases.
+ * In particular, use the domain space for printing names as
+ * that is the space that is used for printing constraints.
  */
 static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p,
 	struct isl_print_space_data *data, unsigned pos)
@@ -3180,8 +3364,16 @@ static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p,
 	isl_multi_pw_aff *mpa = data->user;
 	isl_pw_aff *pa;
 
-	if (data->type != isl_dim_out)
-		return print_name(data->space, p, data->type, pos, data->latex);
+	if (data->type != isl_dim_out) {
+		enum isl_dim_type type = data->type;
+
+		if (type == isl_dim_in)
+			type = isl_dim_set;
+		space = isl_multi_pw_aff_get_domain_space(mpa);
+		p = print_name(space, p, type, pos, data->latex);
+		isl_space_free(space);
+		return p;
+	}
 
 	pa = mpa->u.p[pos];
 	if (pa->n == 0)
@@ -3303,6 +3495,58 @@ __isl_give isl_printer *isl_printer_print_multi_val(
 		return isl_printer_free(p));
 }
 
+/* Print dimension "pos" of data->space to "p".
+ *
+ * data->user is assumed to be an isl_multi_id.
+ *
+ * If the current dimension is an output dimension, then print
+ * the corresponding identifier.  Otherwise, print the name of the dimension.
+ */
+static __isl_give isl_printer *print_dim_mi(__isl_take isl_printer *p,
+	struct isl_print_space_data *data, unsigned pos)
+{
+	isl_multi_id *mi = data->user;
+
+	if (data->type == isl_dim_out)
+		return isl_printer_print_id(p, mi->u.p[pos]);
+	else
+		return print_name(data->space, p, data->type, pos, data->latex);
+}
+
+/* Print the isl_multi_id "mi" to "p" in isl format.
+ */
+static __isl_give isl_printer *print_multi_id_isl(__isl_take isl_printer *p,
+	__isl_keep isl_multi_id *mi)
+{
+	isl_space *space;
+	struct isl_print_space_data data = { 0 };
+
+	space = isl_multi_id_peek_space(mi);
+	p = print_param_tuple(p, space, &data);
+	p = isl_printer_print_str(p, "{ ");
+	data.print_dim = &print_dim_mi;
+	data.user = mi;
+	p = isl_print_space(space, p, 0, &data);
+	p = isl_printer_print_str(p, " }");
+	return p;
+}
+
+/* Print the isl_multi_id "mi" to "p".
+ *
+ * Currently only supported in isl format.
+ */
+__isl_give isl_printer *isl_printer_print_multi_id(
+	__isl_take isl_printer *p, __isl_keep isl_multi_id *mi)
+{
+	if (!p || !mi)
+		return isl_printer_free(p);
+
+	if (p->output_format == ISL_FORMAT_ISL)
+		return print_multi_id_isl(p, mi);
+	isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
+		"unsupported output format", return isl_printer_free(p));
+}
+
 /* Print dimension "pos" of data->space to "p".
  *
  * data->user is assumed to be an isl_multi_union_pw_aff.

diff  --git a/polly/lib/External/isl/isl_point.c b/polly/lib/External/isl/isl_point.c
index 4b3c157b66d2..ee59de8e82b5 100644
--- a/polly/lib/External/isl/isl_point.c
+++ b/polly/lib/External/isl/isl_point.c
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2010      INRIA Saclay
+ * Copyright 2013      Ecole Normale Superieure
+ * Copyright 2015      Sven Verdoolaege
+ * Copyright 2019      Cerebras Systems
+ *
+ * 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
+ * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
 #include <isl_map_private.h>
 #include <isl_point_private.h>
 #include <isl/set.h>
@@ -6,6 +21,7 @@
 #include <isl_scan.h>
 #include <isl_seq.h>
 #include <isl_space_private.h>
+#include <isl_local_private.h>
 #include <isl_val_private.h>
 #include <isl_vec_private.h>
 #include <isl_output_private.h>
@@ -29,50 +45,66 @@ __isl_give isl_space *isl_point_get_space(__isl_keep isl_point *pnt)
 	return isl_space_copy(isl_point_peek_space(pnt));
 }
 
-__isl_give isl_point *isl_point_alloc(__isl_take isl_space *dim,
+#undef TYPE1
+#define TYPE1		isl_basic_map
+#undef TYPE2
+#define TYPE2		isl_point
+#undef TYPE_PAIR
+#define TYPE_PAIR	isl_basic_map_point
+
+static
+#include "isl_type_has_equal_space_templ.c"
+static
+#include "isl_type_check_equal_space_templ.c"
+
+__isl_give isl_point *isl_point_alloc(__isl_take isl_space *space,
 	__isl_take isl_vec *vec)
 {
 	struct isl_point *pnt;
+	isl_size dim;
 
-	if (!dim || !vec)
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0 || !vec)
 		goto error;
 
-	if (vec->size > 1 + isl_space_dim(dim, isl_dim_all)) {
+	if (vec->size > 1 + dim) {
 		vec = isl_vec_cow(vec);
 		if (!vec)
 			goto error;
-		vec->size = 1 + isl_space_dim(dim, isl_dim_all);
+		vec->size = 1 + dim;
 	}
 
-	pnt = isl_alloc_type(dim->ctx, struct isl_point);
+	pnt = isl_alloc_type(space->ctx, struct isl_point);
 	if (!pnt)
 		goto error;
 
 	pnt->ref = 1;
-	pnt->dim = dim;
+	pnt->dim = space;
 	pnt->vec = vec;
 
 	return pnt;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_vec_free(vec);
 	return NULL;
 }
 
-__isl_give isl_point *isl_point_zero(__isl_take isl_space *dim)
+__isl_give isl_point *isl_point_zero(__isl_take isl_space *space)
 {
 	isl_vec *vec;
+	isl_size dim;
 
-	if (!dim)
-		return NULL;
-	vec = isl_vec_alloc(dim->ctx, 1 + isl_space_dim(dim, isl_dim_all));
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0)
+		goto error;
+	vec = isl_vec_alloc(space->ctx, 1 + dim);
 	if (!vec)
 		goto error;
 	isl_int_set_si(vec->el[0], 1);
 	isl_seq_clr(vec->el + 1, vec->size - 1);
-	return isl_point_alloc(dim, vec);
+	return isl_point_alloc(space, vec);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -123,12 +155,12 @@ __isl_null isl_point *isl_point_free(__isl_take isl_point *pnt)
 	return NULL;
 }
 
-__isl_give isl_point *isl_point_void(__isl_take isl_space *dim)
+__isl_give isl_point *isl_point_void(__isl_take isl_space *space)
 {
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	return isl_point_alloc(dim, isl_vec_alloc(dim->ctx, 0));
+	return isl_point_alloc(space, isl_vec_alloc(space->ctx, 0));
 }
 
 isl_bool isl_point_is_void(__isl_keep isl_point *pnt)
@@ -136,7 +168,7 @@ isl_bool isl_point_is_void(__isl_keep isl_point *pnt)
 	if (!pnt)
 		return isl_bool_error;
 
-	return pnt->vec->size == 0;
+	return isl_bool_ok(pnt->vec->size == 0);
 }
 
 /* Return the space of "pnt".
@@ -256,6 +288,27 @@ __isl_give isl_point *isl_point_restore_vec(__isl_take isl_point *pnt,
 	return NULL;
 }
 
+/* Return the number of variables of the given type.
+ */
+static isl_size isl_point_dim(__isl_keep isl_point *pnt, enum isl_dim_type type)
+{
+	return isl_space_dim(isl_point_peek_space(pnt), type);
+}
+
+/* Return the position of the coordinates of the given type
+ * within the sequence of coordinates of "pnt".
+ */
+static isl_size isl_point_var_offset(__isl_keep isl_point *pnt,
+	enum isl_dim_type type)
+{
+	return pnt ? isl_space_offset(pnt->dim, type) : isl_size_error;
+}
+
+#undef TYPE
+#define TYPE	isl_point
+static
+#include "check_type_range_templ.c"
+
 /* Return the value of coordinate "pos" of type "type" of "pnt".
  */
 __isl_give isl_val *isl_point_get_coordinate_val(__isl_keep isl_point *pnt,
@@ -263,6 +316,7 @@ __isl_give isl_val *isl_point_get_coordinate_val(__isl_keep isl_point *pnt,
 {
 	isl_ctx *ctx;
 	isl_val *v;
+	isl_size off;
 
 	if (!pnt)
 		return NULL;
@@ -271,18 +325,68 @@ __isl_give isl_val *isl_point_get_coordinate_val(__isl_keep isl_point *pnt,
 	if (isl_point_is_void(pnt))
 		isl_die(ctx, isl_error_invalid,
 			"void point does not have coordinates", return NULL);
-	if (pos < 0 || pos >= isl_space_dim(pnt->dim, type))
-		isl_die(ctx, isl_error_invalid,
-			"position out of bounds", return NULL);
+	if (isl_point_check_range(pnt, type, pos, 1) < 0)
+		return NULL;
 
-	if (type == isl_dim_set)
-		pos += isl_space_dim(pnt->dim, isl_dim_param);
+	off = isl_point_var_offset(pnt, type);
+	if (off < 0)
+		return NULL;
+	pos += off;
 
 	v = isl_val_rat_from_isl_int(ctx, pnt->vec->el[1 + pos],
 						pnt->vec->el[0]);
 	return isl_val_normalize(v);
 }
 
+/* Set all entries of "mv" to NaN.
+ */
+static __isl_give isl_multi_val *set_nan(__isl_take isl_multi_val *mv)
+{
+	int i;
+	isl_size n;
+	isl_val *v;
+
+	n = isl_multi_val_size(mv);
+	if (n < 0)
+		return isl_multi_val_free(mv);
+	v = isl_val_nan(isl_multi_val_get_ctx(mv));
+	for (i = 0; i < n; ++i)
+		mv = isl_multi_val_set_at(mv, i, isl_val_copy(v));
+	isl_val_free(v);
+
+	return mv;
+}
+
+/* Return the values of the set dimensions of "pnt".
+ * Return a sequence of NaNs in case of a void point.
+ */
+__isl_give isl_multi_val *isl_point_get_multi_val(__isl_keep isl_point *pnt)
+{
+	int i;
+	isl_bool is_void;
+	isl_size n;
+	isl_multi_val *mv;
+
+	is_void = isl_point_is_void(pnt);
+	if (is_void < 0)
+		return NULL;
+
+	mv = isl_multi_val_alloc(isl_point_get_space(pnt));
+	if (is_void)
+		return set_nan(mv);
+	n = isl_multi_val_size(mv);
+	if (n < 0)
+		return isl_multi_val_free(mv);
+	for (i = 0; i < n; ++i) {
+		isl_val *v;
+
+		v = isl_point_get_coordinate_val(pnt, isl_dim_set, i);
+		mv = isl_multi_val_set_at(mv, i, v);
+	}
+
+	return mv;
+}
+
 /* Replace coordinate "pos" of type "type" of "pnt" by "v".
  */
 __isl_give isl_point *isl_point_set_coordinate_val(__isl_take isl_point *pnt,
@@ -293,13 +397,13 @@ __isl_give isl_point *isl_point_set_coordinate_val(__isl_take isl_point *pnt,
 	if (isl_point_is_void(pnt))
 		isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
 			"void point does not have coordinates", goto error);
-	if (pos < 0 || pos >= isl_space_dim(pnt->dim, type))
-		isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
-			"position out of bounds", goto error);
+	if (isl_point_check_range(pnt, type, pos, 1) < 0)
+		goto error;
 	if (!isl_val_is_rat(v))
 		isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
 			"expecting rational value", goto error);
 
+	pos += isl_space_offset(isl_point_peek_space(pnt), type);
 	if (isl_int_eq(pnt->vec->el[1 + pos], v->n) &&
 	    isl_int_eq(pnt->vec->el[0], v->d)) {
 		isl_val_free(v);
@@ -338,6 +442,8 @@ __isl_give isl_point *isl_point_set_coordinate_val(__isl_take isl_point *pnt,
 __isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
 	enum isl_dim_type type, int pos, unsigned val)
 {
+	isl_size off;
+
 	if (!pnt || isl_point_is_void(pnt))
 		return pnt;
 
@@ -348,8 +454,10 @@ __isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
 	if (!pnt->vec)
 		goto error;
 
-	if (type == isl_dim_set)
-		pos += isl_space_dim(pnt->dim, isl_dim_param);
+	off = isl_point_var_offset(pnt, type);
+	if (off < 0)
+		goto error;
+	pos += off;
 
 	isl_int_add_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
 
@@ -362,6 +470,8 @@ __isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
 __isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
 	enum isl_dim_type type, int pos, unsigned val)
 {
+	isl_size off;
+
 	if (!pnt || isl_point_is_void(pnt))
 		return pnt;
 
@@ -372,8 +482,10 @@ __isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
 	if (!pnt->vec)
 		goto error;
 
-	if (type == isl_dim_set)
-		pos += isl_space_dim(pnt->dim, isl_dim_param);
+	off = isl_point_var_offset(pnt, type);
+	if (off < 0)
+		goto error;
+	pos += off;
 
 	isl_int_sub_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
 
@@ -444,30 +556,19 @@ isl_stat isl_set_foreach_point(__isl_keep isl_set *set,
 isl_bool isl_basic_map_contains_point(__isl_keep isl_basic_map *bmap,
 	__isl_keep isl_point *point)
 {
-	int i;
-	struct isl_vec *vec;
-	unsigned dim;
+	isl_local *local;
+	isl_vec *vec;
 	isl_bool contains;
 
-	if (!bmap || !point)
+	if (isl_basic_map_point_check_equal_space(bmap, point) < 0)
 		return isl_bool_error;
-	isl_assert(bmap->ctx, isl_space_is_equal(bmap->dim, point->dim),
-		return isl_bool_error);
 	if (bmap->n_div == 0)
 		return isl_basic_map_contains(bmap, point->vec);
 
-	dim = isl_basic_map_total_dim(bmap) - bmap->n_div;
-	vec = isl_vec_alloc(bmap->ctx, 1 + dim + bmap->n_div);
-	if (!vec)
-		return isl_bool_error;
-
-	isl_seq_cpy(vec->el, point->vec->el, point->vec->size);
-	for (i = 0; i < bmap->n_div; ++i) {
-		isl_seq_inner_product(bmap->div[i] + 1, vec->el,
-					1 + dim + i, &vec->el[1+dim+i]);
-		isl_int_fdiv_q(vec->el[1+dim+i], vec->el[1+dim+i],
-				bmap->div[i][0]);
-	}
+	local = isl_local_alloc_from_mat(isl_basic_map_get_divs(bmap));
+	vec = isl_point_get_vec(point);
+	vec = isl_local_extend_point_vec(local, vec);
+	isl_local_free(local);
 
 	contains = isl_basic_map_contains(bmap, vec);
 
@@ -555,7 +656,7 @@ __isl_give isl_basic_set *isl_basic_set_box_from_points(
 	__isl_take isl_point *pnt1, __isl_take isl_point *pnt2)
 {
 	isl_basic_set *bset = NULL;
-	unsigned total;
+	isl_size total;
 	int i;
 	int k;
 	isl_int t;
@@ -586,7 +687,9 @@ __isl_give isl_basic_set *isl_basic_set_box_from_points(
 		return isl_basic_set_from_point(pnt1);
 	}
 
-	total = isl_space_dim(pnt1->dim, isl_dim_all);
+	total = isl_point_dim(pnt1, isl_dim_all);
+	if (total < 0)
+		goto error;
 	bset = isl_basic_set_alloc_space(isl_space_copy(pnt1->dim), 0, 0, 2 * total);
 
 	for (i = 0; i < total; ++i) {
@@ -651,6 +754,7 @@ static __isl_give isl_printer *print_coordinate(__isl_take isl_printer *p,
 {
 	isl_point *pnt = data->user;
 
+	pos += isl_space_offset(data->space, data->type);
 	p = isl_printer_print_isl_int(p, pnt->vec->el[1 + pos]);
 	if (!isl_int_is_one(pnt->vec->el[0])) {
 		p = isl_printer_print_str(p, "/");
@@ -665,7 +769,7 @@ __isl_give isl_printer *isl_printer_print_point(
 {
 	struct isl_print_space_data data = { 0 };
 	int i;
-	unsigned nparam;
+	isl_size nparam;
 
 	if (!pnt)
 		return p;
@@ -674,7 +778,9 @@ __isl_give isl_printer *isl_printer_print_point(
 		return p;
 	}
 
-	nparam = isl_space_dim(pnt->dim, isl_dim_param);
+	nparam = isl_point_dim(pnt, isl_dim_param);
+	if (nparam < 0)
+		return isl_printer_free(p);
 	if (nparam > 0) {
 		p = isl_printer_print_str(p, "[");
 		for (i = 0; i < nparam; ++i) {

diff  --git a/polly/lib/External/isl/isl_point_private.h b/polly/lib/External/isl/isl_point_private.h
index c405da3f8bc4..a1e84494f35e 100644
--- a/polly/lib/External/isl/isl_point_private.h
+++ b/polly/lib/External/isl/isl_point_private.h
@@ -11,7 +11,7 @@ struct isl_point {
 	struct isl_vec	*vec;
 };
 
-__isl_give isl_point *isl_point_alloc(__isl_take isl_space *dim,
+__isl_give isl_point *isl_point_alloc(__isl_take isl_space *space,
 	__isl_take isl_vec *vec);
 
 __isl_keep isl_space *isl_point_peek_space(__isl_keep isl_point *pnt);

diff  --git a/polly/lib/External/isl/isl_polynomial.c b/polly/lib/External/isl/isl_polynomial.c
index 4c02324f30eb..cd1a25a1ccae 100644
--- a/polly/lib/External/isl/isl_polynomial.c
+++ b/polly/lib/External/isl/isl_polynomial.c
@@ -28,8 +28,8 @@
 #include <isl_val_private.h>
 #include <isl_config.h>
 
-#undef BASE
-#define BASE pw_qpolynomial
+#undef EL_BASE
+#define EL_BASE pw_qpolynomial
 
 #include <isl_list_templ.c>
 
@@ -43,60 +43,62 @@ static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
 	}
 }
 
-int isl_upoly_is_cst(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_cst(__isl_keep isl_poly *poly)
 {
-	if (!up)
-		return -1;
+	if (!poly)
+		return isl_bool_error;
 
-	return up->var < 0;
+	return isl_bool_ok(poly->var < 0);
 }
 
-__isl_keep struct isl_upoly_cst *isl_upoly_as_cst(__isl_keep struct isl_upoly *up)
+__isl_keep isl_poly_cst *isl_poly_as_cst(__isl_keep isl_poly *poly)
 {
-	if (!up)
+	if (!poly)
 		return NULL;
 
-	isl_assert(up->ctx, up->var < 0, return NULL);
+	isl_assert(poly->ctx, poly->var < 0, return NULL);
 
-	return (struct isl_upoly_cst *)up;
+	return (isl_poly_cst *) poly;
 }
 
-__isl_keep struct isl_upoly_rec *isl_upoly_as_rec(__isl_keep struct isl_upoly *up)
+__isl_keep isl_poly_rec *isl_poly_as_rec(__isl_keep isl_poly *poly)
 {
-	if (!up)
+	if (!poly)
 		return NULL;
 
-	isl_assert(up->ctx, up->var >= 0, return NULL);
+	isl_assert(poly->ctx, poly->var >= 0, return NULL);
 
-	return (struct isl_upoly_rec *)up;
+	return (isl_poly_rec *) poly;
 }
 
 /* Compare two polynomials.
  *
- * Return -1 if "up1" is "smaller" than "up2", 1 if "up1" is "greater"
- * than "up2" and 0 if they are equal.
+ * Return -1 if "poly1" is "smaller" than "poly2", 1 if "poly1" is "greater"
+ * than "poly2" and 0 if they are equal.
  */
-static int isl_upoly_plain_cmp(__isl_keep struct isl_upoly *up1,
-	__isl_keep struct isl_upoly *up2)
+static int isl_poly_plain_cmp(__isl_keep isl_poly *poly1,
+	__isl_keep isl_poly *poly2)
 {
 	int i;
-	struct isl_upoly_rec *rec1, *rec2;
+	isl_bool is_cst1;
+	isl_poly_rec *rec1, *rec2;
 
-	if (up1 == up2)
+	if (poly1 == poly2)
 		return 0;
-	if (!up1)
+	is_cst1 = isl_poly_is_cst(poly1);
+	if (is_cst1 < 0)
 		return -1;
-	if (!up2)
+	if (!poly2)
 		return 1;
-	if (up1->var != up2->var)
-		return up1->var - up2->var;
+	if (poly1->var != poly2->var)
+		return poly1->var - poly2->var;
 
-	if (isl_upoly_is_cst(up1)) {
-		struct isl_upoly_cst *cst1, *cst2;
+	if (is_cst1) {
+		isl_poly_cst *cst1, *cst2;
 		int cmp;
 
-		cst1 = isl_upoly_as_cst(up1);
-		cst2 = isl_upoly_as_cst(up2);
+		cst1 = isl_poly_as_cst(poly1);
+		cst2 = isl_poly_as_cst(poly2);
 		if (!cst1 || !cst2)
 			return 0;
 		cmp = isl_int_cmp(cst1->n, cst2->n);
@@ -105,8 +107,8 @@ static int isl_upoly_plain_cmp(__isl_keep struct isl_upoly *up1,
 		return isl_int_cmp(cst1->d, cst2->d);
 	}
 
-	rec1 = isl_upoly_as_rec(up1);
-	rec2 = isl_upoly_as_rec(up2);
+	rec1 = isl_poly_as_rec(poly1);
+	rec2 = isl_poly_as_rec(poly2);
 	if (!rec1 || !rec2)
 		return 0;
 
@@ -114,7 +116,7 @@ static int isl_upoly_plain_cmp(__isl_keep struct isl_upoly *up1,
 		return rec1->n - rec2->n;
 
 	for (i = 0; i < rec1->n; ++i) {
-		int cmp = isl_upoly_plain_cmp(rec1->p[i], rec2->p[i]);
+		int cmp = isl_poly_plain_cmp(rec1->p[i], rec2->p[i]);
 		if (cmp != 0)
 			return cmp;
 	}
@@ -122,30 +124,34 @@ static int isl_upoly_plain_cmp(__isl_keep struct isl_upoly *up1,
 	return 0;
 }
 
-isl_bool isl_upoly_is_equal(__isl_keep struct isl_upoly *up1,
-	__isl_keep struct isl_upoly *up2)
+isl_bool isl_poly_is_equal(__isl_keep isl_poly *poly1,
+	__isl_keep isl_poly *poly2)
 {
 	int i;
-	struct isl_upoly_rec *rec1, *rec2;
+	isl_bool is_cst1;
+	isl_poly_rec *rec1, *rec2;
 
-	if (!up1 || !up2)
+	is_cst1 = isl_poly_is_cst(poly1);
+	if (is_cst1 < 0 || !poly2)
 		return isl_bool_error;
-	if (up1 == up2)
+	if (poly1 == poly2)
 		return isl_bool_true;
-	if (up1->var != up2->var)
+	if (poly1->var != poly2->var)
 		return isl_bool_false;
-	if (isl_upoly_is_cst(up1)) {
-		struct isl_upoly_cst *cst1, *cst2;
-		cst1 = isl_upoly_as_cst(up1);
-		cst2 = isl_upoly_as_cst(up2);
+	if (is_cst1) {
+		isl_poly_cst *cst1, *cst2;
+		int r;
+		cst1 = isl_poly_as_cst(poly1);
+		cst2 = isl_poly_as_cst(poly2);
 		if (!cst1 || !cst2)
 			return isl_bool_error;
-		return isl_int_eq(cst1->n, cst2->n) &&
-		       isl_int_eq(cst1->d, cst2->d);
+		r = isl_int_eq(cst1->n, cst2->n) &&
+		    isl_int_eq(cst1->d, cst2->d);
+		return isl_bool_ok(r);
 	}
 
-	rec1 = isl_upoly_as_rec(up1);
-	rec2 = isl_upoly_as_rec(up2);
+	rec1 = isl_poly_as_rec(poly1);
+	rec2 = isl_poly_as_rec(poly2);
 	if (!rec1 || !rec2)
 		return isl_bool_error;
 
@@ -153,7 +159,7 @@ isl_bool isl_upoly_is_equal(__isl_keep struct isl_upoly *up1,
 		return isl_bool_false;
 
 	for (i = 0; i < rec1->n; ++i) {
-		isl_bool eq = isl_upoly_is_equal(rec1->p[i], rec2->p[i]);
+		isl_bool eq = isl_poly_is_equal(rec1->p[i], rec2->p[i]);
 		if (eq < 0 || !eq)
 			return eq;
 	}
@@ -161,130 +167,132 @@ isl_bool isl_upoly_is_equal(__isl_keep struct isl_upoly *up1,
 	return isl_bool_true;
 }
 
-int isl_upoly_is_zero(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_zero(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
-	if (!up)
-		return -1;
-	if (!isl_upoly_is_cst(up))
-		return 0;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
-		return -1;
+		return isl_bool_error;
 
-	return isl_int_is_zero(cst->n) && isl_int_is_pos(cst->d);
+	return isl_bool_ok(isl_int_is_zero(cst->n) && isl_int_is_pos(cst->d));
 }
 
-int isl_upoly_sgn(__isl_keep struct isl_upoly *up)
+int isl_poly_sgn(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
-	if (!up)
-		return 0;
-	if (!isl_upoly_is_cst(up))
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0 || !is_cst)
 		return 0;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
 		return 0;
 
 	return isl_int_sgn(cst->n);
 }
 
-int isl_upoly_is_nan(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_nan(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
-	if (!up)
-		return -1;
-	if (!isl_upoly_is_cst(up))
-		return 0;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
-		return -1;
+		return isl_bool_error;
 
-	return isl_int_is_zero(cst->n) && isl_int_is_zero(cst->d);
+	return isl_bool_ok(isl_int_is_zero(cst->n) && isl_int_is_zero(cst->d));
 }
 
-int isl_upoly_is_infty(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_infty(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
-	if (!up)
-		return -1;
-	if (!isl_upoly_is_cst(up))
-		return 0;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
-		return -1;
+		return isl_bool_error;
 
-	return isl_int_is_pos(cst->n) && isl_int_is_zero(cst->d);
+	return isl_bool_ok(isl_int_is_pos(cst->n) && isl_int_is_zero(cst->d));
 }
 
-int isl_upoly_is_neginfty(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_neginfty(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
-	if (!up)
-		return -1;
-	if (!isl_upoly_is_cst(up))
-		return 0;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
-		return -1;
+		return isl_bool_error;
 
-	return isl_int_is_neg(cst->n) && isl_int_is_zero(cst->d);
+	return isl_bool_ok(isl_int_is_neg(cst->n) && isl_int_is_zero(cst->d));
 }
 
-int isl_upoly_is_one(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_one(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
+	int r;
 
-	if (!up)
-		return -1;
-	if (!isl_upoly_is_cst(up))
-		return 0;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
-		return -1;
+		return isl_bool_error;
 
-	return isl_int_eq(cst->n, cst->d) && isl_int_is_pos(cst->d);
+	r = isl_int_eq(cst->n, cst->d) && isl_int_is_pos(cst->d);
+	return isl_bool_ok(r);
 }
 
-int isl_upoly_is_negone(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_negone(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
-	if (!up)
-		return -1;
-	if (!isl_upoly_is_cst(up))
-		return 0;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
-		return -1;
+		return isl_bool_error;
 
-	return isl_int_is_negone(cst->n) && isl_int_is_one(cst->d);
+	return isl_bool_ok(isl_int_is_negone(cst->n) && isl_int_is_one(cst->d));
 }
 
-__isl_give struct isl_upoly_cst *isl_upoly_cst_alloc(struct isl_ctx *ctx)
+__isl_give isl_poly_cst *isl_poly_cst_alloc(isl_ctx *ctx)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	cst = isl_alloc_type(ctx, struct isl_upoly_cst);
+	cst = isl_alloc_type(ctx, struct isl_poly_cst);
 	if (!cst)
 		return NULL;
 
-	cst->up.ref = 1;
-	cst->up.ctx = ctx;
+	cst->poly.ref = 1;
+	cst->poly.ctx = ctx;
 	isl_ctx_ref(ctx);
-	cst->up.var = -1;
+	cst->poly.var = -1;
 
 	isl_int_init(cst->n);
 	isl_int_init(cst->d);
@@ -292,108 +300,106 @@ __isl_give struct isl_upoly_cst *isl_upoly_cst_alloc(struct isl_ctx *ctx)
 	return cst;
 }
 
-__isl_give struct isl_upoly *isl_upoly_zero(struct isl_ctx *ctx)
+__isl_give isl_poly *isl_poly_zero(isl_ctx *ctx)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	cst = isl_upoly_cst_alloc(ctx);
+	cst = isl_poly_cst_alloc(ctx);
 	if (!cst)
 		return NULL;
 
 	isl_int_set_si(cst->n, 0);
 	isl_int_set_si(cst->d, 1);
 
-	return &cst->up;
+	return &cst->poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_one(struct isl_ctx *ctx)
+__isl_give isl_poly *isl_poly_one(isl_ctx *ctx)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	cst = isl_upoly_cst_alloc(ctx);
+	cst = isl_poly_cst_alloc(ctx);
 	if (!cst)
 		return NULL;
 
 	isl_int_set_si(cst->n, 1);
 	isl_int_set_si(cst->d, 1);
 
-	return &cst->up;
+	return &cst->poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_infty(struct isl_ctx *ctx)
+__isl_give isl_poly *isl_poly_infty(isl_ctx *ctx)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	cst = isl_upoly_cst_alloc(ctx);
+	cst = isl_poly_cst_alloc(ctx);
 	if (!cst)
 		return NULL;
 
 	isl_int_set_si(cst->n, 1);
 	isl_int_set_si(cst->d, 0);
 
-	return &cst->up;
+	return &cst->poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_neginfty(struct isl_ctx *ctx)
+__isl_give isl_poly *isl_poly_neginfty(isl_ctx *ctx)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	cst = isl_upoly_cst_alloc(ctx);
+	cst = isl_poly_cst_alloc(ctx);
 	if (!cst)
 		return NULL;
 
 	isl_int_set_si(cst->n, -1);
 	isl_int_set_si(cst->d, 0);
 
-	return &cst->up;
+	return &cst->poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_nan(struct isl_ctx *ctx)
+__isl_give isl_poly *isl_poly_nan(isl_ctx *ctx)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	cst = isl_upoly_cst_alloc(ctx);
+	cst = isl_poly_cst_alloc(ctx);
 	if (!cst)
 		return NULL;
 
 	isl_int_set_si(cst->n, 0);
 	isl_int_set_si(cst->d, 0);
 
-	return &cst->up;
+	return &cst->poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_rat_cst(struct isl_ctx *ctx,
-	isl_int n, isl_int d)
+__isl_give isl_poly *isl_poly_rat_cst(isl_ctx *ctx, isl_int n, isl_int d)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	cst = isl_upoly_cst_alloc(ctx);
+	cst = isl_poly_cst_alloc(ctx);
 	if (!cst)
 		return NULL;
 
 	isl_int_set(cst->n, n);
 	isl_int_set(cst->d, d);
 
-	return &cst->up;
+	return &cst->poly;
 }
 
-__isl_give struct isl_upoly_rec *isl_upoly_alloc_rec(struct isl_ctx *ctx,
-	int var, int size)
+__isl_give isl_poly_rec *isl_poly_alloc_rec(isl_ctx *ctx, int var, int size)
 {
-	struct isl_upoly_rec *rec;
+	isl_poly_rec *rec;
 
 	isl_assert(ctx, var >= 0, return NULL);
 	isl_assert(ctx, size >= 0, return NULL);
-	rec = isl_calloc(ctx, struct isl_upoly_rec,
-			sizeof(struct isl_upoly_rec) +
-			size * sizeof(struct isl_upoly *));
+	rec = isl_calloc(ctx, struct isl_poly_rec,
+			sizeof(struct isl_poly_rec) +
+			size * sizeof(struct isl_poly *));
 	if (!rec)
 		return NULL;
 
-	rec->up.ref = 1;
-	rec->up.ctx = ctx;
+	rec->poly.ref = 1;
+	rec->poly.ctx = ctx;
 	isl_ctx_ref(ctx);
-	rec->up.var = var;
+	rec->poly.var = var;
 
 	rec->n = 0;
 	rec->size = size;
@@ -435,10 +441,46 @@ isl_ctx *isl_qpolynomial_get_ctx(__isl_keep isl_qpolynomial *qp)
 	return qp ? qp->dim->ctx : NULL;
 }
 
+/* Return the domain space of "qp".
+ */
+static __isl_keep isl_space *isl_qpolynomial_peek_domain_space(
+	__isl_keep isl_qpolynomial *qp)
+{
+	return qp ? qp->dim : NULL;
+}
+
+/* Return a copy of the domain space of "qp".
+ */
 __isl_give isl_space *isl_qpolynomial_get_domain_space(
 	__isl_keep isl_qpolynomial *qp)
 {
-	return qp ? isl_space_copy(qp->dim) : NULL;
+	return isl_space_copy(isl_qpolynomial_peek_domain_space(qp));
+}
+
+#undef TYPE
+#define TYPE		isl_qpolynomial
+#undef PEEK_SPACE
+#define PEEK_SPACE	peek_domain_space
+
+static
+#include "isl_type_has_equal_space_bin_templ.c"
+static
+#include "isl_type_check_equal_space_templ.c"
+
+#undef PEEK_SPACE
+
+/* Return a copy of the local space on which "qp" is defined.
+ */
+static __isl_give isl_local_space *isl_qpolynomial_get_domain_local_space(
+	__isl_keep isl_qpolynomial *qp)
+{
+	isl_space *space;
+
+	if (!qp)
+		return NULL;
+
+	space = isl_qpolynomial_get_domain_space(qp);
+	return isl_local_space_alloc_div(space, isl_mat_copy(qp->div));
 }
 
 __isl_give isl_space *isl_qpolynomial_get_space(__isl_keep isl_qpolynomial *qp)
@@ -454,50 +496,92 @@ __isl_give isl_space *isl_qpolynomial_get_space(__isl_keep isl_qpolynomial *qp)
 
 /* Return the number of variables of the given type in the domain of "qp".
  */
-unsigned isl_qpolynomial_domain_dim(__isl_keep isl_qpolynomial *qp,
+isl_size isl_qpolynomial_domain_dim(__isl_keep isl_qpolynomial *qp,
 	enum isl_dim_type type)
 {
-	if (!qp)
-		return 0;
+	isl_space *space;
+	isl_size dim;
+
+	space = isl_qpolynomial_peek_domain_space(qp);
+
+	if (!space)
+		return isl_size_error;
 	if (type == isl_dim_div)
 		return qp->div->n_row;
-	if (type == isl_dim_all)
-		return isl_space_dim(qp->dim, isl_dim_all) +
-				    isl_qpolynomial_domain_dim(qp, isl_dim_div);
-	return isl_space_dim(qp->dim, type);
+	dim = isl_space_dim(space, type);
+	if (dim < 0)
+		return isl_size_error;
+	if (type == isl_dim_all) {
+		isl_size n_div;
+
+		n_div = isl_qpolynomial_domain_dim(qp, isl_dim_div);
+		if (n_div < 0)
+			return isl_size_error;
+		dim += n_div;
+	}
+	return dim;
+}
+
+/* Given the type of a dimension of an isl_qpolynomial,
+ * return the type of the corresponding dimension in its domain.
+ * This function is only called for "type" equal to isl_dim_in or
+ * isl_dim_param.
+ */
+static enum isl_dim_type domain_type(enum isl_dim_type type)
+{
+	return type == isl_dim_in ? isl_dim_set : type;
 }
 
 /* Externally, an isl_qpolynomial has a map space, but internally, the
  * ls field corresponds to the domain of that space.
  */
-unsigned isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,
+isl_size isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,
 	enum isl_dim_type type)
 {
 	if (!qp)
-		return 0;
+		return isl_size_error;
 	if (type == isl_dim_out)
 		return 1;
-	if (type == isl_dim_in)
-		type = isl_dim_set;
+	type = domain_type(type);
 	return isl_qpolynomial_domain_dim(qp, type);
 }
 
+/* Return the offset of the first variable of type "type" within
+ * the variables of the domain of "qp".
+ */
+static isl_size isl_qpolynomial_domain_var_offset(
+	__isl_keep isl_qpolynomial *qp, enum isl_dim_type type)
+{
+	isl_space *space;
+
+	space = isl_qpolynomial_peek_domain_space(qp);
+	if (!space)
+		return isl_size_error;
+
+	switch (type) {
+	case isl_dim_param:
+	case isl_dim_set:	return isl_space_offset(space, type);
+	case isl_dim_div:	return isl_space_dim(space, isl_dim_all);
+	case isl_dim_cst:
+	default:
+		isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
+			"invalid dimension type", return isl_size_error);
+	}
+}
+
 /* Return the offset of the first coefficient of type "type" in
  * the domain of "qp".
  */
 unsigned isl_qpolynomial_domain_offset(__isl_keep isl_qpolynomial *qp,
 	enum isl_dim_type type)
 {
-	if (!qp)
-		return 0;
 	switch (type) {
 	case isl_dim_cst:
 		return 0;
 	case isl_dim_param:
 	case isl_dim_set:
-		return 1 + isl_space_offset(qp->dim, type);
 	case isl_dim_div:
-		return 1 + isl_space_dim(qp->dim, isl_dim_all);
+		return 1 + isl_qpolynomial_domain_var_offset(qp, type);
 	default:
 		return 0;
 	}
@@ -505,143 +589,145 @@ unsigned isl_qpolynomial_domain_offset(__isl_keep isl_qpolynomial *qp,
 
 isl_bool isl_qpolynomial_is_zero(__isl_keep isl_qpolynomial *qp)
 {
-	return qp ? isl_upoly_is_zero(qp->upoly) : isl_bool_error;
+	return qp ? isl_poly_is_zero(qp->poly) : isl_bool_error;
 }
 
 isl_bool isl_qpolynomial_is_one(__isl_keep isl_qpolynomial *qp)
 {
-	return qp ? isl_upoly_is_one(qp->upoly) : isl_bool_error;
+	return qp ? isl_poly_is_one(qp->poly) : isl_bool_error;
 }
 
 isl_bool isl_qpolynomial_is_nan(__isl_keep isl_qpolynomial *qp)
 {
-	return qp ? isl_upoly_is_nan(qp->upoly) : isl_bool_error;
+	return qp ? isl_poly_is_nan(qp->poly) : isl_bool_error;
 }
 
 isl_bool isl_qpolynomial_is_infty(__isl_keep isl_qpolynomial *qp)
 {
-	return qp ? isl_upoly_is_infty(qp->upoly) : isl_bool_error;
+	return qp ? isl_poly_is_infty(qp->poly) : isl_bool_error;
 }
 
 isl_bool isl_qpolynomial_is_neginfty(__isl_keep isl_qpolynomial *qp)
 {
-	return qp ? isl_upoly_is_neginfty(qp->upoly) : isl_bool_error;
+	return qp ? isl_poly_is_neginfty(qp->poly) : isl_bool_error;
 }
 
 int isl_qpolynomial_sgn(__isl_keep isl_qpolynomial *qp)
 {
-	return qp ? isl_upoly_sgn(qp->upoly) : 0;
+	return qp ? isl_poly_sgn(qp->poly) : 0;
 }
 
-static void upoly_free_cst(__isl_take struct isl_upoly_cst *cst)
+static void poly_free_cst(__isl_take isl_poly_cst *cst)
 {
 	isl_int_clear(cst->n);
 	isl_int_clear(cst->d);
 }
 
-static void upoly_free_rec(__isl_take struct isl_upoly_rec *rec)
+static void poly_free_rec(__isl_take isl_poly_rec *rec)
 {
 	int i;
 
 	for (i = 0; i < rec->n; ++i)
-		isl_upoly_free(rec->p[i]);
+		isl_poly_free(rec->p[i]);
 }
 
-__isl_give struct isl_upoly *isl_upoly_copy(__isl_keep struct isl_upoly *up)
+__isl_give isl_poly *isl_poly_copy(__isl_keep isl_poly *poly)
 {
-	if (!up)
+	if (!poly)
 		return NULL;
 
-	up->ref++;
-	return up;
+	poly->ref++;
+	return poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_dup_cst(__isl_keep struct isl_upoly *up)
+__isl_give isl_poly *isl_poly_dup_cst(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
-	struct isl_upoly_cst *dup;
+	isl_poly_cst *cst;
+	isl_poly_cst *dup;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
 		return NULL;
 
-	dup = isl_upoly_as_cst(isl_upoly_zero(up->ctx));
+	dup = isl_poly_as_cst(isl_poly_zero(poly->ctx));
 	if (!dup)
 		return NULL;
 	isl_int_set(dup->n, cst->n);
 	isl_int_set(dup->d, cst->d);
 
-	return &dup->up;
+	return &dup->poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_dup_rec(__isl_keep struct isl_upoly *up)
+__isl_give isl_poly *isl_poly_dup_rec(__isl_keep isl_poly *poly)
 {
 	int i;
-	struct isl_upoly_rec *rec;
-	struct isl_upoly_rec *dup;
+	isl_poly_rec *rec;
+	isl_poly_rec *dup;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		return NULL;
 
-	dup = isl_upoly_alloc_rec(up->ctx, up->var, rec->n);
+	dup = isl_poly_alloc_rec(poly->ctx, poly->var, rec->n);
 	if (!dup)
 		return NULL;
 
 	for (i = 0; i < rec->n; ++i) {
-		dup->p[i] = isl_upoly_copy(rec->p[i]);
+		dup->p[i] = isl_poly_copy(rec->p[i]);
 		if (!dup->p[i])
 			goto error;
 		dup->n++;
 	}
 
-	return &dup->up;
+	return &dup->poly;
 error:
-	isl_upoly_free(&dup->up);
+	isl_poly_free(&dup->poly);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_dup(__isl_keep struct isl_upoly *up)
+__isl_give isl_poly *isl_poly_dup(__isl_keep isl_poly *poly)
 {
-	if (!up)
-		return NULL;
+	isl_bool is_cst;
 
-	if (isl_upoly_is_cst(up))
-		return isl_upoly_dup_cst(up);
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return NULL;
+	if (is_cst)
+		return isl_poly_dup_cst(poly);
 	else
-		return isl_upoly_dup_rec(up);
+		return isl_poly_dup_rec(poly);
 }
 
-__isl_give struct isl_upoly *isl_upoly_cow(__isl_take struct isl_upoly *up)
+__isl_give isl_poly *isl_poly_cow(__isl_take isl_poly *poly)
 {
-	if (!up)
+	if (!poly)
 		return NULL;
 
-	if (up->ref == 1)
-		return up;
-	up->ref--;
-	return isl_upoly_dup(up);
+	if (poly->ref == 1)
+		return poly;
+	poly->ref--;
+	return isl_poly_dup(poly);
 }
 
-__isl_null struct isl_upoly *isl_upoly_free(__isl_take struct isl_upoly *up)
+__isl_null isl_poly *isl_poly_free(__isl_take isl_poly *poly)
 {
-	if (!up)
+	if (!poly)
 		return NULL;
 
-	if (--up->ref > 0)
+	if (--poly->ref > 0)
 		return NULL;
 
-	if (up->var < 0)
-		upoly_free_cst((struct isl_upoly_cst *)up);
+	if (poly->var < 0)
+		poly_free_cst((isl_poly_cst *) poly);
 	else
-		upoly_free_rec((struct isl_upoly_rec *)up);
+		poly_free_rec((isl_poly_rec *) poly);
 
-	isl_ctx_deref(up->ctx);
-	free(up);
+	isl_ctx_deref(poly->ctx);
+	free(poly);
 	return NULL;
 }
 
-static void isl_upoly_cst_reduce(__isl_keep struct isl_upoly_cst *cst)
+static void isl_poly_cst_reduce(__isl_keep isl_poly_cst *cst)
 {
 	isl_int gcd;
 
@@ -654,18 +740,18 @@ static void isl_upoly_cst_reduce(__isl_keep struct isl_upoly_cst *cst)
 	isl_int_clear(gcd);
 }
 
-__isl_give struct isl_upoly *isl_upoly_sum_cst(__isl_take struct isl_upoly *up1,
-	__isl_take struct isl_upoly *up2)
+__isl_give isl_poly *isl_poly_sum_cst(__isl_take isl_poly *poly1,
+	__isl_take isl_poly *poly2)
 {
-	struct isl_upoly_cst *cst1;
-	struct isl_upoly_cst *cst2;
+	isl_poly_cst *cst1;
+	isl_poly_cst *cst2;
 
-	up1 = isl_upoly_cow(up1);
-	if (!up1 || !up2)
+	poly1 = isl_poly_cow(poly1);
+	if (!poly1 || !poly2)
 		goto error;
 
-	cst1 = isl_upoly_as_cst(up1);
-	cst2 = isl_upoly_as_cst(up2);
+	cst1 = isl_poly_as_cst(poly1);
+	cst2 = isl_poly_as_cst(poly2);
 
 	if (isl_int_eq(cst1->d, cst2->d))
 		isl_int_add(cst1->n, cst1->n, cst2->n);
@@ -675,489 +761,554 @@ __isl_give struct isl_upoly *isl_upoly_sum_cst(__isl_take struct isl_upoly *up1,
 		isl_int_mul(cst1->d, cst1->d, cst2->d);
 	}
 
-	isl_upoly_cst_reduce(cst1);
+	isl_poly_cst_reduce(cst1);
 
-	isl_upoly_free(up2);
-	return up1;
+	isl_poly_free(poly2);
+	return poly1;
 error:
-	isl_upoly_free(up1);
-	isl_upoly_free(up2);
+	isl_poly_free(poly1);
+	isl_poly_free(poly2);
 	return NULL;
 }
 
-static __isl_give struct isl_upoly *replace_by_zero(
-	__isl_take struct isl_upoly *up)
+static __isl_give isl_poly *replace_by_zero(__isl_take isl_poly *poly)
 {
 	struct isl_ctx *ctx;
 
-	if (!up)
+	if (!poly)
 		return NULL;
-	ctx = up->ctx;
-	isl_upoly_free(up);
-	return isl_upoly_zero(ctx);
+	ctx = poly->ctx;
+	isl_poly_free(poly);
+	return isl_poly_zero(ctx);
 }
 
-static __isl_give struct isl_upoly *replace_by_constant_term(
-	__isl_take struct isl_upoly *up)
+static __isl_give isl_poly *replace_by_constant_term(__isl_take isl_poly *poly)
 {
-	struct isl_upoly_rec *rec;
-	struct isl_upoly *cst;
+	isl_poly_rec *rec;
+	isl_poly *cst;
 
-	if (!up)
+	if (!poly)
 		return NULL;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
-	cst = isl_upoly_copy(rec->p[0]);
-	isl_upoly_free(up);
+	cst = isl_poly_copy(rec->p[0]);
+	isl_poly_free(poly);
 	return cst;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_sum(__isl_take struct isl_upoly *up1,
-	__isl_take struct isl_upoly *up2)
+__isl_give isl_poly *isl_poly_sum(__isl_take isl_poly *poly1,
+	__isl_take isl_poly *poly2)
 {
 	int i;
-	struct isl_upoly_rec *rec1, *rec2;
+	isl_bool is_zero, is_nan, is_cst;
+	isl_poly_rec *rec1, *rec2;
 
-	if (!up1 || !up2)
+	if (!poly1 || !poly2)
 		goto error;
 
-	if (isl_upoly_is_nan(up1)) {
-		isl_upoly_free(up2);
-		return up1;
+	is_nan = isl_poly_is_nan(poly1);
+	if (is_nan < 0)
+		goto error;
+	if (is_nan) {
+		isl_poly_free(poly2);
+		return poly1;
 	}
 
-	if (isl_upoly_is_nan(up2)) {
-		isl_upoly_free(up1);
-		return up2;
+	is_nan = isl_poly_is_nan(poly2);
+	if (is_nan < 0)
+		goto error;
+	if (is_nan) {
+		isl_poly_free(poly1);
+		return poly2;
 	}
 
-	if (isl_upoly_is_zero(up1)) {
-		isl_upoly_free(up1);
-		return up2;
+	is_zero = isl_poly_is_zero(poly1);
+	if (is_zero < 0)
+		goto error;
+	if (is_zero) {
+		isl_poly_free(poly1);
+		return poly2;
 	}
 
-	if (isl_upoly_is_zero(up2)) {
-		isl_upoly_free(up2);
-		return up1;
+	is_zero = isl_poly_is_zero(poly2);
+	if (is_zero < 0)
+		goto error;
+	if (is_zero) {
+		isl_poly_free(poly2);
+		return poly1;
 	}
 
-	if (up1->var < up2->var)
-		return isl_upoly_sum(up2, up1);
+	if (poly1->var < poly2->var)
+		return isl_poly_sum(poly2, poly1);
 
-	if (up2->var < up1->var) {
-		struct isl_upoly_rec *rec;
-		if (isl_upoly_is_infty(up2) || isl_upoly_is_neginfty(up2)) {
-			isl_upoly_free(up1);
-			return up2;
+	if (poly2->var < poly1->var) {
+		isl_poly_rec *rec;
+		isl_bool is_infty;
+
+		is_infty = isl_poly_is_infty(poly2);
+		if (is_infty >= 0 && !is_infty)
+			is_infty = isl_poly_is_neginfty(poly2);
+		if (is_infty < 0)
+			goto error;
+		if (is_infty) {
+			isl_poly_free(poly1);
+			return poly2;
 		}
-		up1 = isl_upoly_cow(up1);
-		rec = isl_upoly_as_rec(up1);
+		poly1 = isl_poly_cow(poly1);
+		rec = isl_poly_as_rec(poly1);
 		if (!rec)
 			goto error;
-		rec->p[0] = isl_upoly_sum(rec->p[0], up2);
+		rec->p[0] = isl_poly_sum(rec->p[0], poly2);
 		if (rec->n == 1)
-			up1 = replace_by_constant_term(up1);
-		return up1;
+			poly1 = replace_by_constant_term(poly1);
+		return poly1;
 	}
 
-	if (isl_upoly_is_cst(up1))
-		return isl_upoly_sum_cst(up1, up2);
+	is_cst = isl_poly_is_cst(poly1);
+	if (is_cst < 0)
+		goto error;
+	if (is_cst)
+		return isl_poly_sum_cst(poly1, poly2);
 
-	rec1 = isl_upoly_as_rec(up1);
-	rec2 = isl_upoly_as_rec(up2);
+	rec1 = isl_poly_as_rec(poly1);
+	rec2 = isl_poly_as_rec(poly2);
 	if (!rec1 || !rec2)
 		goto error;
 
 	if (rec1->n < rec2->n)
-		return isl_upoly_sum(up2, up1);
+		return isl_poly_sum(poly2, poly1);
 
-	up1 = isl_upoly_cow(up1);
-	rec1 = isl_upoly_as_rec(up1);
+	poly1 = isl_poly_cow(poly1);
+	rec1 = isl_poly_as_rec(poly1);
 	if (!rec1)
 		goto error;
 
 	for (i = rec2->n - 1; i >= 0; --i) {
-		rec1->p[i] = isl_upoly_sum(rec1->p[i],
-					    isl_upoly_copy(rec2->p[i]));
+		isl_bool is_zero;
+
+		rec1->p[i] = isl_poly_sum(rec1->p[i],
+					    isl_poly_copy(rec2->p[i]));
 		if (!rec1->p[i])
 			goto error;
-		if (i == rec1->n - 1 && isl_upoly_is_zero(rec1->p[i])) {
-			isl_upoly_free(rec1->p[i]);
+		if (i != rec1->n - 1)
+			continue;
+		is_zero = isl_poly_is_zero(rec1->p[i]);
+		if (is_zero < 0)
+			goto error;
+		if (is_zero) {
+			isl_poly_free(rec1->p[i]);
 			rec1->n--;
 		}
 	}
 
 	if (rec1->n == 0)
-		up1 = replace_by_zero(up1);
+		poly1 = replace_by_zero(poly1);
 	else if (rec1->n == 1)
-		up1 = replace_by_constant_term(up1);
+		poly1 = replace_by_constant_term(poly1);
 
-	isl_upoly_free(up2);
+	isl_poly_free(poly2);
 
-	return up1;
+	return poly1;
 error:
-	isl_upoly_free(up1);
-	isl_upoly_free(up2);
+	isl_poly_free(poly1);
+	isl_poly_free(poly2);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_cst_add_isl_int(
-	__isl_take struct isl_upoly *up, isl_int v)
+__isl_give isl_poly *isl_poly_cst_add_isl_int(__isl_take isl_poly *poly,
+	isl_int v)
 {
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	up = isl_upoly_cow(up);
-	if (!up)
+	poly = isl_poly_cow(poly);
+	if (!poly)
 		return NULL;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 
 	isl_int_addmul(cst->n, cst->d, v);
 
-	return up;
+	return poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_add_isl_int(
-	__isl_take struct isl_upoly *up, isl_int v)
+__isl_give isl_poly *isl_poly_add_isl_int(__isl_take isl_poly *poly, isl_int v)
 {
-	struct isl_upoly_rec *rec;
-
-	if (!up)
-		return NULL;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (isl_upoly_is_cst(up))
-		return isl_upoly_cst_add_isl_int(up, v);
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_poly_free(poly);
+	if (is_cst)
+		return isl_poly_cst_add_isl_int(poly, v);
 
-	up = isl_upoly_cow(up);
-	rec = isl_upoly_as_rec(up);
+	poly = isl_poly_cow(poly);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
-	rec->p[0] = isl_upoly_add_isl_int(rec->p[0], v);
+	rec->p[0] = isl_poly_add_isl_int(rec->p[0], v);
 	if (!rec->p[0])
 		goto error;
 
-	return up;
+	return poly;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_cst_mul_isl_int(
-	__isl_take struct isl_upoly *up, isl_int v)
+__isl_give isl_poly *isl_poly_cst_mul_isl_int(__isl_take isl_poly *poly,
+	isl_int v)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_zero;
+	isl_poly_cst *cst;
 
-	if (isl_upoly_is_zero(up))
-		return up;
+	is_zero = isl_poly_is_zero(poly);
+	if (is_zero < 0)
+		return isl_poly_free(poly);
+	if (is_zero)
+		return poly;
 
-	up = isl_upoly_cow(up);
-	if (!up)
+	poly = isl_poly_cow(poly);
+	if (!poly)
 		return NULL;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 
 	isl_int_mul(cst->n, cst->n, v);
 
-	return up;
+	return poly;
 }
 
-__isl_give struct isl_upoly *isl_upoly_mul_isl_int(
-	__isl_take struct isl_upoly *up, isl_int v)
+__isl_give isl_poly *isl_poly_mul_isl_int(__isl_take isl_poly *poly, isl_int v)
 {
 	int i;
-	struct isl_upoly_rec *rec;
-
-	if (!up)
-		return NULL;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (isl_upoly_is_cst(up))
-		return isl_upoly_cst_mul_isl_int(up, v);
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_poly_free(poly);
+	if (is_cst)
+		return isl_poly_cst_mul_isl_int(poly, v);
 
-	up = isl_upoly_cow(up);
-	rec = isl_upoly_as_rec(up);
+	poly = isl_poly_cow(poly);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
 	for (i = 0; i < rec->n; ++i) {
-		rec->p[i] = isl_upoly_mul_isl_int(rec->p[i], v);
+		rec->p[i] = isl_poly_mul_isl_int(rec->p[i], v);
 		if (!rec->p[i])
 			goto error;
 	}
 
-	return up;
+	return poly;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
-/* Multiply the constant polynomial "up" by "v".
+/* Multiply the constant polynomial "poly" by "v".
  */
-static __isl_give struct isl_upoly *isl_upoly_cst_scale_val(
-	__isl_take struct isl_upoly *up, __isl_keep isl_val *v)
+static __isl_give isl_poly *isl_poly_cst_scale_val(__isl_take isl_poly *poly,
+	__isl_keep isl_val *v)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_zero;
+	isl_poly_cst *cst;
 
-	if (isl_upoly_is_zero(up))
-		return up;
+	is_zero = isl_poly_is_zero(poly);
+	if (is_zero < 0)
+		return isl_poly_free(poly);
+	if (is_zero)
+		return poly;
 
-	up = isl_upoly_cow(up);
-	if (!up)
+	poly = isl_poly_cow(poly);
+	if (!poly)
 		return NULL;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 
 	isl_int_mul(cst->n, cst->n, v->n);
 	isl_int_mul(cst->d, cst->d, v->d);
-	isl_upoly_cst_reduce(cst);
+	isl_poly_cst_reduce(cst);
 
-	return up;
+	return poly;
 }
 
-/* Multiply the polynomial "up" by "v".
+/* Multiply the polynomial "poly" by "v".
  */
-static __isl_give struct isl_upoly *isl_upoly_scale_val(
-	__isl_take struct isl_upoly *up, __isl_keep isl_val *v)
+static __isl_give isl_poly *isl_poly_scale_val(__isl_take isl_poly *poly,
+	__isl_keep isl_val *v)
 {
 	int i;
-	struct isl_upoly_rec *rec;
-
-	if (!up)
-		return NULL;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (isl_upoly_is_cst(up))
-		return isl_upoly_cst_scale_val(up, v);
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_poly_free(poly);
+	if (is_cst)
+		return isl_poly_cst_scale_val(poly, v);
 
-	up = isl_upoly_cow(up);
-	rec = isl_upoly_as_rec(up);
+	poly = isl_poly_cow(poly);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
 	for (i = 0; i < rec->n; ++i) {
-		rec->p[i] = isl_upoly_scale_val(rec->p[i], v);
+		rec->p[i] = isl_poly_scale_val(rec->p[i], v);
 		if (!rec->p[i])
 			goto error;
 	}
 
-	return up;
+	return poly;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_mul_cst(__isl_take struct isl_upoly *up1,
-	__isl_take struct isl_upoly *up2)
+__isl_give isl_poly *isl_poly_mul_cst(__isl_take isl_poly *poly1,
+	__isl_take isl_poly *poly2)
 {
-	struct isl_upoly_cst *cst1;
-	struct isl_upoly_cst *cst2;
+	isl_poly_cst *cst1;
+	isl_poly_cst *cst2;
 
-	up1 = isl_upoly_cow(up1);
-	if (!up1 || !up2)
+	poly1 = isl_poly_cow(poly1);
+	if (!poly1 || !poly2)
 		goto error;
 
-	cst1 = isl_upoly_as_cst(up1);
-	cst2 = isl_upoly_as_cst(up2);
+	cst1 = isl_poly_as_cst(poly1);
+	cst2 = isl_poly_as_cst(poly2);
 
 	isl_int_mul(cst1->n, cst1->n, cst2->n);
 	isl_int_mul(cst1->d, cst1->d, cst2->d);
 
-	isl_upoly_cst_reduce(cst1);
+	isl_poly_cst_reduce(cst1);
 
-	isl_upoly_free(up2);
-	return up1;
+	isl_poly_free(poly2);
+	return poly1;
 error:
-	isl_upoly_free(up1);
-	isl_upoly_free(up2);
+	isl_poly_free(poly1);
+	isl_poly_free(poly2);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_mul_rec(__isl_take struct isl_upoly *up1,
-	__isl_take struct isl_upoly *up2)
+__isl_give isl_poly *isl_poly_mul_rec(__isl_take isl_poly *poly1,
+	__isl_take isl_poly *poly2)
 {
-	struct isl_upoly_rec *rec1;
-	struct isl_upoly_rec *rec2;
-	struct isl_upoly_rec *res = NULL;
+	isl_poly_rec *rec1;
+	isl_poly_rec *rec2;
+	isl_poly_rec *res = NULL;
 	int i, j;
 	int size;
 
-	rec1 = isl_upoly_as_rec(up1);
-	rec2 = isl_upoly_as_rec(up2);
+	rec1 = isl_poly_as_rec(poly1);
+	rec2 = isl_poly_as_rec(poly2);
 	if (!rec1 || !rec2)
 		goto error;
 	size = rec1->n + rec2->n - 1;
-	res = isl_upoly_alloc_rec(up1->ctx, up1->var, size);
+	res = isl_poly_alloc_rec(poly1->ctx, poly1->var, size);
 	if (!res)
 		goto error;
 
 	for (i = 0; i < rec1->n; ++i) {
-		res->p[i] = isl_upoly_mul(isl_upoly_copy(rec2->p[0]),
-					    isl_upoly_copy(rec1->p[i]));
+		res->p[i] = isl_poly_mul(isl_poly_copy(rec2->p[0]),
+					    isl_poly_copy(rec1->p[i]));
 		if (!res->p[i])
 			goto error;
 		res->n++;
 	}
 	for (; i < size; ++i) {
-		res->p[i] = isl_upoly_zero(up1->ctx);
+		res->p[i] = isl_poly_zero(poly1->ctx);
 		if (!res->p[i])
 			goto error;
 		res->n++;
 	}
 	for (i = 0; i < rec1->n; ++i) {
 		for (j = 1; j < rec2->n; ++j) {
-			struct isl_upoly *up;
-			up = isl_upoly_mul(isl_upoly_copy(rec2->p[j]),
-					    isl_upoly_copy(rec1->p[i]));
-			res->p[i + j] = isl_upoly_sum(res->p[i + j], up);
+			isl_poly *poly;
+			poly = isl_poly_mul(isl_poly_copy(rec2->p[j]),
+					    isl_poly_copy(rec1->p[i]));
+			res->p[i + j] = isl_poly_sum(res->p[i + j], poly);
 			if (!res->p[i + j])
 				goto error;
 		}
 	}
 
-	isl_upoly_free(up1);
-	isl_upoly_free(up2);
+	isl_poly_free(poly1);
+	isl_poly_free(poly2);
 
-	return &res->up;
+	return &res->poly;
 error:
-	isl_upoly_free(up1);
-	isl_upoly_free(up2);
-	isl_upoly_free(&res->up);
+	isl_poly_free(poly1);
+	isl_poly_free(poly2);
+	isl_poly_free(&res->poly);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_mul(__isl_take struct isl_upoly *up1,
-	__isl_take struct isl_upoly *up2)
+__isl_give isl_poly *isl_poly_mul(__isl_take isl_poly *poly1,
+	__isl_take isl_poly *poly2)
 {
-	if (!up1 || !up2)
+	isl_bool is_zero, is_nan, is_one, is_cst;
+
+	if (!poly1 || !poly2)
 		goto error;
 
-	if (isl_upoly_is_nan(up1)) {
-		isl_upoly_free(up2);
-		return up1;
+	is_nan = isl_poly_is_nan(poly1);
+	if (is_nan < 0)
+		goto error;
+	if (is_nan) {
+		isl_poly_free(poly2);
+		return poly1;
 	}
 
-	if (isl_upoly_is_nan(up2)) {
-		isl_upoly_free(up1);
-		return up2;
+	is_nan = isl_poly_is_nan(poly2);
+	if (is_nan < 0)
+		goto error;
+	if (is_nan) {
+		isl_poly_free(poly1);
+		return poly2;
 	}
 
-	if (isl_upoly_is_zero(up1)) {
-		isl_upoly_free(up2);
-		return up1;
+	is_zero = isl_poly_is_zero(poly1);
+	if (is_zero < 0)
+		goto error;
+	if (is_zero) {
+		isl_poly_free(poly2);
+		return poly1;
 	}
 
-	if (isl_upoly_is_zero(up2)) {
-		isl_upoly_free(up1);
-		return up2;
+	is_zero = isl_poly_is_zero(poly2);
+	if (is_zero < 0)
+		goto error;
+	if (is_zero) {
+		isl_poly_free(poly1);
+		return poly2;
 	}
 
-	if (isl_upoly_is_one(up1)) {
-		isl_upoly_free(up1);
-		return up2;
+	is_one = isl_poly_is_one(poly1);
+	if (is_one < 0)
+		goto error;
+	if (is_one) {
+		isl_poly_free(poly1);
+		return poly2;
 	}
 
-	if (isl_upoly_is_one(up2)) {
-		isl_upoly_free(up2);
-		return up1;
+	is_one = isl_poly_is_one(poly2);
+	if (is_one < 0)
+		goto error;
+	if (is_one) {
+		isl_poly_free(poly2);
+		return poly1;
 	}
 
-	if (up1->var < up2->var)
-		return isl_upoly_mul(up2, up1);
+	if (poly1->var < poly2->var)
+		return isl_poly_mul(poly2, poly1);
 
-	if (up2->var < up1->var) {
+	if (poly2->var < poly1->var) {
 		int i;
-		struct isl_upoly_rec *rec;
-		if (isl_upoly_is_infty(up2) || isl_upoly_is_neginfty(up2)) {
-			isl_ctx *ctx = up1->ctx;
-			isl_upoly_free(up1);
-			isl_upoly_free(up2);
-			return isl_upoly_nan(ctx);
+		isl_poly_rec *rec;
+		isl_bool is_infty;
+
+		is_infty = isl_poly_is_infty(poly2);
+		if (is_infty >= 0 && !is_infty)
+			is_infty = isl_poly_is_neginfty(poly2);
+		if (is_infty < 0)
+			goto error;
+		if (is_infty) {
+			isl_ctx *ctx = poly1->ctx;
+			isl_poly_free(poly1);
+			isl_poly_free(poly2);
+			return isl_poly_nan(ctx);
 		}
-		up1 = isl_upoly_cow(up1);
-		rec = isl_upoly_as_rec(up1);
+		poly1 = isl_poly_cow(poly1);
+		rec = isl_poly_as_rec(poly1);
 		if (!rec)
 			goto error;
 
 		for (i = 0; i < rec->n; ++i) {
-			rec->p[i] = isl_upoly_mul(rec->p[i],
-						    isl_upoly_copy(up2));
+			rec->p[i] = isl_poly_mul(rec->p[i],
+						isl_poly_copy(poly2));
 			if (!rec->p[i])
 				goto error;
 		}
-		isl_upoly_free(up2);
-		return up1;
+		isl_poly_free(poly2);
+		return poly1;
 	}
 
-	if (isl_upoly_is_cst(up1))
-		return isl_upoly_mul_cst(up1, up2);
+	is_cst = isl_poly_is_cst(poly1);
+	if (is_cst < 0)
+		goto error;
+	if (is_cst)
+		return isl_poly_mul_cst(poly1, poly2);
 
-	return isl_upoly_mul_rec(up1, up2);
+	return isl_poly_mul_rec(poly1, poly2);
 error:
-	isl_upoly_free(up1);
-	isl_upoly_free(up2);
+	isl_poly_free(poly1);
+	isl_poly_free(poly2);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_pow(__isl_take struct isl_upoly *up,
-	unsigned power)
+__isl_give isl_poly *isl_poly_pow(__isl_take isl_poly *poly, unsigned power)
 {
-	struct isl_upoly *res;
+	isl_poly *res;
 
-	if (!up)
+	if (!poly)
 		return NULL;
 	if (power == 1)
-		return up;
+		return poly;
 
 	if (power % 2)
-		res = isl_upoly_copy(up);
+		res = isl_poly_copy(poly);
 	else
-		res = isl_upoly_one(up->ctx);
+		res = isl_poly_one(poly->ctx);
 
 	while (power >>= 1) {
-		up = isl_upoly_mul(up, isl_upoly_copy(up));
+		poly = isl_poly_mul(poly, isl_poly_copy(poly));
 		if (power % 2)
-			res = isl_upoly_mul(res, isl_upoly_copy(up));
+			res = isl_poly_mul(res, isl_poly_copy(poly));
 	}
 
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return res;
 }
 
-__isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *dim,
-	unsigned n_div, __isl_take struct isl_upoly *up)
+__isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *space,
+	unsigned n_div, __isl_take isl_poly *poly)
 {
 	struct isl_qpolynomial *qp = NULL;
-	unsigned total;
+	isl_size total;
 
-	if (!dim || !up)
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0 || !poly)
 		goto error;
 
-	if (!isl_space_is_set(dim))
-		isl_die(isl_space_get_ctx(dim), isl_error_invalid,
+	if (!isl_space_is_set(space))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
 			"domain of polynomial should be a set", goto error);
 
-	total = isl_space_dim(dim, isl_dim_all);
-
-	qp = isl_calloc_type(dim->ctx, struct isl_qpolynomial);
+	qp = isl_calloc_type(space->ctx, struct isl_qpolynomial);
 	if (!qp)
 		goto error;
 
 	qp->ref = 1;
-	qp->div = isl_mat_alloc(dim->ctx, n_div, 1 + 1 + total + n_div);
+	qp->div = isl_mat_alloc(space->ctx, n_div, 1 + 1 + total + n_div);
 	if (!qp->div)
 		goto error;
 
-	qp->dim = dim;
-	qp->upoly = up;
+	qp->dim = space;
+	qp->poly = poly;
 
 	return qp;
 error:
-	isl_space_free(dim);
-	isl_upoly_free(up);
+	isl_space_free(space);
+	isl_poly_free(poly);
 	isl_qpolynomial_free(qp);
 	return NULL;
 }
@@ -1179,7 +1330,7 @@ __isl_give isl_qpolynomial *isl_qpolynomial_dup(__isl_keep isl_qpolynomial *qp)
 		return NULL;
 
 	dup = isl_qpolynomial_alloc(isl_space_copy(qp->dim), qp->div->n_row,
-				    isl_upoly_copy(qp->upoly));
+				    isl_poly_copy(qp->poly));
 	if (!dup)
 		return NULL;
 	isl_mat_free(dup->div);
@@ -1215,69 +1366,72 @@ __isl_null isl_qpolynomial *isl_qpolynomial_free(
 
 	isl_space_free(qp->dim);
 	isl_mat_free(qp->div);
-	isl_upoly_free(qp->upoly);
+	isl_poly_free(qp->poly);
 
 	free(qp);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_var_pow(isl_ctx *ctx, int pos, int power)
+__isl_give isl_poly *isl_poly_var_pow(isl_ctx *ctx, int pos, int power)
 {
 	int i;
-	struct isl_upoly_rec *rec;
-	struct isl_upoly_cst *cst;
+	isl_poly_rec *rec;
+	isl_poly_cst *cst;
 
-	rec = isl_upoly_alloc_rec(ctx, pos, 1 + power);
+	rec = isl_poly_alloc_rec(ctx, pos, 1 + power);
 	if (!rec)
 		return NULL;
 	for (i = 0; i < 1 + power; ++i) {
-		rec->p[i] = isl_upoly_zero(ctx);
+		rec->p[i] = isl_poly_zero(ctx);
 		if (!rec->p[i])
 			goto error;
 		rec->n++;
 	}
-	cst = isl_upoly_as_cst(rec->p[power]);
+	cst = isl_poly_as_cst(rec->p[power]);
 	isl_int_set_si(cst->n, 1);
 
-	return &rec->up;
+	return &rec->poly;
 error:
-	isl_upoly_free(&rec->up);
+	isl_poly_free(&rec->poly);
 	return NULL;
 }
 
 /* r array maps original positions to new positions.
  */
-static __isl_give struct isl_upoly *reorder(__isl_take struct isl_upoly *up,
-	int *r)
+static __isl_give isl_poly *reorder(__isl_take isl_poly *poly, int *r)
 {
 	int i;
-	struct isl_upoly_rec *rec;
-	struct isl_upoly *base;
-	struct isl_upoly *res;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
+	isl_poly *base;
+	isl_poly *res;
 
-	if (isl_upoly_is_cst(up))
-		return up;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_poly_free(poly);
+	if (is_cst)
+		return poly;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
-	isl_assert(up->ctx, rec->n >= 1, goto error);
+	isl_assert(poly->ctx, rec->n >= 1, goto error);
 
-	base = isl_upoly_var_pow(up->ctx, r[up->var], 1);
-	res = reorder(isl_upoly_copy(rec->p[rec->n - 1]), r);
+	base = isl_poly_var_pow(poly->ctx, r[poly->var], 1);
+	res = reorder(isl_poly_copy(rec->p[rec->n - 1]), r);
 
 	for (i = rec->n - 2; i >= 0; --i) {
-		res = isl_upoly_mul(res, isl_upoly_copy(base));
-		res = isl_upoly_sum(res, reorder(isl_upoly_copy(rec->p[i]), r));
+		res = isl_poly_mul(res, isl_poly_copy(base));
+		res = isl_poly_sum(res, reorder(isl_poly_copy(rec->p[i]), r));
 	}
 
-	isl_upoly_free(base);
-	isl_upoly_free(up);
+	isl_poly_free(base);
+	isl_poly_free(poly);
 
 	return res;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
@@ -1344,14 +1498,16 @@ static __isl_give isl_qpolynomial *sort_divs(__isl_take isl_qpolynomial *qp)
 	struct isl_div_sort_info *array = NULL;
 	int *pos = NULL, *at = NULL;
 	int *reordering = NULL;
-	unsigned div_pos;
+	isl_size div_pos;
 
 	if (!qp)
 		return NULL;
 	if (qp->div->n_row <= 1)
 		return qp;
 
-	div_pos = isl_space_dim(qp->dim, isl_dim_all);
+	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
+	if (div_pos < 0)
+		return isl_qpolynomial_free(qp);
 
 	array = isl_alloc_array(qp->div->ctx, struct isl_div_sort_info,
 				qp->div->n_row);
@@ -1400,9 +1556,9 @@ static __isl_give isl_qpolynomial *sort_divs(__isl_take isl_qpolynomial *qp)
 		reordering[div_pos + array[i].row] = div_pos + i - skip;
 	}
 
-	qp->upoly = reorder(qp->upoly, reordering);
+	qp->poly = reorder(qp->poly, reordering);
 
-	if (!qp->upoly || !qp->div)
+	if (!qp->poly || !qp->div)
 		goto error;
 
 	free(at);
@@ -1420,28 +1576,32 @@ static __isl_give isl_qpolynomial *sort_divs(__isl_take isl_qpolynomial *qp)
 	return NULL;
 }
 
-static __isl_give struct isl_upoly *expand(__isl_take struct isl_upoly *up,
-	int *exp, int first)
+static __isl_give isl_poly *expand(__isl_take isl_poly *poly, int *exp,
+	int first)
 {
 	int i;
-	struct isl_upoly_rec *rec;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (isl_upoly_is_cst(up))
-		return up;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_poly_free(poly);
+	if (is_cst)
+		return poly;
 
-	if (up->var < first)
-		return up;
+	if (poly->var < first)
+		return poly;
 
-	if (exp[up->var - first] == up->var - first)
-		return up;
+	if (exp[poly->var - first] == poly->var - first)
+		return poly;
 
-	up = isl_upoly_cow(up);
-	if (!up)
+	poly = isl_poly_cow(poly);
+	if (!poly)
 		goto error;
 
-	up->var = exp[up->var - first] + first;
+	poly->var = exp[poly->var - first] + first;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
@@ -1451,9 +1611,9 @@ static __isl_give struct isl_upoly *expand(__isl_take struct isl_upoly *up,
 			goto error;
 	}
 
-	return up;
+	return poly;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
@@ -1492,10 +1652,10 @@ static __isl_give isl_qpolynomial *with_merged_divs(
 	isl_mat_free(qp2->div);
 	qp2->div = isl_mat_copy(div);
 
-	qp1->upoly = expand(qp1->upoly, exp1, div->n_col - div->n_row - 2);
-	qp2->upoly = expand(qp2->upoly, exp2, div->n_col - div->n_row - 2);
+	qp1->poly = expand(qp1->poly, exp1, div->n_col - div->n_row - 2);
+	qp2->poly = expand(qp2->poly, exp2, div->n_col - div->n_row - 2);
 
-	if (!qp1->upoly || !qp2->upoly)
+	if (!qp1->poly || !qp2->poly)
 		goto error;
 
 	isl_mat_free(div);
@@ -1519,21 +1679,20 @@ __isl_give isl_qpolynomial *isl_qpolynomial_add(__isl_take isl_qpolynomial *qp1,
 
 	qp1 = isl_qpolynomial_cow(qp1);
 
-	if (!qp1 || !qp2)
+	if (isl_qpolynomial_check_equal_space(qp1, qp2) < 0)
 		goto error;
 
 	if (qp1->div->n_row < qp2->div->n_row)
 		return isl_qpolynomial_add(qp2, qp1);
 
-	isl_assert(qp1->dim->ctx, isl_space_is_equal(qp1->dim, qp2->dim), goto error);
 	compatible = compatible_divs(qp1->div, qp2->div);
 	if (compatible < 0)
 		goto error;
 	if (!compatible)
 		return with_merged_divs(isl_qpolynomial_add, qp1, qp2);
 
-	qp1->upoly = isl_upoly_sum(qp1->upoly, isl_upoly_copy(qp2->upoly));
-	if (!qp1->upoly)
+	qp1->poly = isl_poly_sum(qp1->poly, isl_poly_copy(qp2->poly));
+	if (!qp1->poly)
 		goto error;
 
 	isl_qpolynomial_free(qp2);
@@ -1571,8 +1730,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_add_isl_int(
 	if (!qp)
 		return NULL;
 
-	qp->upoly = isl_upoly_add_isl_int(qp->upoly, v);
-	if (!qp->upoly)
+	qp->poly = isl_poly_add_isl_int(qp->poly, v);
+	if (!qp->poly)
 		goto error;
 
 	return qp;
@@ -1607,8 +1766,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_mul_isl_int(
 	if (!qp)
 		return NULL;
 
-	qp->upoly = isl_upoly_mul_isl_int(qp->upoly, v);
-	if (!qp->upoly)
+	qp->poly = isl_poly_mul_isl_int(qp->poly, v);
+	if (!qp->poly)
 		goto error;
 
 	return qp;
@@ -1653,8 +1812,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_scale_val(
 	if (!qp)
 		goto error;
 
-	qp->upoly = isl_upoly_scale_val(qp->upoly, v);
-	if (!qp->upoly)
+	qp->poly = isl_poly_scale_val(qp->poly, v);
+	if (!qp->poly)
 		qp = isl_qpolynomial_free(qp);
 
 	isl_val_free(v);
@@ -1694,21 +1853,20 @@ __isl_give isl_qpolynomial *isl_qpolynomial_mul(__isl_take isl_qpolynomial *qp1,
 
 	qp1 = isl_qpolynomial_cow(qp1);
 
-	if (!qp1 || !qp2)
+	if (isl_qpolynomial_check_equal_space(qp1, qp2) < 0)
 		goto error;
 
 	if (qp1->div->n_row < qp2->div->n_row)
 		return isl_qpolynomial_mul(qp2, qp1);
 
-	isl_assert(qp1->dim->ctx, isl_space_is_equal(qp1->dim, qp2->dim), goto error);
 	compatible = compatible_divs(qp1->div, qp2->div);
 	if (compatible < 0)
 		goto error;
 	if (!compatible)
 		return with_merged_divs(isl_qpolynomial_mul, qp1, qp2);
 
-	qp1->upoly = isl_upoly_mul(qp1->upoly, isl_upoly_copy(qp2->upoly));
-	if (!qp1->upoly)
+	qp1->poly = isl_poly_mul(qp1->poly, isl_poly_copy(qp2->poly));
+	if (!qp1->poly)
 		goto error;
 
 	isl_qpolynomial_free(qp2);
@@ -1728,8 +1886,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_qpolynomial *qp,
 	if (!qp)
 		return NULL;
 
-	qp->upoly = isl_upoly_pow(qp->upoly, power);
-	if (!qp->upoly)
+	qp->poly = isl_poly_pow(qp->poly, power);
+	if (!qp->poly)
 		goto error;
 
 	return qp;
@@ -1760,111 +1918,112 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_pow(
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain(
-	__isl_take isl_space *dim)
+	__isl_take isl_space *domain)
 {
-	if (!dim)
+	if (!domain)
 		return NULL;
-	return isl_qpolynomial_alloc(dim, 0, isl_upoly_zero(dim->ctx));
+	return isl_qpolynomial_alloc(domain, 0, isl_poly_zero(domain->ctx));
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(
-	__isl_take isl_space *dim)
+	__isl_take isl_space *domain)
 {
-	if (!dim)
+	if (!domain)
 		return NULL;
-	return isl_qpolynomial_alloc(dim, 0, isl_upoly_one(dim->ctx));
+	return isl_qpolynomial_alloc(domain, 0, isl_poly_one(domain->ctx));
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(
-	__isl_take isl_space *dim)
+	__isl_take isl_space *domain)
 {
-	if (!dim)
+	if (!domain)
 		return NULL;
-	return isl_qpolynomial_alloc(dim, 0, isl_upoly_infty(dim->ctx));
+	return isl_qpolynomial_alloc(domain, 0, isl_poly_infty(domain->ctx));
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(
-	__isl_take isl_space *dim)
+	__isl_take isl_space *domain)
 {
-	if (!dim)
+	if (!domain)
 		return NULL;
-	return isl_qpolynomial_alloc(dim, 0, isl_upoly_neginfty(dim->ctx));
+	return isl_qpolynomial_alloc(domain, 0, isl_poly_neginfty(domain->ctx));
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(
-	__isl_take isl_space *dim)
+	__isl_take isl_space *domain)
 {
-	if (!dim)
+	if (!domain)
 		return NULL;
-	return isl_qpolynomial_alloc(dim, 0, isl_upoly_nan(dim->ctx));
+	return isl_qpolynomial_alloc(domain, 0, isl_poly_nan(domain->ctx));
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_cst_on_domain(
-	__isl_take isl_space *dim,
+	__isl_take isl_space *domain,
 	isl_int v)
 {
 	struct isl_qpolynomial *qp;
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	if (!dim)
-		return NULL;
-
-	qp = isl_qpolynomial_alloc(dim, 0, isl_upoly_zero(dim->ctx));
+	qp = isl_qpolynomial_zero_on_domain(domain);
 	if (!qp)
 		return NULL;
 
-	cst = isl_upoly_as_cst(qp->upoly);
+	cst = isl_poly_as_cst(qp->poly);
 	isl_int_set(cst->n, v);
 
 	return qp;
 }
 
-int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
+isl_bool isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
 	isl_int *n, isl_int *d)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
 	if (!qp)
-		return -1;
+		return isl_bool_error;
 
-	if (!isl_upoly_is_cst(qp->upoly))
-		return 0;
+	is_cst = isl_poly_is_cst(qp->poly);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	cst = isl_upoly_as_cst(qp->upoly);
+	cst = isl_poly_as_cst(qp->poly);
 	if (!cst)
-		return -1;
+		return isl_bool_error;
 
 	if (n)
 		isl_int_set(*n, cst->n);
 	if (d)
 		isl_int_set(*d, cst->d);
 
-	return 1;
+	return isl_bool_true;
 }
 
-/* Return the constant term of "up".
+/* Return the constant term of "poly".
  */
-static __isl_give isl_val *isl_upoly_get_constant_val(
-	__isl_keep struct isl_upoly *up)
+static __isl_give isl_val *isl_poly_get_constant_val(__isl_keep isl_poly *poly)
 {
-	struct isl_upoly_cst *cst;
+	isl_bool is_cst;
+	isl_poly_cst *cst;
 
-	if (!up)
+	if (!poly)
 		return NULL;
 
-	while (!isl_upoly_is_cst(up)) {
-		struct isl_upoly_rec *rec;
+	while ((is_cst = isl_poly_is_cst(poly)) == isl_bool_false) {
+		isl_poly_rec *rec;
 
-		rec = isl_upoly_as_rec(up);
+		rec = isl_poly_as_rec(poly);
 		if (!rec)
 			return NULL;
-		up = rec->p[0];
+		poly = rec->p[0];
 	}
+	if (is_cst < 0)
+		return NULL;
 
-	cst = isl_upoly_as_cst(up);
+	cst = isl_poly_as_cst(poly);
 	if (!cst)
 		return NULL;
-	return isl_val_rat_from_isl_int(cst->up.ctx, cst->n, cst->d);
+	return isl_val_rat_from_isl_int(cst->poly.ctx, cst->n, cst->d);
 }
 
 /* Return the constant term of "qp".
@@ -1875,51 +2034,49 @@ __isl_give isl_val *isl_qpolynomial_get_constant_val(
 	if (!qp)
 		return NULL;
 
-	return isl_upoly_get_constant_val(qp->upoly);
+	return isl_poly_get_constant_val(qp->poly);
 }
 
-int isl_upoly_is_affine(__isl_keep struct isl_upoly *up)
+isl_bool isl_poly_is_affine(__isl_keep isl_poly *poly)
 {
-	int is_cst;
-	struct isl_upoly_rec *rec;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (!up)
-		return -1;
+	if (!poly)
+		return isl_bool_error;
 
-	if (up->var < 0)
-		return 1;
+	if (poly->var < 0)
+		return isl_bool_true;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
-		return -1;
+		return isl_bool_error;
 
 	if (rec->n > 2)
-		return 0;
+		return isl_bool_false;
 
-	isl_assert(up->ctx, rec->n > 1, return -1);
+	isl_assert(poly->ctx, rec->n > 1, return isl_bool_error);
 
-	is_cst = isl_upoly_is_cst(rec->p[1]);
-	if (is_cst < 0)
-		return -1;
-	if (!is_cst)
-		return 0;
+	is_cst = isl_poly_is_cst(rec->p[1]);
+	if (is_cst < 0 || !is_cst)
+		return is_cst;
 
-	return isl_upoly_is_affine(rec->p[0]);
+	return isl_poly_is_affine(rec->p[0]);
 }
 
-int isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp)
+isl_bool isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp)
 {
 	if (!qp)
-		return -1;
+		return isl_bool_error;
 
 	if (qp->div->n_row > 0)
-		return 0;
+		return isl_bool_false;
 
-	return isl_upoly_is_affine(qp->upoly);
+	return isl_poly_is_affine(qp->poly);
 }
 
 static void update_coeff(__isl_keep isl_vec *aff,
-	__isl_keep struct isl_upoly_cst *cst, int pos)
+	__isl_keep isl_poly_cst *cst, int pos)
 {
 	isl_int gcd;
 	isl_int f;
@@ -1938,56 +2095,55 @@ static void update_coeff(__isl_keep isl_vec *aff,
 	isl_int_clear(f);
 }
 
-int isl_upoly_update_affine(__isl_keep struct isl_upoly *up,
-	__isl_keep isl_vec *aff)
+int isl_poly_update_affine(__isl_keep isl_poly *poly, __isl_keep isl_vec *aff)
 {
-	struct isl_upoly_cst *cst;
-	struct isl_upoly_rec *rec;
+	isl_poly_cst *cst;
+	isl_poly_rec *rec;
 
-	if (!up || !aff)
+	if (!poly || !aff)
 		return -1;
 
-	if (up->var < 0) {
-		struct isl_upoly_cst *cst;
+	if (poly->var < 0) {
+		isl_poly_cst *cst;
 
-		cst = isl_upoly_as_cst(up);
+		cst = isl_poly_as_cst(poly);
 		if (!cst)
 			return -1;
 		update_coeff(aff, cst, 0);
 		return 0;
 	}
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		return -1;
-	isl_assert(up->ctx, rec->n == 2, return -1);
+	isl_assert(poly->ctx, rec->n == 2, return -1);
 
-	cst = isl_upoly_as_cst(rec->p[1]);
+	cst = isl_poly_as_cst(rec->p[1]);
 	if (!cst)
 		return -1;
-	update_coeff(aff, cst, 1 + up->var);
+	update_coeff(aff, cst, 1 + poly->var);
 
-	return isl_upoly_update_affine(rec->p[0], aff);
+	return isl_poly_update_affine(rec->p[0], aff);
 }
 
 __isl_give isl_vec *isl_qpolynomial_extract_affine(
 	__isl_keep isl_qpolynomial *qp)
 {
 	isl_vec *aff;
-	unsigned d;
+	isl_size d;
 
-	if (!qp)
+	d = isl_qpolynomial_domain_dim(qp, isl_dim_all);
+	if (d < 0)
 		return NULL;
 
-	d = isl_space_dim(qp->dim, isl_dim_all);
-	aff = isl_vec_alloc(qp->div->ctx, 2 + d + qp->div->n_row);
+	aff = isl_vec_alloc(qp->div->ctx, 2 + d);
 	if (!aff)
 		return NULL;
 
-	isl_seq_clr(aff->el + 1, 1 + d + qp->div->n_row);
+	isl_seq_clr(aff->el + 1, 1 + d);
 	isl_int_set_si(aff->el[0], 1);
 
-	if (isl_upoly_update_affine(qp->upoly, aff) < 0)
+	if (isl_poly_update_affine(qp->poly, aff) < 0)
 		goto error;
 
 	return aff;
@@ -2021,7 +2177,7 @@ int isl_qpolynomial_plain_cmp(__isl_keep isl_qpolynomial *qp1,
 	if (cmp != 0)
 		return cmp;
 
-	return isl_upoly_plain_cmp(qp1->upoly, qp2->upoly);
+	return isl_poly_plain_cmp(qp1->poly, qp2->poly);
 }
 
 /* Is "qp1" obviously equal to "qp2"?
@@ -2047,137 +2203,149 @@ isl_bool isl_qpolynomial_plain_is_equal(__isl_keep isl_qpolynomial *qp1,
 	if (equal < 0 || !equal)
 		return equal;
 
-	return isl_upoly_is_equal(qp1->upoly, qp2->upoly);
+	return isl_poly_is_equal(qp1->poly, qp2->poly);
 }
 
-static void upoly_update_den(__isl_keep struct isl_upoly *up, isl_int *d)
+static isl_stat poly_update_den(__isl_keep isl_poly *poly, isl_int *d)
 {
 	int i;
-	struct isl_upoly_rec *rec;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (isl_upoly_is_cst(up)) {
-		struct isl_upoly_cst *cst;
-		cst = isl_upoly_as_cst(up);
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_stat_error;
+	if (is_cst) {
+		isl_poly_cst *cst;
+		cst = isl_poly_as_cst(poly);
 		if (!cst)
-			return;
+			return isl_stat_error;
 		isl_int_lcm(*d, *d, cst->d);
-		return;
+		return isl_stat_ok;
 	}
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
-		return;
+		return isl_stat_error;
 
 	for (i = 0; i < rec->n; ++i)
-		upoly_update_den(rec->p[i], d);
+		poly_update_den(rec->p[i], d);
+
+	return isl_stat_ok;
 }
 
-void isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp, isl_int *d)
+__isl_give isl_val *isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp)
 {
-	isl_int_set_si(*d, 1);
+	isl_val *d;
+
 	if (!qp)
-		return;
-	upoly_update_den(qp->upoly, d);
+		return NULL;
+	d = isl_val_one(isl_qpolynomial_get_ctx(qp));
+	if (!d)
+		return NULL;
+	if (poly_update_den(qp->poly, &d->n) < 0)
+		return isl_val_free(d);
+	return d;
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_var_pow_on_domain(
-	__isl_take isl_space *dim, int pos, int power)
+	__isl_take isl_space *domain, int pos, int power)
 {
 	struct isl_ctx *ctx;
 
-	if (!dim)
+	if (!domain)
 		return NULL;
 
-	ctx = dim->ctx;
+	ctx = domain->ctx;
 
-	return isl_qpolynomial_alloc(dim, 0, isl_upoly_var_pow(ctx, pos, power));
+	return isl_qpolynomial_alloc(domain, 0,
+					isl_poly_var_pow(ctx, pos, power));
 }
 
-__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_var_on_domain(
+	__isl_take isl_space *domain, enum isl_dim_type type, unsigned pos)
 {
-	if (!dim)
-		return NULL;
-
-	isl_assert(dim->ctx, isl_space_dim(dim, isl_dim_in) == 0, goto error);
-	isl_assert(dim->ctx, pos < isl_space_dim(dim, type), goto error);
+	if (isl_space_check_is_set(domain ) < 0)
+		goto error;
+	if (isl_space_check_range(domain, type, pos, 1) < 0)
+		goto error;
 
-	if (type == isl_dim_set)
-		pos += isl_space_dim(dim, isl_dim_param);
+	pos += isl_space_offset(domain, type);
 
-	return isl_qpolynomial_var_pow_on_domain(dim, pos, 1);
+	return isl_qpolynomial_var_pow_on_domain(domain, pos, 1);
 error:
-	isl_space_free(dim);
+	isl_space_free(domain);
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_subs(__isl_take struct isl_upoly *up,
-	unsigned first, unsigned n, __isl_keep struct isl_upoly **subs)
+__isl_give isl_poly *isl_poly_subs(__isl_take isl_poly *poly,
+	unsigned first, unsigned n, __isl_keep isl_poly **subs)
 {
 	int i;
-	struct isl_upoly_rec *rec;
-	struct isl_upoly *base, *res;
-
-	if (!up)
-		return NULL;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
+	isl_poly *base, *res;
 
-	if (isl_upoly_is_cst(up))
-		return up;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_poly_free(poly);
+	if (is_cst)
+		return poly;
 
-	if (up->var < first)
-		return up;
+	if (poly->var < first)
+		return poly;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
-	isl_assert(up->ctx, rec->n >= 1, goto error);
+	isl_assert(poly->ctx, rec->n >= 1, goto error);
 
-	if (up->var >= first + n)
-		base = isl_upoly_var_pow(up->ctx, up->var, 1);
+	if (poly->var >= first + n)
+		base = isl_poly_var_pow(poly->ctx, poly->var, 1);
 	else
-		base = isl_upoly_copy(subs[up->var - first]);
+		base = isl_poly_copy(subs[poly->var - first]);
 
-	res = isl_upoly_subs(isl_upoly_copy(rec->p[rec->n - 1]), first, n, subs);
+	res = isl_poly_subs(isl_poly_copy(rec->p[rec->n - 1]), first, n, subs);
 	for (i = rec->n - 2; i >= 0; --i) {
-		struct isl_upoly *t;
-		t = isl_upoly_subs(isl_upoly_copy(rec->p[i]), first, n, subs);
-		res = isl_upoly_mul(res, isl_upoly_copy(base));
-		res = isl_upoly_sum(res, t);
+		isl_poly *t;
+		t = isl_poly_subs(isl_poly_copy(rec->p[i]), first, n, subs);
+		res = isl_poly_mul(res, isl_poly_copy(base));
+		res = isl_poly_sum(res, t);
 	}
 
-	isl_upoly_free(base);
-	isl_upoly_free(up);
+	isl_poly_free(base);
+	isl_poly_free(poly);
 				
 	return res;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }	
 
-__isl_give struct isl_upoly *isl_upoly_from_affine(isl_ctx *ctx, isl_int *f,
+__isl_give isl_poly *isl_poly_from_affine(isl_ctx *ctx, isl_int *f,
 	isl_int denom, unsigned len)
 {
 	int i;
-	struct isl_upoly *up;
+	isl_poly *poly;
 
 	isl_assert(ctx, len >= 1, return NULL);
 
-	up = isl_upoly_rat_cst(ctx, f[0], denom);
+	poly = isl_poly_rat_cst(ctx, f[0], denom);
 	for (i = 0; i < len - 1; ++i) {
-		struct isl_upoly *t;
-		struct isl_upoly *c;
+		isl_poly *t;
+		isl_poly *c;
 
 		if (isl_int_is_zero(f[1 + i]))
 			continue;
 
-		c = isl_upoly_rat_cst(ctx, f[1 + i], denom);
-		t = isl_upoly_var_pow(ctx, i, 1);
-		t = isl_upoly_mul(c, t);
-		up = isl_upoly_sum(up, t);
+		c = isl_poly_rat_cst(ctx, f[1 + i], denom);
+		t = isl_poly_var_pow(ctx, i, 1);
+		t = isl_poly_mul(c, t);
+		poly = isl_poly_sum(poly, t);
 	}
 
-	return up;
+	return poly;
 }
 
 /* Remove common factor of non-constant terms and denominator.
@@ -2206,12 +2374,12 @@ static void normalize_div(__isl_keep isl_qpolynomial *qp, int div)
  * of any other integer divisions.
  */
 static __isl_give isl_qpolynomial *substitute_div(
-	__isl_take isl_qpolynomial *qp,
-	int div, __isl_take struct isl_upoly *s)
+	__isl_take isl_qpolynomial *qp, int div, __isl_take isl_poly *s)
 {
 	int i;
-	int total;
+	isl_size div_pos;
 	int *reordering;
+	isl_ctx *ctx;
 
 	if (!qp || !s)
 		goto error;
@@ -2220,31 +2388,34 @@ static __isl_give isl_qpolynomial *substitute_div(
 	if (!qp)
 		goto error;
 
-	total = isl_space_dim(qp->dim, isl_dim_all);
-	qp->upoly = isl_upoly_subs(qp->upoly, total + div, 1, &s);
-	if (!qp->upoly)
+	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
+	if (div_pos < 0)
+		goto error;
+	qp->poly = isl_poly_subs(qp->poly, div_pos + div, 1, &s);
+	if (!qp->poly)
 		goto error;
 
-	reordering = isl_alloc_array(qp->dim->ctx, int, total + qp->div->n_row);
+	ctx = isl_qpolynomial_get_ctx(qp);
+	reordering = isl_alloc_array(ctx, int, div_pos + qp->div->n_row);
 	if (!reordering)
 		goto error;
-	for (i = 0; i < total + div; ++i)
+	for (i = 0; i < div_pos + div; ++i)
 		reordering[i] = i;
-	for (i = total + div + 1; i < total + qp->div->n_row; ++i)
+	for (i = div_pos + div + 1; i < div_pos + qp->div->n_row; ++i)
 		reordering[i] = i - 1;
 	qp->div = isl_mat_drop_rows(qp->div, div, 1);
-	qp->div = isl_mat_drop_cols(qp->div, 2 + total + div, 1);
-	qp->upoly = reorder(qp->upoly, reordering);
+	qp->div = isl_mat_drop_cols(qp->div, 2 + div_pos + div, 1);
+	qp->poly = reorder(qp->poly, reordering);
 	free(reordering);
 
-	if (!qp->upoly || !qp->div)
+	if (!qp->poly || !qp->div)
 		goto error;
 
-	isl_upoly_free(s);
+	isl_poly_free(s);
 	return qp;
 error:
 	isl_qpolynomial_free(qp);
-	isl_upoly_free(s);
+	isl_poly_free(s);
 	return NULL;
 }
 
@@ -2255,27 +2426,27 @@ static __isl_give isl_qpolynomial *substitute_non_divs(
 	__isl_take isl_qpolynomial *qp)
 {
 	int i, j;
-	int total;
-	struct isl_upoly *s;
+	isl_size div_pos;
+	isl_poly *s;
 
-	if (!qp)
-		return NULL;
+	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
+	if (div_pos < 0)
+		return isl_qpolynomial_free(qp);
 
-	total = isl_space_dim(qp->dim, isl_dim_all);
 	for (i = 0; qp && i < qp->div->n_row; ++i) {
 		if (!isl_int_is_one(qp->div->row[i][0]))
 			continue;
 		for (j = i + 1; j < qp->div->n_row; ++j) {
-			if (isl_int_is_zero(qp->div->row[j][2 + total + i]))
+			if (isl_int_is_zero(qp->div->row[j][2 + div_pos + i]))
 				continue;
 			isl_seq_combine(qp->div->row[j] + 1,
 				qp->div->ctx->one, qp->div->row[j] + 1,
-				qp->div->row[j][2 + total + i],
-				qp->div->row[i] + 1, 1 + total + i);
-			isl_int_set_si(qp->div->row[j][2 + total + i], 0);
+				qp->div->row[j][2 + div_pos + i],
+				qp->div->row[i] + 1, 1 + div_pos + i);
+			isl_int_set_si(qp->div->row[j][2 + div_pos + i], 0);
 			normalize_div(qp, j);
 		}
-		s = isl_upoly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
+		s = isl_poly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
 					qp->div->row[i][0], qp->div->n_col - 1);
 		qp = substitute_div(qp, i, s);
 		--i;
@@ -2385,15 +2556,15 @@ static __isl_give isl_qpolynomial *reduce_divs(__isl_take isl_qpolynomial *qp)
 	int i;
 	isl_ctx *ctx;
 	isl_mat *mat;
-	struct isl_upoly **s;
-	unsigned o_div, n_div, total;
-
-	if (!qp)
-		return NULL;
+	isl_poly **s;
+	unsigned o_div;
+	isl_size n_div, total, new_n_div;
 
 	total = isl_qpolynomial_domain_dim(qp, isl_dim_all);
 	n_div = isl_qpolynomial_domain_dim(qp, isl_dim_div);
 	o_div = isl_qpolynomial_domain_offset(qp, isl_dim_div);
+	if (total < 0 || n_div < 0)
+		return isl_qpolynomial_free(qp);
 	ctx = isl_qpolynomial_get_ctx(qp);
 	mat = isl_mat_zero(ctx, n_div, 1 + total);
 
@@ -2411,24 +2582,27 @@ static __isl_give isl_qpolynomial *reduce_divs(__isl_take isl_qpolynomial *qp)
 	if (!mat)
 		goto error;
 
-	s = isl_alloc_array(ctx, struct isl_upoly *, n_div);
+	s = isl_alloc_array(ctx, struct isl_poly *, n_div);
 	if (n_div && !s)
 		goto error;
 	for (i = 0; i < n_div; ++i)
-		s[i] = isl_upoly_from_affine(ctx, mat->row[i], ctx->one,
+		s[i] = isl_poly_from_affine(ctx, mat->row[i], ctx->one,
 					    1 + total);
-	qp->upoly = isl_upoly_subs(qp->upoly, o_div - 1, n_div, s);
+	qp->poly = isl_poly_subs(qp->poly, o_div - 1, n_div, s);
 	for (i = 0; i < n_div; ++i)
-		isl_upoly_free(s[i]);
+		isl_poly_free(s[i]);
 	free(s);
-	if (!qp->upoly)
+	if (!qp->poly)
 		goto error;
 
 	isl_mat_free(mat);
 
 	qp = substitute_non_divs(qp);
 	qp = sort_divs(qp);
-	if (qp && isl_qpolynomial_domain_dim(qp, isl_dim_div) < n_div)
+	new_n_div = isl_qpolynomial_domain_dim(qp, isl_dim_div);
+	if (new_n_div < 0)
+		return isl_qpolynomial_free(qp);
+	if (new_n_div < n_div)
 		return reduce_divs(qp);
 
 	return qp;
@@ -2439,19 +2613,16 @@ static __isl_give isl_qpolynomial *reduce_divs(__isl_take isl_qpolynomial *qp)
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(
-	__isl_take isl_space *dim, const isl_int n, const isl_int d)
+	__isl_take isl_space *domain, const isl_int n, const isl_int d)
 {
 	struct isl_qpolynomial *qp;
-	struct isl_upoly_cst *cst;
-
-	if (!dim)
-		return NULL;
+	isl_poly_cst *cst;
 
-	qp = isl_qpolynomial_alloc(dim, 0, isl_upoly_zero(dim->ctx));
+	qp = isl_qpolynomial_zero_on_domain(domain);
 	if (!qp)
 		return NULL;
 
-	cst = isl_upoly_as_cst(qp->upoly);
+	cst = isl_poly_as_cst(qp->poly);
 	isl_int_set(cst->n, n);
 	isl_int_set(cst->d, d);
 
@@ -2464,58 +2635,57 @@ __isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain(
 	__isl_take isl_space *domain, __isl_take isl_val *val)
 {
 	isl_qpolynomial *qp;
-	struct isl_upoly_cst *cst;
+	isl_poly_cst *cst;
 
-	if (!domain || !val)
-		goto error;
-
-	qp = isl_qpolynomial_alloc(isl_space_copy(domain), 0,
-					isl_upoly_zero(domain->ctx));
-	if (!qp)
+	qp = isl_qpolynomial_zero_on_domain(domain);
+	if (!qp || !val)
 		goto error;
 
-	cst = isl_upoly_as_cst(qp->upoly);
+	cst = isl_poly_as_cst(qp->poly);
 	isl_int_set(cst->n, val->n);
 	isl_int_set(cst->d, val->d);
 
-	isl_space_free(domain);
 	isl_val_free(val);
 	return qp;
 error:
-	isl_space_free(domain);
 	isl_val_free(val);
+	isl_qpolynomial_free(qp);
 	return NULL;
 }
 
-static int up_set_active(__isl_keep struct isl_upoly *up, int *active, int d)
+static isl_stat poly_set_active(__isl_keep isl_poly *poly, int *active, int d)
 {
-	struct isl_upoly_rec *rec;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 	int i;
 
-	if (!up)
-		return -1;
-
-	if (isl_upoly_is_cst(up))
-		return 0;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_stat_error;
+	if (is_cst)
+		return isl_stat_ok;
 
-	if (up->var < d)
-		active[up->var] = 1;
+	if (poly->var < d)
+		active[poly->var] = 1;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	for (i = 0; i < rec->n; ++i)
-		if (up_set_active(rec->p[i], active, d) < 0)
-			return -1;
+		if (poly_set_active(rec->p[i], active, d) < 0)
+			return isl_stat_error;
 
-	return 0;
+	return isl_stat_ok;
 }
 
-static int set_active(__isl_keep isl_qpolynomial *qp, int *active)
+static isl_stat set_active(__isl_keep isl_qpolynomial *qp, int *active)
 {
 	int i, j;
-	int d = isl_space_dim(qp->dim, isl_dim_all);
+	isl_size d;
+	isl_space *space;
 
-	if (!qp || !active)
-		return -1;
+	space = isl_qpolynomial_peek_domain_space(qp);
+	d = isl_space_dim(space, isl_dim_all);
+	if (d < 0 || !active)
+		return isl_stat_error;
 
 	for (i = 0; i < d; ++i)
 		for (j = 0; j < qp->div->n_row; ++j) {
@@ -2525,34 +2695,46 @@ static int set_active(__isl_keep isl_qpolynomial *qp, int *active)
 			break;
 		}
 
-	return up_set_active(qp->upoly, active, d);
+	return poly_set_active(qp->poly, active, d);
 }
 
+#undef TYPE
+#define TYPE	isl_qpolynomial
+static
+#include "check_type_range_templ.c"
+
 isl_bool isl_qpolynomial_involves_dims(__isl_keep isl_qpolynomial *qp,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
 	int i;
 	int *active = NULL;
 	isl_bool involves = isl_bool_false;
+	isl_size offset;
+	isl_size d;
+	isl_space *space;
 
 	if (!qp)
 		return isl_bool_error;
 	if (n == 0)
 		return isl_bool_false;
 
-	isl_assert(qp->dim->ctx,
-		    first + n <= isl_qpolynomial_dim(qp, type),
-		    return isl_bool_error);
+	if (isl_qpolynomial_check_range(qp, type, first, n) < 0)
+		return isl_bool_error;
 	isl_assert(qp->dim->ctx, type == isl_dim_param ||
 				 type == isl_dim_in, return isl_bool_error);
 
-	active = isl_calloc_array(qp->dim->ctx, int,
-					isl_space_dim(qp->dim, isl_dim_all));
+	space = isl_qpolynomial_peek_domain_space(qp);
+	d = isl_space_dim(space, isl_dim_all);
+	if (d < 0)
+		return isl_bool_error;
+	active = isl_calloc_array(qp->dim->ctx, int, d);
 	if (set_active(qp, active) < 0)
 		goto error;
 
-	if (type == isl_dim_in)
-		first += isl_space_dim(qp->dim, isl_dim_param);
+	offset = isl_qpolynomial_domain_var_offset(qp, domain_type(type));
+	if (offset < 0)
+		goto error;
+	first += offset;
 	for (i = 0; i < n; ++i)
 		if (active[first + i]) {
 			involves = isl_bool_true;
@@ -2574,7 +2756,7 @@ static __isl_give isl_qpolynomial *remove_redundant_divs(
 	__isl_take isl_qpolynomial *qp)
 {
 	int i, j;
-	int d;
+	isl_size div_pos;
 	int len;
 	int skip;
 	int *active = NULL;
@@ -2588,25 +2770,27 @@ static __isl_give isl_qpolynomial *remove_redundant_divs(
 	if (qp->div->n_row == 0)
 		return qp;
 
-	d = isl_space_dim(qp->dim, isl_dim_all);
+	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
+	if (div_pos < 0)
+		return isl_qpolynomial_free(qp);
 	len = qp->div->n_col - 2;
 	ctx = isl_qpolynomial_get_ctx(qp);
 	active = isl_calloc_array(ctx, int, len);
 	if (!active)
 		goto error;
 
-	if (up_set_active(qp->upoly, active, len) < 0)
+	if (poly_set_active(qp->poly, active, len) < 0)
 		goto error;
 
 	for (i = qp->div->n_row - 1; i >= 0; --i) {
-		if (!active[d + i]) {
+		if (!active[div_pos + i]) {
 			redundant = 1;
 			continue;
 		}
 		for (j = 0; j < i; ++j) {
-			if (isl_int_is_zero(qp->div->row[i][2 + d + j]))
+			if (isl_int_is_zero(qp->div->row[i][2 + div_pos + j]))
 				continue;
-			active[d + j] = 1;
+			active[div_pos + j] = 1;
 			break;
 		}
 	}
@@ -2620,24 +2804,24 @@ static __isl_give isl_qpolynomial *remove_redundant_divs(
 	if (!reordering)
 		goto error;
 
-	for (i = 0; i < d; ++i)
+	for (i = 0; i < div_pos; ++i)
 		reordering[i] = i;
 
 	skip = 0;
 	n_div = qp->div->n_row;
 	for (i = 0; i < n_div; ++i) {
-		if (!active[d + i]) {
+		if (!active[div_pos + i]) {
 			qp->div = isl_mat_drop_rows(qp->div, i - skip, 1);
 			qp->div = isl_mat_drop_cols(qp->div,
-						    2 + d + i - skip, 1);
+						    2 + div_pos + i - skip, 1);
 			skip++;
 		}
-		reordering[d + i] = d + i - skip;
+		reordering[div_pos + i] = div_pos + i - skip;
 	}
 
-	qp->upoly = reorder(qp->upoly, reordering);
+	qp->poly = reorder(qp->poly, reordering);
 
-	if (!qp->upoly || !qp->div)
+	if (!qp->poly || !qp->div)
 		goto error;
 
 	free(active);
@@ -2651,37 +2835,37 @@ static __isl_give isl_qpolynomial *remove_redundant_divs(
 	return NULL;
 }
 
-__isl_give struct isl_upoly *isl_upoly_drop(__isl_take struct isl_upoly *up,
+__isl_give isl_poly *isl_poly_drop(__isl_take isl_poly *poly,
 	unsigned first, unsigned n)
 {
 	int i;
-	struct isl_upoly_rec *rec;
+	isl_poly_rec *rec;
 
-	if (!up)
+	if (!poly)
 		return NULL;
-	if (n == 0 || up->var < 0 || up->var < first)
-		return up;
-	if (up->var < first + n) {
-		up = replace_by_constant_term(up);
-		return isl_upoly_drop(up, first, n);
+	if (n == 0 || poly->var < 0 || poly->var < first)
+		return poly;
+	if (poly->var < first + n) {
+		poly = replace_by_constant_term(poly);
+		return isl_poly_drop(poly, first, n);
 	}
-	up = isl_upoly_cow(up);
-	if (!up)
+	poly = isl_poly_cow(poly);
+	if (!poly)
 		return NULL;
-	up->var -= n;
-	rec = isl_upoly_as_rec(up);
+	poly->var -= n;
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
 	for (i = 0; i < rec->n; ++i) {
-		rec->p[i] = isl_upoly_drop(rec->p[i], first, n);
+		rec->p[i] = isl_poly_drop(rec->p[i], first, n);
 		if (!rec->p[i])
 			goto error;
 	}
 
-	return up;
+	return poly;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
@@ -2696,8 +2880,7 @@ __isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name(
 		isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
 			"cannot set name of output/set dimension",
 			return isl_qpolynomial_free(qp));
-	if (type == isl_dim_in)
-		type = isl_dim_set;
+	type = domain_type(type);
 	qp->dim = isl_space_set_dim_name(qp->dim, type, pos, s);
 	if (!qp->dim)
 		goto error;
@@ -2711,14 +2894,17 @@ __isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(
 	__isl_take isl_qpolynomial *qp,
 	enum isl_dim_type type, unsigned first, unsigned n)
 {
+	isl_size offset;
+
 	if (!qp)
 		return NULL;
 	if (type == isl_dim_out)
 		isl_die(qp->dim->ctx, isl_error_invalid,
 			"cannot drop output/set dimension",
 			goto error);
-	if (type == isl_dim_in)
-		type = isl_dim_set;
+	if (isl_qpolynomial_check_range(qp, type, first, n) < 0)
+		return isl_qpolynomial_free(qp);
+	type = domain_type(type);
 	if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))
 		return qp;
 
@@ -2726,8 +2912,6 @@ __isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(
 	if (!qp)
 		return NULL;
 
-	isl_assert(qp->dim->ctx, first + n <= isl_space_dim(qp->dim, type),
-			goto error);
 	isl_assert(qp->dim->ctx, type == isl_dim_param ||
 				 type == isl_dim_set, goto error);
 
@@ -2735,15 +2919,17 @@ __isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(
 	if (!qp->dim)
 		goto error;
 
-	if (type == isl_dim_set)
-		first += isl_space_dim(qp->dim, isl_dim_param);
+	offset = isl_qpolynomial_domain_var_offset(qp, type);
+	if (offset < 0)
+		goto error;
+	first += offset;
 
 	qp->div = isl_mat_drop_cols(qp->div, 2 + first, n);
 	if (!qp->div)
 		goto error;
 
-	qp->upoly = isl_upoly_drop(qp->upoly, first, n);
-	if (!qp->upoly)
+	qp->poly = isl_poly_drop(qp->poly, first, n);
+	if (!qp->poly)
 		goto error;
 
 	return qp;
@@ -2759,10 +2945,12 @@ __isl_give isl_qpolynomial *isl_qpolynomial_project_domain_on_params(
 	__isl_take isl_qpolynomial *qp)
 {
 	isl_space *space;
-	unsigned n;
-	int involves;
+	isl_size n;
+	isl_bool involves;
 
 	n = isl_qpolynomial_dim(qp, isl_dim_in);
+	if (n < 0)
+		return isl_qpolynomial_free(qp);
 	involves = isl_qpolynomial_involves_dims(qp, isl_dim_in, 0, n);
 	if (involves < 0)
 		return isl_qpolynomial_free(qp);
@@ -2784,7 +2972,7 @@ static __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities_lifted(
 	isl_int denom;
 	unsigned total;
 	unsigned n_div;
-	struct isl_upoly *up;
+	isl_poly *poly;
 
 	if (!eq)
 		goto error;
@@ -2800,7 +2988,7 @@ static __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities_lifted(
 	if (!qp->div)
 		goto error;
 
-	total = 1 + isl_space_dim(eq->dim, isl_dim_all);
+	total = isl_basic_set_offset(eq, isl_dim_div);
 	n_div = eq->n_div;
 	isl_int_init(denom);
 	for (i = 0; i < eq->n_eq; ++i) {
@@ -2821,14 +3009,14 @@ static __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities_lifted(
 		isl_int_abs(denom, eq->eq[i][j]);
 		isl_int_set_si(eq->eq[i][j], 0);
 
-		up = isl_upoly_from_affine(qp->dim->ctx,
+		poly = isl_poly_from_affine(qp->dim->ctx,
 						   eq->eq[i], denom, total);
-		qp->upoly = isl_upoly_subs(qp->upoly, j - 1, 1, &up);
-		isl_upoly_free(up);
+		qp->poly = isl_poly_subs(qp->poly, j - 1, 1, &poly);
+		isl_poly_free(poly);
 	}
 	isl_int_clear(denom);
 
-	if (!qp->upoly)
+	if (!qp->poly)
 		goto error;
 
 	isl_basic_set_free(eq);
@@ -2859,32 +3047,6 @@ __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities(
 	return NULL;
 }
 
-static __isl_give isl_basic_set *add_div_constraints(
-	__isl_take isl_basic_set *bset, __isl_take isl_mat *div)
-{
-	int i;
-	unsigned total;
-
-	if (!bset || !div)
-		goto error;
-
-	bset = isl_basic_set_extend_constraints(bset, 0, 2 * div->n_row);
-	if (!bset)
-		goto error;
-	total = isl_basic_set_total_dim(bset);
-	for (i = 0; i < div->n_row; ++i)
-		if (isl_basic_set_add_div_constraints_var(bset,
-				    total - div->n_row + i, div->row[i]) < 0)
-			goto error;
-
-	isl_mat_free(div);
-	return bset;
-error:
-	isl_mat_free(div);
-	isl_basic_set_free(bset);
-	return NULL;
-}
-
 /* Look for equalities among the variables shared by context and qp
  * and the integer divisions of qp, if any.
  * The equalities are then used to eliminate variables and/or integer
@@ -2893,26 +3055,14 @@ static __isl_give isl_basic_set *add_div_constraints(
 __isl_give isl_qpolynomial *isl_qpolynomial_gist(
 	__isl_take isl_qpolynomial *qp, __isl_take isl_set *context)
 {
+	isl_local_space *ls;
 	isl_basic_set *aff;
 
-	if (!qp)
-		goto error;
-	if (qp->div->n_row > 0) {
-		isl_basic_set *bset;
-		context = isl_set_add_dims(context, isl_dim_set,
-					    qp->div->n_row);
-		bset = isl_basic_set_universe(isl_set_get_space(context));
-		bset = add_div_constraints(bset, isl_mat_copy(qp->div));
-		context = isl_set_intersect(context,
-					    isl_set_from_basic_set(bset));
-	}
+	ls = isl_qpolynomial_get_domain_local_space(qp);
+	context = isl_local_space_lift_set(ls, context);
 
 	aff = isl_set_affine_hull(context);
 	return isl_qpolynomial_substitute_equalities_lifted(qp, aff);
-error:
-	isl_qpolynomial_free(qp);
-	isl_set_free(context);
-	return NULL;
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
@@ -2924,29 +3074,23 @@ __isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
 	return isl_qpolynomial_gist(qp, dom_context);
 }
 
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
-	__isl_take isl_qpolynomial *qp)
+/* Return a zero isl_qpolynomial in the given space.
+ *
+ * This is a helper function for isl_pw_*_as_* that ensures a uniform
+ * interface over all piecewise types.
+ */
+static __isl_give isl_qpolynomial *isl_qpolynomial_zero_in_space(
+	__isl_take isl_space *space)
 {
-	isl_set *dom;
-
-	if (!qp)
-		return NULL;
-	if (isl_qpolynomial_is_zero(qp)) {
-		isl_space *dim = isl_qpolynomial_get_space(qp);
-		isl_qpolynomial_free(qp);
-		return isl_pw_qpolynomial_zero(dim);
-	}
-
-	dom = isl_set_universe(isl_qpolynomial_get_domain_space(qp));
-	return isl_pw_qpolynomial_alloc(dom, qp);
+	return isl_qpolynomial_zero_on_domain(isl_space_domain(space));
 }
 
 #define isl_qpolynomial_involves_nan isl_qpolynomial_is_nan
 
 #undef PW
 #define PW isl_pw_qpolynomial
-#undef EL
-#define EL isl_qpolynomial
+#undef BASE
+#define BASE qpolynomial
 #undef EL_IS_ZERO
 #define EL_IS_ZERO is_zero
 #undef ZERO
@@ -2958,10 +3102,15 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
 #undef DEFAULT_IS_ZERO
 #define DEFAULT_IS_ZERO 1
 
-#define NO_PULLBACK
-
 #include <isl_pw_templ.c>
 #include <isl_pw_eval.c>
+#include <isl_pw_insert_dims_templ.c>
+#include <isl_pw_lift_templ.c>
+#include <isl_pw_morph_templ.c>
+#include <isl_pw_move_dims_templ.c>
+#include <isl_pw_neg_templ.c>
+#include <isl_pw_opt_templ.c>
+#include <isl_pw_sub_templ.c>
 
 #undef BASE
 #define BASE pw_qpolynomial
@@ -3056,46 +3205,49 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
 	return NULL;
 }
 
-__isl_give isl_val *isl_upoly_eval(__isl_take struct isl_upoly *up,
+__isl_give isl_val *isl_poly_eval(__isl_take isl_poly *poly,
 	__isl_take isl_vec *vec)
 {
 	int i;
-	struct isl_upoly_rec *rec;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 	isl_val *res;
 	isl_val *base;
 
-	if (isl_upoly_is_cst(up)) {
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		goto error;
+	if (is_cst) {
 		isl_vec_free(vec);
-		res = isl_upoly_get_constant_val(up);
-		isl_upoly_free(up);
+		res = isl_poly_get_constant_val(poly);
+		isl_poly_free(poly);
 		return res;
 	}
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec || !vec)
 		goto error;
 
-	isl_assert(up->ctx, rec->n >= 1, goto error);
+	isl_assert(poly->ctx, rec->n >= 1, goto error);
 
-	base = isl_val_rat_from_isl_int(up->ctx,
-					vec->el[1 + up->var], vec->el[0]);
+	base = isl_val_rat_from_isl_int(poly->ctx,
+					vec->el[1 + poly->var], vec->el[0]);
 
-	res = isl_upoly_eval(isl_upoly_copy(rec->p[rec->n - 1]),
+	res = isl_poly_eval(isl_poly_copy(rec->p[rec->n - 1]),
 				isl_vec_copy(vec));
 
 	for (i = rec->n - 2; i >= 0; --i) {
 		res = isl_val_mul(res, isl_val_copy(base));
-		res = isl_val_add(res,
-			    isl_upoly_eval(isl_upoly_copy(rec->p[i]),
+		res = isl_val_add(res, isl_poly_eval(isl_poly_copy(rec->p[i]),
 							    isl_vec_copy(vec)));
 	}
 
 	isl_val_free(base);
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	isl_vec_free(vec);
 	return res;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	isl_vec_free(vec);
 	return NULL;
 }
@@ -3132,7 +3284,7 @@ __isl_give isl_val *isl_qpolynomial_eval(__isl_take isl_qpolynomial *qp,
 
 	ext = isl_local_extend_point_vec(qp->div, isl_vec_copy(pnt->vec));
 
-	v = isl_upoly_eval(isl_upoly_copy(qp->upoly), ext);
+	v = isl_poly_eval(isl_poly_copy(qp->poly), ext);
 
 	isl_qpolynomial_free(qp);
 	isl_point_free(pnt);
@@ -3144,8 +3296,7 @@ __isl_give isl_val *isl_qpolynomial_eval(__isl_take isl_qpolynomial *qp,
 	return NULL;
 }
 
-int isl_upoly_cmp(__isl_keep struct isl_upoly_cst *cst1,
-	__isl_keep struct isl_upoly_cst *cst2)
+int isl_poly_cmp(__isl_keep isl_poly_cst *cst1, __isl_keep isl_poly_cst *cst2)
 {
 	int cmp;
 	isl_int t;
@@ -3171,8 +3322,9 @@ __isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
 		isl_die(qp->div->ctx, isl_error_invalid,
 			"cannot insert output/set dimensions",
 			goto error);
-	if (type == isl_dim_in)
-		type = isl_dim_set;
+	if (isl_qpolynomial_check_range(qp, type, first, 0) < 0)
+		return isl_qpolynomial_free(qp);
+	type = domain_type(type);
 	if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))
 		return qp;
 
@@ -3180,9 +3332,6 @@ __isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
 	if (!qp)
 		return NULL;
 
-	isl_assert(qp->div->ctx, first <= isl_space_dim(qp->dim, type),
-		    goto error);
-
 	g_pos = pos(qp->dim, type) + first;
 
 	qp->div = isl_mat_insert_zero_cols(qp->div, 2 + g_pos, n);
@@ -3197,9 +3346,9 @@ __isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
 			goto error;
 		for (i = 0; i < total - g_pos; ++i)
 			exp[i] = i + n;
-		qp->upoly = expand(qp->upoly, exp, g_pos);
+		qp->poly = expand(qp->poly, exp, g_pos);
 		free(exp);
-		if (!qp->upoly)
+		if (!qp->poly)
 			goto error;
 	}
 
@@ -3216,9 +3365,11 @@ __isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
 __isl_give isl_qpolynomial *isl_qpolynomial_add_dims(
 	__isl_take isl_qpolynomial *qp, enum isl_dim_type type, unsigned n)
 {
-	unsigned pos;
+	isl_size pos;
 
 	pos = isl_qpolynomial_dim(qp, type);
+	if (pos < 0)
+		return isl_qpolynomial_free(qp);
 
 	return isl_qpolynomial_insert_dims(qp, type, pos, n);
 }
@@ -3227,9 +3378,11 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_dims(
 	__isl_take isl_pw_qpolynomial *pwqp,
 	enum isl_dim_type type, unsigned n)
 {
-	unsigned pos;
+	isl_size pos;
 
 	pos = isl_pw_qpolynomial_dim(pwqp, type);
+	if (pos < 0)
+		return isl_pw_qpolynomial_free(pwqp);
 
 	return isl_pw_qpolynomial_insert_dims(pwqp, type, pos, n);
 }
@@ -3283,6 +3436,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
 		isl_die(qp->dim->ctx, isl_error_invalid,
 			"cannot move output/set dimension",
 			goto error);
+	if (isl_qpolynomial_check_range(qp, src_type, src_pos, n) < 0)
+		return isl_qpolynomial_free(qp);
 	if (dst_type == isl_dim_in)
 		dst_type = isl_dim_set;
 	if (src_type == isl_dim_in)
@@ -3297,9 +3452,6 @@ __isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
 	if (!qp)
 		return NULL;
 
-	isl_assert(qp->dim->ctx, src_pos + n <= isl_space_dim(qp->dim, src_type),
-		goto error);
-
 	g_dst_pos = pos(qp->dim, dst_type) + dst_pos;
 	g_src_pos = pos(qp->dim, src_type) + src_pos;
 	if (dst_type > src_type)
@@ -3317,9 +3469,9 @@ __isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
 	if (!reordering)
 		goto error;
 
-	qp->upoly = reorder(qp->upoly, reordering);
+	qp->poly = reorder(qp->poly, reordering);
 	free(reordering);
-	if (!qp->upoly)
+	if (!qp->poly)
 		goto error;
 
 	qp->dim = isl_space_move_dims(qp->dim, dst_type, dst_pos, src_type, src_pos, n);
@@ -3332,36 +3484,37 @@ __isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
 	return NULL;
 }
 
-__isl_give isl_qpolynomial *isl_qpolynomial_from_affine(__isl_take isl_space *dim,
-	isl_int *f, isl_int denom)
+__isl_give isl_qpolynomial *isl_qpolynomial_from_affine(
+	__isl_take isl_space *space, isl_int *f, isl_int denom)
 {
-	struct isl_upoly *up;
+	isl_size d;
+	isl_poly *poly;
 
-	dim = isl_space_domain(dim);
-	if (!dim)
+	space = isl_space_domain(space);
+	if (!space)
 		return NULL;
 
-	up = isl_upoly_from_affine(dim->ctx, f, denom,
-					1 + isl_space_dim(dim, isl_dim_all));
+	d = isl_space_dim(space, isl_dim_all);
+	poly = d < 0 ? NULL : isl_poly_from_affine(space->ctx, f, denom, 1 + d);
 
-	return isl_qpolynomial_alloc(dim, 0, up);
+	return isl_qpolynomial_alloc(space, 0, poly);
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_from_aff(__isl_take isl_aff *aff)
 {
 	isl_ctx *ctx;
-	struct isl_upoly *up;
+	isl_poly *poly;
 	isl_qpolynomial *qp;
 
 	if (!aff)
 		return NULL;
 
 	ctx = isl_aff_get_ctx(aff);
-	up = isl_upoly_from_affine(ctx, aff->v->el + 1, aff->v->el[0],
+	poly = isl_poly_from_affine(ctx, aff->v->el + 1, aff->v->el[0],
 				    aff->v->size - 1);
 
 	qp = isl_qpolynomial_alloc(isl_aff_get_domain_space(aff),
-				    aff->ls->div->n_row, up);
+				    aff->ls->div->n_row, poly);
 	if (!qp)
 		goto error;
 
@@ -3424,7 +3577,7 @@ __isl_give isl_qpolynomial *isl_qpolynomial_substitute(
 	__isl_keep isl_qpolynomial **subs)
 {
 	int i;
-	struct isl_upoly **ups;
+	isl_poly **polys;
 
 	if (n == 0)
 		return qp;
@@ -3437,19 +3590,17 @@ __isl_give isl_qpolynomial *isl_qpolynomial_substitute(
 		isl_die(qp->dim->ctx, isl_error_invalid,
 			"cannot substitute output/set dimension",
 			goto error);
-	if (type == isl_dim_in)
-		type = isl_dim_set;
+	if (isl_qpolynomial_check_range(qp, type, first, n) < 0)
+		return isl_qpolynomial_free(qp);
+	type = domain_type(type);
 
 	for (i = 0; i < n; ++i)
 		if (!subs[i])
 			goto error;
 
-	isl_assert(qp->dim->ctx, first + n <= isl_space_dim(qp->dim, type),
-			goto error);
-
 	for (i = 0; i < n; ++i)
-		isl_assert(qp->dim->ctx, isl_space_is_equal(qp->dim, subs[i]->dim),
-				goto error);
+		if (isl_qpolynomial_check_equal_space(qp, subs[i]) < 0)
+			goto error;
 
 	isl_assert(qp->dim->ctx, qp->div->n_row == 0, goto error);
 	for (i = 0; i < n; ++i)
@@ -3457,17 +3608,17 @@ __isl_give isl_qpolynomial *isl_qpolynomial_substitute(
 
 	first += pos(qp->dim, type);
 
-	ups = isl_alloc_array(qp->dim->ctx, struct isl_upoly *, n);
-	if (!ups)
+	polys = isl_alloc_array(qp->dim->ctx, struct isl_poly *, n);
+	if (!polys)
 		goto error;
 	for (i = 0; i < n; ++i)
-		ups[i] = subs[i]->upoly;
+		polys[i] = subs[i]->poly;
 
-	qp->upoly = isl_upoly_subs(qp->upoly, first, n, ups);
+	qp->poly = isl_poly_subs(qp->poly, first, n, polys);
 
-	free(ups);
+	free(polys);
 
-	if (!qp->upoly)
+	if (!qp->poly)
 		goto error;
 
 	return qp;
@@ -3486,8 +3637,8 @@ isl_stat isl_qpolynomial_as_polynomial_on_domain(__isl_keep isl_qpolynomial *qp,
 	isl_stat (*fn)(__isl_take isl_basic_set *bset,
 		  __isl_take isl_qpolynomial *poly, void *user), void *user)
 {
-	isl_space *dim;
-	isl_mat *div;
+	isl_space *space;
+	isl_local_space *ls;
 	isl_qpolynomial *poly;
 
 	if (!qp || !bset)
@@ -3496,43 +3647,50 @@ isl_stat isl_qpolynomial_as_polynomial_on_domain(__isl_keep isl_qpolynomial *qp,
 		return fn(isl_basic_set_copy(bset), isl_qpolynomial_copy(qp),
 			  user);
 
-	div = isl_mat_copy(qp->div);
-	dim = isl_space_copy(qp->dim);
-	dim = isl_space_add_dims(dim, isl_dim_set, qp->div->n_row);
-	poly = isl_qpolynomial_alloc(dim, 0, isl_upoly_copy(qp->upoly));
+	space = isl_space_copy(qp->dim);
+	space = isl_space_add_dims(space, isl_dim_set, qp->div->n_row);
+	poly = isl_qpolynomial_alloc(space, 0, isl_poly_copy(qp->poly));
 	bset = isl_basic_set_copy(bset);
-	bset = isl_basic_set_add_dims(bset, isl_dim_set, qp->div->n_row);
-	bset = add_div_constraints(bset, div);
+	ls = isl_qpolynomial_get_domain_local_space(qp);
+	bset = isl_local_space_lift_basic_set(ls, bset);
 
 	return fn(bset, poly, user);
 }
 
 /* Return total degree in variables first (inclusive) up to last (exclusive).
  */
-int isl_upoly_degree(__isl_keep struct isl_upoly *up, int first, int last)
+int isl_poly_degree(__isl_keep isl_poly *poly, int first, int last)
 {
 	int deg = -1;
 	int i;
-	struct isl_upoly_rec *rec;
+	isl_bool is_zero, is_cst;
+	isl_poly_rec *rec;
 
-	if (!up)
+	is_zero = isl_poly_is_zero(poly);
+	if (is_zero < 0)
 		return -2;
-	if (isl_upoly_is_zero(up))
+	if (is_zero)
 		return -1;
-	if (isl_upoly_is_cst(up) || up->var < first)
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return -2;
+	if (is_cst || poly->var < first)
 		return 0;
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		return -2;
 
 	for (i = 0; i < rec->n; ++i) {
 		int d;
 
-		if (isl_upoly_is_zero(rec->p[i]))
+		is_zero = isl_poly_is_zero(rec->p[i]);
+		if (is_zero < 0)
+			return -2;
+		if (is_zero)
 			continue;
-		d = isl_upoly_degree(rec->p[i], first, last);
-		if (up->var < last)
+		d = isl_poly_degree(rec->p[i], first, last);
+		if (poly->var < last)
 			d += i;
 		if (d > deg)
 			deg = d;
@@ -3546,61 +3704,64 @@ int isl_upoly_degree(__isl_keep struct isl_upoly *up, int first, int last)
 int isl_qpolynomial_degree(__isl_keep isl_qpolynomial *poly)
 {
 	unsigned ovar;
-	unsigned nvar;
+	isl_size nvar;
 
 	if (!poly)
 		return -2;
 
 	ovar = isl_space_offset(poly->dim, isl_dim_set);
 	nvar = isl_space_dim(poly->dim, isl_dim_set);
-	return isl_upoly_degree(poly->upoly, ovar, ovar + nvar);
+	if (nvar < 0)
+		return -2;
+	return isl_poly_degree(poly->poly, ovar, ovar + nvar);
 }
 
-__isl_give struct isl_upoly *isl_upoly_coeff(__isl_keep struct isl_upoly *up,
+__isl_give isl_poly *isl_poly_coeff(__isl_keep isl_poly *poly,
 	unsigned pos, int deg)
 {
 	int i;
-	struct isl_upoly_rec *rec;
+	isl_bool is_cst;
+	isl_poly_rec *rec;
 
-	if (!up)
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
 		return NULL;
-
-	if (isl_upoly_is_cst(up) || up->var < pos) {
+	if (is_cst || poly->var < pos) {
 		if (deg == 0)
-			return isl_upoly_copy(up);
+			return isl_poly_copy(poly);
 		else
-			return isl_upoly_zero(up->ctx);
+			return isl_poly_zero(poly->ctx);
 	}
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		return NULL;
 
-	if (up->var == pos) {
+	if (poly->var == pos) {
 		if (deg < rec->n)
-			return isl_upoly_copy(rec->p[deg]);
+			return isl_poly_copy(rec->p[deg]);
 		else
-			return isl_upoly_zero(up->ctx);
+			return isl_poly_zero(poly->ctx);
 	}
 
-	up = isl_upoly_copy(up);
-	up = isl_upoly_cow(up);
-	rec = isl_upoly_as_rec(up);
+	poly = isl_poly_copy(poly);
+	poly = isl_poly_cow(poly);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
 	for (i = 0; i < rec->n; ++i) {
-		struct isl_upoly *t;
-		t = isl_upoly_coeff(rec->p[i], pos, deg);
+		isl_poly *t;
+		t = isl_poly_coeff(rec->p[i], pos, deg);
 		if (!t)
 			goto error;
-		isl_upoly_free(rec->p[i]);
+		isl_poly_free(rec->p[i]);
 		rec->p[i] = t;
 	}
 
-	return up;
+	return poly;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
@@ -3611,7 +3772,7 @@ __isl_give isl_qpolynomial *isl_qpolynomial_coeff(
 	enum isl_dim_type type, unsigned t_pos, int deg)
 {
 	unsigned g_pos;
-	struct isl_upoly *up;
+	isl_poly *poly;
 	isl_qpolynomial *c;
 
 	if (!qp)
@@ -3621,16 +3782,15 @@ __isl_give isl_qpolynomial *isl_qpolynomial_coeff(
 		isl_die(qp->div->ctx, isl_error_invalid,
 			"output/set dimension does not have a coefficient",
 			return NULL);
-	if (type == isl_dim_in)
-		type = isl_dim_set;
-
-	isl_assert(qp->div->ctx, t_pos < isl_space_dim(qp->dim, type),
-			return NULL);
+	if (isl_qpolynomial_check_range(qp, type, t_pos, 1) < 0)
+		return NULL;
+	type = domain_type(type);
 
 	g_pos = pos(qp->dim, type) + t_pos;
-	up = isl_upoly_coeff(qp->upoly, g_pos, deg);
+	poly = isl_poly_coeff(qp->poly, g_pos, deg);
 
-	c = isl_qpolynomial_alloc(isl_space_copy(qp->dim), qp->div->n_row, up);
+	c = isl_qpolynomial_alloc(isl_space_copy(qp->dim),
+				qp->div->n_row, poly);
 	if (!c)
 		return NULL;
 	isl_mat_free(c->div);
@@ -3647,49 +3807,56 @@ __isl_give isl_qpolynomial *isl_qpolynomial_coeff(
  * last (exclusive) by inserting powers of variable first.
  * Variable first is assumed not to appear in the input.
  */
-__isl_give struct isl_upoly *isl_upoly_homogenize(
-	__isl_take struct isl_upoly *up, int deg, int target,
-	int first, int last)
+__isl_give isl_poly *isl_poly_homogenize(__isl_take isl_poly *poly, int deg,
+	int target, int first, int last)
 {
 	int i;
-	struct isl_upoly_rec *rec;
-
-	if (!up)
-		return NULL;
-	if (isl_upoly_is_zero(up))
-		return up;
+	isl_bool is_zero, is_cst;
+	isl_poly_rec *rec;
+
+	is_zero = isl_poly_is_zero(poly);
+	if (is_zero < 0)
+		return isl_poly_free(poly);
+	if (is_zero)
+		return poly;
 	if (deg == target)
-		return up;
-	if (isl_upoly_is_cst(up) || up->var < first) {
-		struct isl_upoly *hom;
+		return poly;
+	is_cst = isl_poly_is_cst(poly);
+	if (is_cst < 0)
+		return isl_poly_free(poly);
+	if (is_cst || poly->var < first) {
+		isl_poly *hom;
 
-		hom = isl_upoly_var_pow(up->ctx, first, target - deg);
+		hom = isl_poly_var_pow(poly->ctx, first, target - deg);
 		if (!hom)
 			goto error;
-		rec = isl_upoly_as_rec(hom);
-		rec->p[target - deg] = isl_upoly_mul(rec->p[target - deg], up);
+		rec = isl_poly_as_rec(hom);
+		rec->p[target - deg] = isl_poly_mul(rec->p[target - deg], poly);
 
 		return hom;
 	}
 
-	up = isl_upoly_cow(up);
-	rec = isl_upoly_as_rec(up);
+	poly = isl_poly_cow(poly);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
 	for (i = 0; i < rec->n; ++i) {
-		if (isl_upoly_is_zero(rec->p[i]))
+		is_zero = isl_poly_is_zero(rec->p[i]);
+		if (is_zero < 0)
+			return isl_poly_free(poly);
+		if (is_zero)
 			continue;
-		rec->p[i] = isl_upoly_homogenize(rec->p[i],
-				up->var < last ? deg + i : i, target,
+		rec->p[i] = isl_poly_homogenize(rec->p[i],
+				poly->var < last ? deg + i : i, target,
 				first, last);
 		if (!rec->p[i])
 			goto error;
 	}
 
-	return up;
+	return poly;
 error:
-	isl_upoly_free(up);
+	isl_poly_free(poly);
 	return NULL;
 }
 
@@ -3700,7 +3867,7 @@ __isl_give isl_qpolynomial *isl_qpolynomial_homogenize(
 	__isl_take isl_qpolynomial *poly)
 {
 	unsigned ovar;
-	unsigned nvar;
+	isl_size nvar;
 	int deg = isl_qpolynomial_degree(poly);
 
 	if (deg < -1)
@@ -3713,9 +3880,10 @@ __isl_give isl_qpolynomial *isl_qpolynomial_homogenize(
 
 	ovar = isl_space_offset(poly->dim, isl_dim_set);
 	nvar = isl_space_dim(poly->dim, isl_dim_set);
-	poly->upoly = isl_upoly_homogenize(poly->upoly, 0, deg,
-						ovar, ovar + nvar);
-	if (!poly->upoly)
+	if (nvar < 0)
+		return isl_qpolynomial_free(poly);
+	poly->poly = isl_poly_homogenize(poly->poly, 0, deg, ovar, ovar + nvar);
+	if (!poly->poly)
 		goto error;
 
 	return poly;
@@ -3724,31 +3892,33 @@ __isl_give isl_qpolynomial *isl_qpolynomial_homogenize(
 	return NULL;
 }
 
-__isl_give isl_term *isl_term_alloc(__isl_take isl_space *dim,
+__isl_give isl_term *isl_term_alloc(__isl_take isl_space *space,
 	__isl_take isl_mat *div)
 {
 	isl_term *term;
+	isl_size d;
 	int n;
 
-	if (!dim || !div)
+	d = isl_space_dim(space, isl_dim_all);
+	if (d < 0 || !div)
 		goto error;
 
-	n = isl_space_dim(dim, isl_dim_all) + div->n_row;
+	n = d + div->n_row;
 
-	term = isl_calloc(dim->ctx, struct isl_term,
+	term = isl_calloc(space->ctx, struct isl_term,
 			sizeof(struct isl_term) + (n - 1) * sizeof(int));
 	if (!term)
 		goto error;
 
 	term->ref = 1;
-	term->dim = dim;
+	term->dim = space;
 	term->div = div;
 	isl_int_init(term->n);
 	isl_int_init(term->d);
 	
 	return term;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_mat_free(div);
 	return NULL;
 }
@@ -3766,13 +3936,12 @@ __isl_give isl_term *isl_term_dup(__isl_keep isl_term *term)
 {
 	int i;
 	isl_term *dup;
-	unsigned total;
+	isl_size total;
 
-	if (!term)
+	total = isl_term_dim(term, isl_dim_all);
+	if (total < 0)
 		return NULL;
 
-	total = isl_space_dim(term->dim, isl_dim_all) + term->div->n_row;
-
 	dup = isl_term_alloc(isl_space_copy(term->dim), isl_mat_copy(term->div));
 	if (!dup)
 		return NULL;
@@ -3797,34 +3966,69 @@ __isl_give isl_term *isl_term_cow(__isl_take isl_term *term)
 	return isl_term_dup(term);
 }
 
-void isl_term_free(__isl_take isl_term *term)
+__isl_null isl_term *isl_term_free(__isl_take isl_term *term)
 {
 	if (!term)
-		return;
+		return NULL;
 
 	if (--term->ref > 0)
-		return;
+		return NULL;
 
 	isl_space_free(term->dim);
 	isl_mat_free(term->div);
 	isl_int_clear(term->n);
 	isl_int_clear(term->d);
 	free(term);
+
+	return NULL;
 }
 
-unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type)
+isl_size isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type)
 {
+	isl_size dim;
+
 	if (!term)
-		return 0;
+		return isl_size_error;
 
 	switch (type) {
 	case isl_dim_param:
 	case isl_dim_in:
 	case isl_dim_out:	return isl_space_dim(term->dim, type);
 	case isl_dim_div:	return term->div->n_row;
-	case isl_dim_all:	return isl_space_dim(term->dim, isl_dim_all) +
-								term->div->n_row;
-	default:		return 0;
+	case isl_dim_all:	dim = isl_space_dim(term->dim, isl_dim_all);
+				if (dim < 0)
+					return isl_size_error;
+				return dim + term->div->n_row;
+	default:		return isl_size_error;
+	}
+}
+
+/* Return the space of "term".
+ */
+static __isl_keep isl_space *isl_term_peek_space(__isl_keep isl_term *term)
+{
+	return term ? term->dim : NULL;
+}
+
+/* Return the offset of the first variable of type "type" within
+ * the variables of "term".
+ */
+static isl_size isl_term_offset(__isl_keep isl_term *term,
+	enum isl_dim_type type)
+{
+	isl_space *space;
+
+	space = isl_term_peek_space(term);
+	if (!space)
+		return isl_size_error;
+
+	switch (type) {
+	case isl_dim_param:
+	case isl_dim_set:	return isl_space_offset(space, type);
+	case isl_dim_div:	return isl_space_dim(space, isl_dim_all);
+	default:
+		isl_die(isl_term_get_ctx(term), isl_error_invalid,
+			"invalid dimension type", return isl_size_error);
 	}
 }
 
@@ -3851,20 +4055,23 @@ __isl_give isl_val *isl_term_get_coefficient_val(__isl_keep isl_term *term)
 					term->n, term->d);
 }
 
-int isl_term_get_exp(__isl_keep isl_term *term,
+#undef TYPE
+#define TYPE	isl_term
+static
+#include "check_type_range_templ.c"
+
+isl_size isl_term_get_exp(__isl_keep isl_term *term,
 	enum isl_dim_type type, unsigned pos)
 {
-	if (!term)
-		return -1;
-
-	isl_assert(term->dim->ctx, pos < isl_term_dim(term, type), return -1);
+	isl_size offset;
 
-	if (type >= isl_dim_set)
-		pos += isl_space_dim(term->dim, isl_dim_param);
-	if (type >= isl_dim_div)
-		pos += isl_space_dim(term->dim, isl_dim_set);
+	if (isl_term_check_range(term, type, pos, 1) < 0)
+		return isl_size_error;
+	offset = isl_term_offset(term, type);
+	if (offset < 0)
+		return isl_size_error;
 
-	return term->pow[pos];
+	return term->pow[offset + pos];
 }
 
 __isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos)
@@ -3872,12 +4079,9 @@ __isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos)
 	isl_local_space *ls;
 	isl_aff *aff;
 
-	if (!term)
+	if (isl_term_check_range(term, isl_dim_div, pos, 1) < 0)
 		return NULL;
 
-	isl_assert(term->dim->ctx, pos < isl_term_dim(term, isl_dim_div),
-			return NULL);
-
 	ls = isl_local_space_alloc_div(isl_space_copy(term->dim),
 					isl_mat_copy(term->div));
 	aff = isl_aff_alloc(ls);
@@ -3891,26 +4095,37 @@ __isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos)
 	return aff;
 }
 
-__isl_give isl_term *isl_upoly_foreach_term(__isl_keep struct isl_upoly *up,
+__isl_give isl_term *isl_poly_foreach_term(__isl_keep isl_poly *poly,
 	isl_stat (*fn)(__isl_take isl_term *term, void *user),
 	__isl_take isl_term *term, void *user)
 {
 	int i;
-	struct isl_upoly_rec *rec;
+	isl_bool is_zero, is_bad, is_cst;
+	isl_poly_rec *rec;
 
-	if (!up || !term)
+	is_zero = isl_poly_is_zero(poly);
+	if (is_zero < 0 || !term)
 		goto error;
 
-	if (isl_upoly_is_zero(up))
+	if (is_zero)
 		return term;
 
-	isl_assert(up->ctx, !isl_upoly_is_nan(up), goto error);
-	isl_assert(up->ctx, !isl_upoly_is_infty(up), goto error);
-	isl_assert(up->ctx, !isl_upoly_is_neginfty(up), goto error);
-
-	if (isl_upoly_is_cst(up)) {
-		struct isl_upoly_cst *cst;
-		cst = isl_upoly_as_cst(up);
+	is_cst = isl_poly_is_cst(poly);
+	is_bad = isl_poly_is_nan(poly);
+	if (is_bad >= 0 && !is_bad)
+		is_bad = isl_poly_is_infty(poly);
+	if (is_bad >= 0 && !is_bad)
+		is_bad = isl_poly_is_neginfty(poly);
+	if (is_cst < 0 || is_bad < 0)
+		return isl_term_free(term);
+	if (is_bad)
+		isl_die(isl_term_get_ctx(term), isl_error_invalid,
+			"cannot handle NaN/infty polynomial",
+			return isl_term_free(term));
+
+	if (is_cst) {
+		isl_poly_cst *cst;
+		cst = isl_poly_as_cst(poly);
 		if (!cst)
 			goto error;
 		term = isl_term_cow(term);
@@ -3923,7 +4138,7 @@ __isl_give isl_term *isl_upoly_foreach_term(__isl_keep struct isl_upoly *up,
 		return term;
 	}
 
-	rec = isl_upoly_as_rec(up);
+	rec = isl_poly_as_rec(poly);
 	if (!rec)
 		goto error;
 
@@ -3931,12 +4146,15 @@ __isl_give isl_term *isl_upoly_foreach_term(__isl_keep struct isl_upoly *up,
 		term = isl_term_cow(term);
 		if (!term)
 			goto error;
-		term->pow[up->var] = i;
-		term = isl_upoly_foreach_term(rec->p[i], fn, term, user);
+		term->pow[poly->var] = i;
+		term = isl_poly_foreach_term(rec->p[i], fn, term, user);
 		if (!term)
 			goto error;
 	}
-	term->pow[up->var] = 0;
+	term = isl_term_cow(term);
+	if (!term)
+		return NULL;
+	term->pow[poly->var] = 0;
 
 	return term;
 error:
@@ -3956,7 +4174,7 @@ isl_stat isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,
 	if (!term)
 		return isl_stat_error;
 
-	term = isl_upoly_foreach_term(qp->upoly, fn, term, user);
+	term = isl_poly_foreach_term(qp->poly, fn, term, user);
 
 	isl_term_free(term);
 
@@ -3965,24 +4183,27 @@ isl_stat isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,
 
 __isl_give isl_qpolynomial *isl_qpolynomial_from_term(__isl_take isl_term *term)
 {
-	struct isl_upoly *up;
+	isl_poly *poly;
 	isl_qpolynomial *qp;
-	int i, n;
+	int i;
+	isl_size n;
 
+	n = isl_term_dim(term, isl_dim_all);
+	if (n < 0)
+		term = isl_term_free(term);
 	if (!term)
 		return NULL;
 
-	n = isl_space_dim(term->dim, isl_dim_all) + term->div->n_row;
-
-	up = isl_upoly_rat_cst(term->dim->ctx, term->n, term->d);
+	poly = isl_poly_rat_cst(term->dim->ctx, term->n, term->d);
 	for (i = 0; i < n; ++i) {
 		if (!term->pow[i])
 			continue;
-		up = isl_upoly_mul(up,
-			isl_upoly_var_pow(term->dim->ctx, i, term->pow[i]));
+		poly = isl_poly_mul(poly,
+			    isl_poly_var_pow(term->dim->ctx, i, term->pow[i]));
 	}
 
-	qp = isl_qpolynomial_alloc(isl_space_copy(term->dim), term->div->n_row, up);
+	qp = isl_qpolynomial_alloc(isl_space_copy(term->dim),
+				    term->div->n_row, poly);
 	if (!qp)
 		goto error;
 	isl_mat_free(qp->div);
@@ -3999,17 +4220,17 @@ __isl_give isl_qpolynomial *isl_qpolynomial_from_term(__isl_take isl_term *term)
 }
 
 __isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
-	__isl_take isl_space *dim)
+	__isl_take isl_space *space)
 {
 	int i;
 	int extra;
-	unsigned total;
+	isl_size total, d_set, d_qp;
 
-	if (!qp || !dim)
+	if (!qp || !space)
 		goto error;
 
-	if (isl_space_is_equal(qp->dim, dim)) {
-		isl_space_free(dim);
+	if (isl_space_is_equal(qp->dim, space)) {
+		isl_space_free(space);
 		return qp;
 	}
 
@@ -4017,9 +4238,12 @@ __isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
 	if (!qp)
 		goto error;
 
-	extra = isl_space_dim(dim, isl_dim_set) -
-			isl_space_dim(qp->dim, isl_dim_set);
+	d_set = isl_space_dim(space, isl_dim_set);
+	d_qp = isl_qpolynomial_domain_dim(qp, isl_dim_set);
+	extra = d_set - d_qp;
 	total = isl_space_dim(qp->dim, isl_dim_all);
+	if (d_set < 0 || d_qp < 0 || total < 0)
+		goto error;
 	if (qp->div->n_row) {
 		int *exp;
 
@@ -4028,9 +4252,9 @@ __isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
 			goto error;
 		for (i = 0; i < qp->div->n_row; ++i)
 			exp[i] = extra + i;
-		qp->upoly = expand(qp->upoly, exp, total);
+		qp->poly = expand(qp->poly, exp, total);
 		free(exp);
-		if (!qp->upoly)
+		if (!qp->poly)
 			goto error;
 	}
 	qp->div = isl_mat_insert_cols(qp->div, 2 + total, extra);
@@ -4040,11 +4264,11 @@ __isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
 		isl_seq_clr(qp->div->row[i] + 2 + total, extra);
 
 	isl_space_free(qp->dim);
-	qp->dim = dim;
+	qp->dim = space;
 
 	return qp;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_qpolynomial_free(qp);
 	return NULL;
 }
@@ -4057,14 +4281,14 @@ static __isl_give isl_set *fix_inactive(__isl_take isl_set *set,
 {
 	int *active = NULL;
 	int i;
-	int d;
-	unsigned nparam;
-	unsigned nvar;
+	isl_size d;
+	isl_size nparam;
+	isl_size nvar;
 
-	if (!set || !qp)
+	d = isl_set_dim(set, isl_dim_all);
+	if (d < 0 || !qp)
 		goto error;
 
-	d = isl_space_dim(set->dim, isl_dim_all);
 	active = isl_calloc_array(set->ctx, int, d);
 	if (set_active(qp, active) < 0)
 		goto error;
@@ -4078,8 +4302,10 @@ static __isl_give isl_set *fix_inactive(__isl_take isl_set *set,
 		return set;
 	}
 
-	nparam = isl_space_dim(set->dim, isl_dim_param);
-	nvar = isl_space_dim(set->dim, isl_dim_set);
+	nparam = isl_set_dim(set, isl_dim_param);
+	nvar = isl_set_dim(set, isl_dim_set);
+	if (nparam < 0 || nvar < 0)
+		goto error;
 	for (i = 0; i < nparam; ++i) {
 		if (active[i])
 			continue;
@@ -4131,11 +4357,15 @@ __isl_give isl_val *isl_qpolynomial_opt_on_domain(
 	__isl_take isl_qpolynomial *qp, __isl_take isl_set *set, int max)
 {
 	struct isl_opt_data data = { NULL, 1, NULL, max };
+	isl_bool is_cst;
 
 	if (!set || !qp)
 		goto error;
 
-	if (isl_upoly_is_cst(qp->upoly)) {
+	is_cst = isl_poly_is_cst(qp->poly);
+	if (is_cst < 0)
+		goto error;
+	if (is_cst) {
 		isl_set_free(set);
 		data.opt = isl_qpolynomial_get_constant_val(qp);
 		isl_qpolynomial_free(qp);
@@ -4167,7 +4397,7 @@ __isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(
 	int i;
 	int n_sub;
 	isl_ctx *ctx;
-	struct isl_upoly **subs;
+	isl_poly **subs;
 	isl_mat *mat, *diag;
 
 	qp = isl_qpolynomial_cow(qp);
@@ -4180,22 +4410,22 @@ __isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(
 	n_sub = morph->inv->n_row - 1;
 	if (morph->inv->n_row != morph->inv->n_col)
 		n_sub += qp->div->n_row;
-	subs = isl_calloc_array(ctx, struct isl_upoly *, n_sub);
+	subs = isl_calloc_array(ctx, struct isl_poly *, n_sub);
 	if (n_sub && !subs)
 		goto error;
 
 	for (i = 0; 1 + i < morph->inv->n_row; ++i)
-		subs[i] = isl_upoly_from_affine(ctx, morph->inv->row[1 + i],
+		subs[i] = isl_poly_from_affine(ctx, morph->inv->row[1 + i],
 					morph->inv->row[0][0], morph->inv->n_col);
 	if (morph->inv->n_row != morph->inv->n_col)
 		for (i = 0; i < qp->div->n_row; ++i)
 			subs[morph->inv->n_row - 1 + i] =
-			    isl_upoly_var_pow(ctx, morph->inv->n_col - 1 + i, 1);
+			    isl_poly_var_pow(ctx, morph->inv->n_col - 1 + i, 1);
 
-	qp->upoly = isl_upoly_subs(qp->upoly, 0, n_sub, subs);
+	qp->poly = isl_poly_subs(qp->poly, 0, n_sub, subs);
 
 	for (i = 0; i < n_sub; ++i)
-		isl_upoly_free(subs[i]);
+		isl_poly_free(subs[i]);
 	free(subs);
 
 	diag = isl_mat_diag(ctx, 1, morph->inv->row[0][0]);
@@ -4206,7 +4436,7 @@ __isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(
 	isl_space_free(qp->dim);
 	qp->dim = isl_space_copy(morph->ran->dim);
 
-	if (!qp->upoly || !qp->div || !qp->dim)
+	if (!qp->poly || !qp->div || !qp->dim)
 		goto error;
 
 	isl_morph_free(morph);
@@ -4245,8 +4475,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_realign_domain(
 	if (!qp->div)
 		goto error;
 
-	qp->upoly = reorder(qp->upoly, r->pos);
-	if (!qp->upoly)
+	qp->poly = reorder(qp->poly, r->pos);
+	if (!qp->poly)
 		goto error;
 
 	space = isl_reordering_get_space(r);
@@ -4303,18 +4533,18 @@ struct isl_split_periods_data {
  *	f - m v >= 0
  *	-f + m v + (m - 1) >= 0
  */
-static __isl_give isl_set *set_div_slice(__isl_take isl_space *dim,
+static __isl_give isl_set *set_div_slice(__isl_take isl_space *space,
 	__isl_keep isl_qpolynomial *qp, int div, isl_int v)
 {
-	int total;
+	isl_size total;
 	isl_basic_set *bset = NULL;
 	int k;
 
-	if (!dim || !qp)
+	total = isl_space_dim(space, isl_dim_all);
+	if (total < 0 || !qp)
 		goto error;
 
-	total = isl_space_dim(dim, isl_dim_all);
-	bset = isl_basic_set_alloc_space(isl_space_copy(dim), 0, 0, 2);
+	bset = isl_basic_set_alloc_space(isl_space_copy(space), 0, 0, 2);
 
 	k = isl_basic_set_alloc_inequality(bset);
 	if (k < 0)
@@ -4330,11 +4560,11 @@ static __isl_give isl_set *set_div_slice(__isl_take isl_space *dim,
 	isl_int_add(bset->ineq[k][0], bset->ineq[k][0], qp->div->row[div][0]);
 	isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
 
-	isl_space_free(dim);
+	isl_space_free(space);
 	return isl_set_from_basic_set(bset);
 error:
 	isl_basic_set_free(bset);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -4350,27 +4580,26 @@ static isl_stat set_div(__isl_take isl_set *set,
 	struct isl_split_periods_data *data)
 {
 	int i;
-	int total;
+	isl_size div_pos;
 	isl_set *slice;
-	struct isl_upoly *cst;
+	isl_poly *cst;
 
 	slice = set_div_slice(isl_set_get_space(set), qp, div, v);
 	set = isl_set_intersect(set, slice);
 
-	if (!qp)
+	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
+	if (div_pos < 0)
 		goto error;
 
-	total = isl_space_dim(qp->dim, isl_dim_all);
-
 	for (i = div + 1; i < qp->div->n_row; ++i) {
-		if (isl_int_is_zero(qp->div->row[i][2 + total + div]))
+		if (isl_int_is_zero(qp->div->row[i][2 + div_pos + div]))
 			continue;
 		isl_int_addmul(qp->div->row[i][1],
-				qp->div->row[i][2 + total + div], v);
-		isl_int_set_si(qp->div->row[i][2 + total + div], 0);
+				qp->div->row[i][2 + div_pos + div], v);
+		isl_int_set_si(qp->div->row[i][2 + div_pos + div], 0);
 	}
 
-	cst = isl_upoly_rat_cst(qp->dim->ctx, v, qp->dim->ctx->one);
+	cst = isl_poly_rat_cst(qp->dim->ctx, v, qp->dim->ctx->one);
 	qp = substitute_div(qp, div, cst);
 
 	return split_periods(set, qp, data);
@@ -4417,7 +4646,7 @@ static isl_stat split_periods(__isl_take isl_set *set,
 	isl_pw_qpolynomial *pwqp;
 	struct isl_split_periods_data *data;
 	isl_int min, max;
-	int total;
+	isl_size div_pos;
 	isl_stat r = isl_stat_ok;
 
 	data = (struct isl_split_periods_data *)user;
@@ -4431,13 +4660,16 @@ static isl_stat split_periods(__isl_take isl_set *set,
 		return isl_stat_ok;
 	}
 
+	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
+	if (div_pos < 0)
+		goto error;
+
 	isl_int_init(min);
 	isl_int_init(max);
-	total = isl_space_dim(qp->dim, isl_dim_all);
 	for (i = 0; i < qp->div->n_row; ++i) {
 		enum isl_lp_result lp_res;
 
-		if (isl_seq_first_non_zero(qp->div->row[i] + 2 + total,
+		if (isl_seq_first_non_zero(qp->div->row[i] + 2 + div_pos,
 						qp->div->n_row) != -1)
 			continue;
 
@@ -4555,8 +4787,8 @@ static __isl_give isl_pw_qpolynomial *compressed_multiplicative_call(
 	isl_factorizer *f;
 	isl_qpolynomial *qp;
 	isl_pw_qpolynomial *pwqp;
-	unsigned nparam;
-	unsigned nvar;
+	isl_size nparam;
+	isl_size nvar;
 
 	f = isl_basic_set_factorizer(bset);
 	if (!f)
@@ -4568,6 +4800,8 @@ static __isl_give isl_pw_qpolynomial *compressed_multiplicative_call(
 
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nparam < 0 || nvar < 0)
+		bset = isl_basic_set_free(bset);
 
 	space = isl_basic_set_get_space(bset);
 	space = isl_space_params(space);
@@ -4618,6 +4852,7 @@ __isl_give isl_pw_qpolynomial *isl_basic_set_multiplicative_call(
 	__isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))
 {
 	isl_bool bounded;
+	isl_size dim;
 	isl_morph *morph;
 	isl_pw_qpolynomial *pwqp;
 
@@ -4627,7 +4862,10 @@ __isl_give isl_pw_qpolynomial *isl_basic_set_multiplicative_call(
 	if (isl_basic_set_plain_is_empty(bset))
 		return constant_on_domain(bset, 0);
 
-	if (isl_basic_set_dim(bset, isl_dim_set) == 0)
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		goto error;
+	if (dim == 0)
 		return constant_on_domain(bset, 1);
 
 	bounded = isl_basic_set_is_bounded(bset);
@@ -4664,7 +4902,7 @@ static __isl_give isl_qpolynomial *qp_drop_floors(
 	__isl_take isl_qpolynomial *qp, int down)
 {
 	int i;
-	struct isl_upoly *s;
+	isl_poly *s;
 
 	if (!qp)
 		return NULL;
@@ -4682,7 +4920,7 @@ static __isl_give isl_qpolynomial *qp_drop_floors(
 			isl_int_add_ui(qp->div->row[i][1],
 				       qp->div->row[i][1], 1);
 		}
-		s = isl_upoly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
+		s = isl_poly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
 					qp->div->row[i][0], qp->div->n_col - 1);
 		qp = substitute_div(qp, i, s);
 		if (!qp)
@@ -4741,18 +4979,18 @@ static __isl_give isl_qpolynomial *make_divs_pos(__isl_take isl_qpolynomial *qp,
 	int *signs)
 {
 	int i, j;
-	int total;
+	isl_size div_pos;
 	isl_vec *v = NULL;
-	struct isl_upoly *s;
+	isl_poly *s;
 
 	qp = isl_qpolynomial_cow(qp);
-	if (!qp)
-		return NULL;
+	div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
+	if (div_pos < 0)
+		return isl_qpolynomial_free(qp);
 	qp->div = isl_mat_cow(qp->div);
 	if (!qp->div)
 		goto error;
 
-	total = isl_space_dim(qp->dim, isl_dim_all);
 	v = isl_vec_alloc(qp->div->ctx, qp->div->n_col - 1);
 
 	for (i = 0; i < qp->div->n_row; ++i) {
@@ -4765,7 +5003,7 @@ static __isl_give isl_qpolynomial *make_divs_pos(__isl_take isl_qpolynomial *qp,
 			isl_int_sub_ui(v->el[0], v->el[0], 1);
 			isl_int_submul(row[1], row[0], v->el[0]);
 		}
-		for (j = 0; j < total; ++j) {
+		for (j = 0; j < div_pos; ++j) {
 			if (isl_int_sgn(row[2 + j]) * signs[j] >= 0)
 				continue;
 			if (signs[j] < 0)
@@ -4775,26 +5013,27 @@ static __isl_give isl_qpolynomial *make_divs_pos(__isl_take isl_qpolynomial *qp,
 			isl_int_submul(row[2 + j], row[0], v->el[1 + j]);
 		}
 		for (j = 0; j < i; ++j) {
-			if (isl_int_sgn(row[2 + total + j]) >= 0)
+			if (isl_int_sgn(row[2 + div_pos + j]) >= 0)
 				continue;
-			isl_int_fdiv_q(v->el[1 + total + j],
-					row[2 + total + j], row[0]);
-			isl_int_submul(row[2 + total + j],
-					row[0], v->el[1 + total + j]);
+			isl_int_fdiv_q(v->el[1 + div_pos + j],
+					row[2 + div_pos + j], row[0]);
+			isl_int_submul(row[2 + div_pos + j],
+					row[0], v->el[1 + div_pos + j]);
 		}
 		for (j = i + 1; j < qp->div->n_row; ++j) {
-			if (isl_int_is_zero(qp->div->row[j][2 + total + i]))
+			if (isl_int_is_zero(qp->div->row[j][2 + div_pos + i]))
 				continue;
 			isl_seq_combine(qp->div->row[j] + 1,
 				qp->div->ctx->one, qp->div->row[j] + 1,
-				qp->div->row[j][2 + total + i], v->el, v->size);
+				qp->div->row[j][2 + div_pos + i], v->el,
+				v->size);
 		}
-		isl_int_set_si(v->el[1 + total + i], 1);
-		s = isl_upoly_from_affine(qp->dim->ctx, v->el,
+		isl_int_set_si(v->el[1 + div_pos + i], 1);
+		s = isl_poly_from_affine(qp->dim->ctx, v->el,
 					qp->div->ctx->one, v->size);
-		qp->upoly = isl_upoly_subs(qp->upoly, total + i, 1, &s);
-		isl_upoly_free(s);
-		if (!qp->upoly)
+		qp->poly = isl_poly_subs(qp->poly, div_pos + i, 1, &s);
+		isl_poly_free(s);
+		if (!qp->poly)
 			goto error;
 	}
 
@@ -4917,12 +5156,16 @@ __isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
 	isl_space *dim;
 	isl_vec *aff = NULL;
 	isl_basic_map *bmap = NULL;
+	isl_bool is_affine;
 	unsigned pos;
 	unsigned n_div;
 
 	if (!qp)
 		return NULL;
-	if (!isl_upoly_is_affine(qp->upoly))
+	is_affine = isl_poly_is_affine(qp->poly);
+	if (is_affine < 0)
+		goto error;
+	if (!is_affine)
 		isl_die(qp->dim->ctx, isl_error_invalid,
 			"input quasi-polynomial not affine", goto error);
 	aff = isl_qpolynomial_extract_affine(qp);
@@ -4939,8 +5182,7 @@ __isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
 			goto error;
 		isl_seq_cpy(bmap->div[k], qp->div->row[i], qp->div->n_col);
 		isl_int_set_si(bmap->div[k][qp->div->n_col], 0);
-		if (isl_basic_map_add_div_constraints(bmap, k) < 0)
-			goto error;
+		bmap = isl_basic_map_add_div_constraints(bmap, k);
 	}
 	k = isl_basic_map_alloc_equality(bmap);
 	if (k < 0)

diff  --git a/polly/lib/External/isl/isl_polynomial_private.h b/polly/lib/External/isl/isl_polynomial_private.h
index 5e87d7ccff3c..be5d9e9a85c6 100644
--- a/polly/lib/External/isl/isl_polynomial_private.h
+++ b/polly/lib/External/isl/isl_polynomial_private.h
@@ -6,26 +6,29 @@
 #include <isl/polynomial.h>
 #include <isl_reordering.h>
 
-struct isl_upoly {
+struct isl_poly {
 	int ref;
 	struct isl_ctx *ctx;
 
 	int var;
 };
+typedef struct isl_poly isl_poly;
 
-struct isl_upoly_cst {
-	struct isl_upoly up;
+struct isl_poly_cst {
+	struct isl_poly poly;
 	isl_int n;
 	isl_int d;
 };
+typedef struct isl_poly_cst isl_poly_cst;
 
-struct isl_upoly_rec {
-	struct isl_upoly up;
+struct isl_poly_rec {
+	struct isl_poly poly;
 	int n;
 
 	size_t size;
-	struct isl_upoly *p[];
+	isl_poly *p[];
 };
+typedef struct isl_poly_rec isl_poly_rec;
 
 /* dim represents the domain space.
  */
@@ -34,7 +37,7 @@ struct isl_qpolynomial {
 
 	isl_space *dim;
 	struct isl_mat *div;
-	struct isl_upoly *upoly;
+	isl_poly *poly;
 };
 
 struct isl_term {
@@ -118,28 +121,28 @@ struct isl_pw_qpolynomial_fold {
 
 void isl_term_get_num(__isl_keep isl_term *term, isl_int *n);
 
-__isl_give struct isl_upoly *isl_upoly_zero(struct isl_ctx *ctx);
-__isl_give struct isl_upoly *isl_upoly_copy(__isl_keep struct isl_upoly *up);
-__isl_give struct isl_upoly *isl_upoly_cow(__isl_take struct isl_upoly *up);
-__isl_give struct isl_upoly *isl_upoly_dup(__isl_keep struct isl_upoly *up);
-__isl_null struct isl_upoly *isl_upoly_free(__isl_take struct isl_upoly *up);
-__isl_give struct isl_upoly *isl_upoly_mul(__isl_take struct isl_upoly *up1,
-	__isl_take struct isl_upoly *up2);
-
-int isl_upoly_is_cst(__isl_keep struct isl_upoly *up);
-int isl_upoly_is_zero(__isl_keep struct isl_upoly *up);
-int isl_upoly_is_one(__isl_keep struct isl_upoly *up);
-int isl_upoly_is_negone(__isl_keep struct isl_upoly *up);
-__isl_keep struct isl_upoly_cst *isl_upoly_as_cst(__isl_keep struct isl_upoly *up);
-__isl_keep struct isl_upoly_rec *isl_upoly_as_rec(__isl_keep struct isl_upoly *up);
-
-__isl_give struct isl_upoly *isl_upoly_sum(__isl_take struct isl_upoly *up1,
-	__isl_take struct isl_upoly *up2);
-__isl_give struct isl_upoly *isl_upoly_mul_isl_int(
-	__isl_take struct isl_upoly *up, isl_int v);
-
-__isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *dim,
-	unsigned n_div, __isl_take struct isl_upoly *up);
+__isl_give isl_poly *isl_poly_zero(struct isl_ctx *ctx);
+__isl_give isl_poly *isl_poly_copy(__isl_keep isl_poly *poly);
+__isl_give isl_poly *isl_poly_cow(__isl_take isl_poly *poly);
+__isl_give isl_poly *isl_poly_dup(__isl_keep isl_poly *poly);
+__isl_null isl_poly *isl_poly_free(__isl_take isl_poly *poly);
+__isl_give struct isl_poly *isl_poly_mul(__isl_take struct isl_poly *poly1,
+	__isl_take struct isl_poly *poly2);
+
+isl_bool isl_poly_is_cst(__isl_keep isl_poly *poly);
+isl_bool isl_poly_is_zero(__isl_keep isl_poly *poly);
+isl_bool isl_poly_is_one(__isl_keep isl_poly *poly);
+isl_bool isl_poly_is_negone(__isl_keep isl_poly *poly);
+__isl_keep isl_poly_cst *isl_poly_as_cst(__isl_keep isl_poly *poly);
+__isl_keep isl_poly_rec *isl_poly_as_rec(__isl_keep isl_poly *poly);
+
+__isl_give isl_poly *isl_poly_sum(__isl_take isl_poly *poly1,
+	__isl_take isl_poly *poly2);
+__isl_give struct isl_poly *isl_poly_mul_isl_int(
+	__isl_take isl_poly *poly, isl_int v);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *space,
+	unsigned n_div, __isl_take isl_poly *poly);
 __isl_give isl_qpolynomial *isl_qpolynomial_cow(__isl_take isl_qpolynomial *qp);
 __isl_give isl_qpolynomial *isl_qpolynomial_dup(__isl_keep isl_qpolynomial *qp);
 
@@ -150,8 +153,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(
 __isl_give isl_qpolynomial *isl_qpolynomial_var_pow_on_domain(__isl_take isl_space *dim,
 	int pos, int power);
 isl_bool isl_qpolynomial_is_one(__isl_keep isl_qpolynomial *qp);
-int isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp);
-int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
+isl_bool isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp);
+isl_bool isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
 	isl_int *n, isl_int *d);
 
 unsigned isl_qpolynomial_domain_offset(__isl_keep isl_qpolynomial *qp,
@@ -172,8 +175,8 @@ __isl_give isl_qpolynomial *isl_qpolynomial_coeff(
 
 __isl_give isl_vec *isl_qpolynomial_extract_affine(
 	__isl_keep isl_qpolynomial *qp);
-__isl_give isl_qpolynomial *isl_qpolynomial_from_affine(__isl_take isl_space *dim,
-	isl_int *f, isl_int denom);
+__isl_give isl_qpolynomial *isl_qpolynomial_from_affine(
+	__isl_take isl_space *space, isl_int *f, isl_int denom);
 
 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_cow(
 	__isl_take isl_pw_qpolynomial *pwqp);
@@ -215,7 +218,8 @@ int isl_qpolynomial_fold_plain_cmp(__isl_keep isl_qpolynomial_fold *fold1,
 __isl_give isl_val *isl_qpolynomial_fold_opt_on_domain(
 	__isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *set, int max);
 
-int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
+isl_bool isl_pw_qpolynomial_fold_covers(
+	__isl_keep isl_pw_qpolynomial_fold *pwf1,
 	__isl_keep isl_pw_qpolynomial_fold *pwf2);
 
 __isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(
@@ -228,7 +232,7 @@ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_morph_domain(
 	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_morph *morph);
 
 __isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
-	__isl_take isl_space *dim);
+	__isl_take isl_space *space);
 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_lift(
 	__isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *dim);
 
@@ -263,7 +267,7 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_reset_space_and_domain(
 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_reset_domain_space(
 	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_space *dim);
 
-void isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp, isl_int *d);
+__isl_give isl_val *isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp);
 __isl_give isl_qpolynomial *isl_qpolynomial_add_isl_int(
 	__isl_take isl_qpolynomial *qp, isl_int v);
 __isl_give isl_qpolynomial *isl_qpolynomial_mul_isl_int(

diff  --git a/polly/lib/External/isl/isl_printer.c b/polly/lib/External/isl/isl_printer.c
index 27b54b2b10bf..f58a8a7aaa72 100644
--- a/polly/lib/External/isl/isl_printer.c
+++ b/polly/lib/External/isl/isl_printer.c
@@ -93,6 +93,7 @@ static __isl_give isl_printer *str_print_indent(__isl_take isl_printer *p,
 		goto error;
 	for (i = 0; i < indent; ++i)
 		p->buf[p->buf_n++] = ' ';
+	p->buf[p->buf_n] = '\0';
 	return p;
 error:
 	isl_printer_free(p);

diff  --git a/polly/lib/External/isl/isl_project_out_all_params_templ.c b/polly/lib/External/isl/isl_project_out_all_params_templ.c
new file mode 100644
index 000000000000..73f9a8fa4d8f
--- /dev/null
+++ b/polly/lib/External/isl/isl_project_out_all_params_templ.c
@@ -0,0 +1,21 @@
+/*
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege
+ */
+
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Project out all parameters from "obj" by existentially quantifying
+ * over them.
+ */
+__isl_give TYPE *FN(TYPE,project_out_all_params)(__isl_take TYPE *obj)
+{
+	isl_size n;
+
+	n = FN(TYPE,dim)(obj, isl_dim_param);
+	if (n < 0)
+		return FN(TYPE,free)(obj);
+	return FN(TYPE,project_out)(obj, isl_dim_param, 0, n);
+}

diff  --git a/polly/lib/External/isl/isl_pw_add_constant_multi_val_templ.c b/polly/lib/External/isl/isl_pw_add_constant_multi_val_templ.c
new file mode 100644
index 000000000000..eccc356cb147
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_add_constant_multi_val_templ.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2019      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#undef VAL_BASE
+#define VAL_BASE	multi_val
+
+#include <isl_pw_add_constant_templ.c>

diff  --git a/polly/lib/External/isl/isl_pw_add_constant_templ.c b/polly/lib/External/isl/isl_pw_add_constant_templ.c
new file mode 100644
index 000000000000..db60e4f7ab7f
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_add_constant_templ.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#include <isl_pw_macro.h>
+
+#undef VAL
+#define VAL	CAT(isl_,VAL_BASE)
+
+/* Add "v" to the constant term of "pw" over its entire definition domain.
+ */
+__isl_give PW *FN(FN(PW,add_constant),VAL_BASE)(__isl_take PW *pw,
+	__isl_take VAL *v)
+{
+	isl_bool zero;
+	isl_size n;
+	int i;
+
+	zero = FN(VAL,is_zero)(v);
+	n = FN(PW,n_piece)(pw);
+	if (zero < 0 || n < 0)
+		goto error;
+	if (zero || n == 0) {
+		FN(VAL,free)(v);
+		return pw;
+	}
+
+	for (i = 0; i < n; ++i) {
+		EL *el;
+
+		el = FN(PW,take_base_at)(pw, i);
+		el = FN(FN(EL,add_constant),VAL_BASE)(el, FN(VAL,copy)(v));
+		pw = FN(PW,restore_base_at)(pw, i, el);
+	}
+
+	FN(VAL,free)(v);
+	return pw;
+error:
+	FN(PW,free)(pw);
+	FN(VAL,free)(v);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_pw_add_constant_val_templ.c b/polly/lib/External/isl/isl_pw_add_constant_val_templ.c
new file mode 100644
index 000000000000..d63ec04936e7
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_add_constant_val_templ.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2019      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#undef VAL_BASE
+#define VAL_BASE	val
+
+#include <isl_pw_add_constant_templ.c>

diff  --git a/polly/lib/External/isl/isl_pw_bind_domain_templ.c b/polly/lib/External/isl/isl_pw_bind_domain_templ.c
new file mode 100644
index 000000000000..2a01495b8168
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_bind_domain_templ.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2018      Cerebras Systems
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
+ */
+
+#include <isl_pw_macro.h>
+
+#undef TYPE
+#define TYPE	PW
+#include <isl_bind_domain_templ.c>

diff  --git a/polly/lib/External/isl/isl_pw_insert_dims_templ.c b/polly/lib/External/isl/isl_pw_insert_dims_templ.c
new file mode 100644
index 000000000000..8e61fd9beca7
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_insert_dims_templ.c
@@ -0,0 +1,47 @@
+/*
+ * 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
+ */
+
+__isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type,
+	unsigned first, unsigned n)
+{
+	int i;
+	enum isl_dim_type set_type;
+
+	if (!pw)
+		return NULL;
+	if (n == 0 && !isl_space_is_named_or_nested(pw->dim, type))
+		return pw;
+
+	set_type = type == isl_dim_in ? isl_dim_set : type;
+
+	pw = FN(PW,cow)(pw);
+	if (!pw)
+		return NULL;
+
+	pw->dim = isl_space_insert_dims(pw->dim, type, first, n);
+	if (!pw->dim)
+		goto error;
+
+	for (i = 0; i < pw->n; ++i) {
+		pw->p[i].set = isl_set_insert_dims(pw->p[i].set,
+							    set_type, first, n);
+		if (!pw->p[i].set)
+			goto error;
+		pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD,
+								type, first, n);
+		if (!pw->p[i].FIELD)
+			goto error;
+	}
+
+	return pw;
+error:
+	FN(PW,free)(pw);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_pw_lift_templ.c b/polly/lib/External/isl/isl_pw_lift_templ.c
new file mode 100644
index 000000000000..ad5b9e0d98e9
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_lift_templ.c
@@ -0,0 +1,90 @@
+/*
+ * 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_pw_macro.h>
+
+static isl_bool any_divs(__isl_keep isl_set *set)
+{
+	int i;
+
+	if (!set)
+		return isl_bool_error;
+
+	for (i = 0; i < set->n; ++i)
+		if (set->p[i]->n_div > 0)
+			return isl_bool_true;
+
+	return isl_bool_false;
+}
+
+static isl_stat foreach_lifted_subset(__isl_take isl_set *set,
+	__isl_take EL *el,
+	isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
+		void *user), void *user)
+{
+	int i;
+
+	if (!set || !el)
+		goto error;
+
+	for (i = 0; i < set->n; ++i) {
+		isl_set *lift;
+		EL *copy;
+
+		lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
+		lift = isl_set_lift(lift);
+
+		copy = FN(EL,copy)(el);
+		copy = FN(EL,lift)(copy, isl_set_get_space(lift));
+
+		if (fn(lift, copy, user) < 0)
+			goto error;
+	}
+
+	isl_set_free(set);
+	FN(EL,free)(el);
+
+	return isl_stat_ok;
+error:
+	isl_set_free(set);
+	FN(EL,free)(el);
+	return isl_stat_error;
+}
+
+isl_stat FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
+	isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
+		    void *user), void *user)
+{
+	int i;
+
+	if (!pw)
+		return isl_stat_error;
+
+	for (i = 0; i < pw->n; ++i) {
+		isl_bool any;
+		isl_set *set;
+		EL *el;
+
+		any = any_divs(pw->p[i].set);
+		if (any < 0)
+			return isl_stat_error;
+		set = isl_set_copy(pw->p[i].set);
+		el = FN(EL,copy)(pw->p[i].FIELD);
+		if (!any) {
+			if (fn(set, el, user) < 0)
+				return isl_stat_error;
+			continue;
+		}
+		if (foreach_lifted_subset(set, el, fn, user) < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/isl_pw_macro.h b/polly/lib/External/isl/isl_pw_macro.h
index f445df6729e2..4f74978f4bb7 100644
--- a/polly/lib/External/isl/isl_pw_macro.h
+++ b/polly/lib/External/isl/isl_pw_macro.h
@@ -1,3 +1,7 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef EL
+#define EL CAT(isl_,BASE)
 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
 #define FN(TYPE,NAME) xFN(TYPE,NAME)
 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME

diff  --git a/polly/lib/External/isl/isl_pw_morph_templ.c b/polly/lib/External/isl/isl_pw_morph_templ.c
new file mode 100644
index 000000000000..a90fea12168f
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_morph_templ.c
@@ -0,0 +1,49 @@
+/*
+ * 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
+ */
+
+__isl_give PW *FN(PW,morph_domain)(__isl_take PW *pw,
+	__isl_take isl_morph *morph)
+{
+	int i;
+	isl_ctx *ctx;
+
+	if (!pw || !morph)
+		goto error;
+
+	ctx = isl_space_get_ctx(pw->dim);
+	isl_assert(ctx, isl_space_is_domain_internal(morph->dom->dim, pw->dim),
+		goto error);
+
+	pw = FN(PW,cow)(pw);
+	if (!pw)
+		goto error;
+	pw->dim = isl_space_extend_domain_with_range(
+			isl_space_copy(morph->ran->dim), pw->dim);
+	if (!pw->dim)
+		goto error;
+
+	for (i = 0; i < pw->n; ++i) {
+		pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
+		if (!pw->p[i].set)
+			goto error;
+		pw->p[i].FIELD = FN(EL,morph_domain)(pw->p[i].FIELD,
+						isl_morph_copy(morph));
+		if (!pw->p[i].FIELD)
+			goto error;
+	}
+
+	isl_morph_free(morph);
+
+	return pw;
+error:
+	FN(PW,free)(pw);
+	isl_morph_free(morph);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_pw_move_dims_templ.c b/polly/lib/External/isl/isl_pw_move_dims_templ.c
new file mode 100644
index 000000000000..31788d79a7f7
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_move_dims_templ.c
@@ -0,0 +1,49 @@
+/*
+ * 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
+ */
+
+__isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+	int i;
+
+	pw = FN(PW,cow)(pw);
+	if (!pw)
+		return NULL;
+
+	pw->dim = isl_space_move_dims(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
+	if (!pw->dim)
+		goto error;
+
+	for (i = 0; i < pw->n; ++i) {
+		pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
+					dst_type, dst_pos, src_type, src_pos, n);
+		if (!pw->p[i].FIELD)
+			goto error;
+	}
+
+	if (dst_type == isl_dim_in)
+		dst_type = isl_dim_set;
+	if (src_type == isl_dim_in)
+		src_type = isl_dim_set;
+
+	for (i = 0; i < pw->n; ++i) {
+		pw->p[i].set = isl_set_move_dims(pw->p[i].set,
+						dst_type, dst_pos,
+						src_type, src_pos, n);
+		if (!pw->p[i].set)
+			goto error;
+	}
+
+	return pw;
+error:
+	FN(PW,free)(pw);
+	return NULL;
+}

diff  --git a/polly/lib/External/isl/isl_pw_neg_templ.c b/polly/lib/External/isl/isl_pw_neg_templ.c
new file mode 100644
index 000000000000..65970cf64166
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_neg_templ.c
@@ -0,0 +1,34 @@
+/*
+ * 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_pw_macro.h>
+
+__isl_give PW *FN(PW,neg)(__isl_take PW *pw)
+{
+	int i;
+
+	if (!pw)
+		return NULL;
+
+	if (FN(PW,IS_ZERO)(pw))
+		return pw;
+
+	pw = FN(PW,cow)(pw);
+	if (!pw)
+		return NULL;
+
+	for (i = 0; i < pw->n; ++i) {
+		pw->p[i].FIELD = FN(EL,neg)(pw->p[i].FIELD);
+		if (!pw->p[i].FIELD)
+			return FN(PW,free)(pw);
+	}
+
+	return pw;
+}

diff  --git a/polly/lib/External/isl/isl_pw_opt_templ.c b/polly/lib/External/isl/isl_pw_opt_templ.c
new file mode 100644
index 000000000000..421b4d52e222
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_opt_templ.c
@@ -0,0 +1,54 @@
+/*
+ * 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
+ */
+
+/* Compute the maximal value attained by the piecewise quasipolynomial
+ * on its domain or zero if the domain is empty.
+ * In the worst case, the domain is scanned completely,
+ * so the domain is assumed to be bounded.
+ */
+__isl_give isl_val *FN(PW,opt)(__isl_take PW *pw, int max)
+{
+	int i;
+	isl_val *opt;
+
+	if (!pw)
+		return NULL;
+
+	if (pw->n == 0) {
+		opt = isl_val_zero(FN(PW,get_ctx)(pw));
+		FN(PW,free)(pw);
+		return opt;
+	}
+
+	opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD),
+					isl_set_copy(pw->p[0].set), max);
+	for (i = 1; i < pw->n; ++i) {
+		isl_val *opt_i;
+		opt_i = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[i].FIELD),
+						isl_set_copy(pw->p[i].set), max);
+		if (max)
+			opt = isl_val_max(opt, opt_i);
+		else
+			opt = isl_val_min(opt, opt_i);
+	}
+
+	FN(PW,free)(pw);
+	return opt;
+}
+
+__isl_give isl_val *FN(PW,max)(__isl_take PW *pw)
+{
+	return FN(PW,opt)(pw, 1);
+}
+
+__isl_give isl_val *FN(PW,min)(__isl_take PW *pw)
+{
+	return FN(PW,opt)(pw, 0);
+}

diff  --git a/polly/lib/External/isl/isl_pw_pullback_templ.c b/polly/lib/External/isl/isl_pw_pullback_templ.c
new file mode 100644
index 000000000000..6f1bda9a6b94
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_pullback_templ.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012      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_pw_macro.h>
+
+#undef SUFFIX
+#define SUFFIX	multi_aff
+#undef ARG1
+#define ARG1	PW
+#undef ARG2
+#define ARG2	isl_multi_aff
+
+static
+#include "isl_align_params_templ.c"
+
+#undef SUFFIX
+#define SUFFIX	pw_multi_aff
+#undef ARG1
+#define ARG1	PW
+#undef ARG2
+#define ARG2	isl_pw_multi_aff
+
+static
+#include "isl_align_params_templ.c"
+
+/* Compute the pullback of "pw" by the function represented by "ma".
+ * In other words, plug in "ma" in "pw".
+ */
+__isl_give PW *FN(PW,pullback_multi_aff)(__isl_take PW *pw,
+	__isl_take isl_multi_aff *ma)
+{
+	int i;
+	isl_space *space = NULL;
+
+	FN(PW,align_params_multi_aff)(&pw, &ma);
+	ma = isl_multi_aff_align_divs(ma);
+	pw = FN(PW,cow)(pw);
+	if (!pw || !ma)
+		goto error;
+
+	space = isl_space_join(isl_multi_aff_get_space(ma),
+				FN(PW,get_space)(pw));
+
+	for (i = 0; i < pw->n; ++i) {
+		pw->p[i].set = isl_set_preimage_multi_aff(pw->p[i].set,
+						    isl_multi_aff_copy(ma));
+		if (!pw->p[i].set)
+			goto error;
+		pw->p[i].FIELD = FN(EL,pullback_multi_aff)(pw->p[i].FIELD,
+						    isl_multi_aff_copy(ma));
+		if (!pw->p[i].FIELD)
+			goto error;
+	}
+
+	pw = FN(PW,reset_space)(pw, space);
+	isl_multi_aff_free(ma);
+	return pw;
+error:
+	isl_space_free(space);
+	isl_multi_aff_free(ma);
+	FN(PW,free)(pw);
+	return NULL;
+}
+
+/* Compute the pullback of "pw" by the function represented by "pma".
+ * In other words, plug in "pma" in "pw".
+ */
+static __isl_give PW *FN(PW,pullback_pw_multi_aff_aligned)(__isl_take PW *pw,
+	__isl_take isl_pw_multi_aff *pma)
+{
+	int i;
+	PW *res;
+
+	if (!pma)
+		goto error;
+
+	if (pma->n == 0) {
+		isl_space *space;
+		space = isl_space_join(isl_pw_multi_aff_get_space(pma),
+					FN(PW,get_space)(pw));
+		isl_pw_multi_aff_free(pma);
+		res = FN(PW,empty)(space);
+		FN(PW,free)(pw);
+		return res;
+	}
+
+	res = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
+					isl_multi_aff_copy(pma->p[0].maff));
+	res = FN(PW,intersect_domain)(res, isl_set_copy(pma->p[0].set));
+
+	for (i = 1; i < pma->n; ++i) {
+		PW *res_i;
+
+		res_i = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
+					isl_multi_aff_copy(pma->p[i].maff));
+		res_i = FN(PW,intersect_domain)(res_i,
+					isl_set_copy(pma->p[i].set));
+		res = FN(PW,add_disjoint)(res, res_i);
+	}
+
+	isl_pw_multi_aff_free(pma);
+	FN(PW,free)(pw);
+	return res;
+error:
+	isl_pw_multi_aff_free(pma);
+	FN(PW,free)(pw);
+	return NULL;
+}
+
+__isl_give PW *FN(PW,pullback_pw_multi_aff)(__isl_take PW *pw,
+	__isl_take isl_pw_multi_aff *pma)
+{
+	FN(PW,align_params_pw_multi_aff)(&pw, &pma);
+	return FN(PW,pullback_pw_multi_aff_aligned)(pw, pma);
+}

diff  --git a/polly/lib/External/isl/isl_pw_sub_templ.c b/polly/lib/External/isl/isl_pw_sub_templ.c
new file mode 100644
index 000000000000..34107948f778
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_sub_templ.c
@@ -0,0 +1,16 @@
+/*
+ * 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_pw_macro.h>
+
+__isl_give PW *FN(PW,sub)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+	return FN(PW,add)(pw1, FN(PW,neg)(pw2));
+}

diff  --git a/polly/lib/External/isl/isl_pw_templ.c b/polly/lib/External/isl/isl_pw_templ.c
index a828f695ee64..cbb6dc0b8268 100644
--- a/polly/lib/External/isl/isl_pw_templ.c
+++ b/polly/lib/External/isl/isl_pw_templ.c
@@ -18,19 +18,17 @@
 
 #include <isl_pw_macro.h>
 
-#ifdef HAS_TYPE
-__isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim,
-	enum isl_fold type, int n)
-#else
-__isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim, int n)
-#endif
+#include "opt_type.h"
+
+__isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *space
+	OPT_TYPE_PARAM, int n)
 {
 	isl_ctx *ctx;
 	struct PW *pw;
 
-	if (!dim)
+	if (!space)
 		return NULL;
-	ctx = isl_space_get_ctx(dim);
+	ctx = isl_space_get_ctx(space);
 	isl_assert(ctx, n >= 0, goto error);
 	pw = isl_alloc(ctx, struct PW,
 			sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
@@ -38,29 +36,20 @@ __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim, int n)
 		goto error;
 
 	pw->ref = 1;
-#ifdef HAS_TYPE
-	pw->type = type;
-#endif
+	OPT_SET_TYPE(pw->, type);
 	pw->size = n;
 	pw->n = 0;
-	pw->dim = dim;
+	pw->dim = space;
 	return pw;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
-#ifdef HAS_TYPE
-__isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
-{
-	return FN(PW,alloc_size)(dim, type, 0);
-}
-#else
-__isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim)
+__isl_give PW *FN(PW,ZERO)(__isl_take isl_space *space OPT_TYPE_PARAM)
 {
-	return FN(PW,alloc_size)(dim, 0);
+	return FN(PW,alloc_size)(space OPT_TYPE_ARG(NO_LOC), 0);
 }
-#endif
 
 __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
 	__isl_take isl_set *set, __isl_take EL *el)
@@ -78,11 +67,9 @@ __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
 	}
 
 	ctx = isl_set_get_ctx(set);
-#ifdef HAS_TYPE
-	if (pw->type != el->type)
+	if (!OPT_EQUAL_TYPES(pw->, el->))
 		isl_die(ctx, isl_error_invalid, "fold types don't match",
 			goto error);
-#endif
 	el_dim = FN(EL,get_space(el));
 	isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error);
 	isl_assert(ctx, pw->n < pw->size, goto error);
@@ -136,23 +123,15 @@ static isl_stat FN(PW,check_compatible_domain)(__isl_keep EL *el,
 	return isl_stat_ok;
 }
 
-#ifdef HAS_TYPE
-__isl_give PW *FN(PW,alloc)(enum isl_fold type,
+__isl_give PW *FN(PW,alloc)(OPT_TYPE_PARAM_FIRST
 	__isl_take isl_set *set, __isl_take EL *el)
-#else
-__isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
-#endif
 {
 	PW *pw;
 
 	if (FN(PW,check_compatible_domain)(el, set) < 0)
 		goto error;
 
-#ifdef HAS_TYPE
-	pw = FN(PW,alloc_size)(FN(EL,get_space)(el), type, 1);
-#else
-	pw = FN(PW,alloc_size)(FN(EL,get_space)(el), 1);
-#endif
+	pw = FN(PW,alloc_size)(FN(EL,get_space)(el) OPT_TYPE_ARG(NO_LOC), 1);
 
 	return FN(PW,add_piece)(pw, set, el);
 error:
@@ -169,11 +148,8 @@ __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
 	if (!pw)
 		return NULL;
 
-#ifdef HAS_TYPE
-	dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, pw->n);
-#else
-	dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->n);
-#endif
+	dup = FN(PW,alloc_size)(isl_space_copy(pw->dim)
+				OPT_TYPE_ARG(pw->), pw->n);
 	if (!dup)
 		return NULL;
 
@@ -223,6 +199,65 @@ __isl_null PW *FN(PW,free)(__isl_take PW *pw)
 	return NULL;
 }
 
+/* Create a piecewise expression with the given base expression on a universe
+ * domain.
+ */
+static __isl_give PW *FN(FN(FN(PW,from),BASE),type_base)(__isl_take EL *el
+	OPT_TYPE_PARAM)
+{
+	isl_set *dom = isl_set_universe(FN(EL,get_domain_space)(el));
+	return FN(PW,alloc)(OPT_TYPE_ARG_FIRST(NO_LOC) dom, el);
+}
+
+/* Create a piecewise expression with the given base expression on a universe
+ * domain.
+ *
+ * If the default value of this piecewise type is zero and
+ * if "el" is effectively zero, then create an empty piecewise expression
+ * instead.
+ */
+static __isl_give PW *FN(FN(FN(PW,from),BASE),type)(__isl_take EL *el
+	OPT_TYPE_PARAM)
+{
+	isl_bool is_zero;
+	isl_space *space;
+
+	if (!DEFAULT_IS_ZERO)
+		return FN(FN(FN(PW,from),BASE),type_base)(el
+							OPT_TYPE_ARG(NO_LOC));
+	is_zero = FN(EL,EL_IS_ZERO)(el);
+	if (is_zero < 0)
+		goto error;
+	if (!is_zero)
+		return FN(FN(FN(PW,from),BASE),type_base)(el
+							OPT_TYPE_ARG(NO_LOC));
+	space = FN(EL,get_space)(el);
+	FN(EL,free)(el);
+	return FN(PW,ZERO)(space OPT_TYPE_ARG(NO_LOC));
+error:
+	FN(EL,free)(el);
+	return NULL;
+}
+
+#ifdef HAS_TYPE
+/* Create a piecewise expression with the given base expression on a universe
+ * domain.
+ *
+ * Pass along the type as an extra argument for improved uniformity
+ * with piecewise types that do not have a fold type.
+ */
+__isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el)
+{
+	enum isl_fold type = FN(EL,get_type)(el);
+	return FN(FN(FN(PW,from),BASE),type)(el, type);
+}
+#else
+__isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el)
+{
+	return FN(FN(FN(PW,from),BASE),type)(el);
+}
+#endif
+
 const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type,
 	unsigned pos)
 {
@@ -266,10 +301,9 @@ isl_bool FN(PW,IS_ZERO)(__isl_keep PW *pw)
 	if (!pw)
 		return isl_bool_error;
 
-	return pw->n == 0;
+	return isl_bool_ok(pw->n == 0);
 }
 
-#ifndef NO_REALIGN
 __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
 	__isl_take isl_reordering *exp)
 {
@@ -300,13 +334,10 @@ __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
 	return NULL;
 }
 
-/* Check that "pw" has only named parameters, reporting an error
- * if it does not.
- */
-isl_stat FN(PW,check_named_params)(__isl_keep PW *pw)
-{
-	return isl_space_check_named_params(FN(PW,peek_space)(pw));
-}
+#undef TYPE
+#define TYPE PW
+
+#include "isl_check_named_params_templ.c"
 
 /* Align the parameters of "pw" to those of "model".
  */
@@ -344,79 +375,47 @@ __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *mode
 	return NULL;
 }
 
-static __isl_give PW *FN(PW,align_params_pw_pw_and)(__isl_take PW *pw1,
-	__isl_take PW *pw2,
-	__isl_give PW *(*fn)(__isl_take PW *pw1, __isl_take PW *pw2))
-{
-	isl_bool equal_params;
+#undef TYPE
+#define TYPE	PW
 
-	if (!pw1 || !pw2)
-		goto error;
-	equal_params = isl_space_has_equal_params(pw1->dim, pw2->dim);
-	if (equal_params < 0)
-		goto error;
-	if (equal_params)
-		return fn(pw1, pw2);
-	if (FN(PW,check_named_params)(pw1) < 0 ||
-	    FN(PW,check_named_params)(pw2) < 0)
-		goto error;
-	pw1 = FN(PW,align_params)(pw1, FN(PW,get_space)(pw2));
-	pw2 = FN(PW,align_params)(pw2, FN(PW,get_space)(pw1));
-	return fn(pw1, pw2);
-error:
-	FN(PW,free)(pw1);
-	FN(PW,free)(pw2);
-	return NULL;
-}
+static
+#include "isl_align_params_bin_templ.c"
 
-static __isl_give PW *FN(PW,align_params_pw_set_and)(__isl_take PW *pw,
-	__isl_take isl_set *set,
-	__isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_set *set))
-{
-	isl_ctx *ctx;
-	isl_bool aligned;
+#undef SUFFIX
+#define SUFFIX	set
+#undef ARG1
+#define ARG1	PW
+#undef ARG2
+#define ARG2	isl_set
 
-	if (!pw || !set)
-		goto error;
-	aligned = isl_set_space_has_equal_params(set, pw->dim);
-	if (aligned < 0)
-		goto error;
-	if (aligned)
-		return fn(pw, set);
-	ctx = FN(PW,get_ctx)(pw);
-	if (FN(PW,check_named_params)(pw) < 0)
-		goto error;
-	if (!isl_space_has_named_params(set->dim))
-		isl_die(ctx, isl_error_invalid,
-			"unaligned unnamed parameters", goto error);
-	pw = FN(PW,align_params)(pw, isl_set_get_space(set));
-	set = isl_set_align_params(set, FN(PW,get_space)(pw));
-	return fn(pw, set);
-error:
-	FN(PW,free)(pw);
-	isl_set_free(set);
-	return NULL;
-}
-#endif
+static
+#include "isl_align_params_templ.c"
+
+#undef TYPE
+#define TYPE	PW
 
-static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1,
-	__isl_take PW *pw2)
+#include "isl_type_has_equal_space_bin_templ.c"
+#include "isl_type_check_equal_space_templ.c"
+
+/* Private version of "union_add".  For isl_pw_qpolynomial and
+ * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
+ */
+static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
 {
 	int i, j, n;
 	struct PW *res;
 	isl_ctx *ctx;
 	isl_set *set;
 
-	if (!pw1 || !pw2)
+	if (FN(PW,align_params_bin)(&pw1, &pw2) < 0)
 		goto error;
 
 	ctx = isl_space_get_ctx(pw1->dim);
-#ifdef HAS_TYPE
-	if (pw1->type != pw2->type)
+	if (!OPT_EQUAL_TYPES(pw1->, pw2->))
 		isl_die(ctx, isl_error_invalid,
 			"fold types don't match", goto error);
-#endif
-	isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
+	if (FN(PW,check_equal_space)(pw1, pw2) < 0)
+		goto error;
 
 	if (FN(PW,IS_ZERO)(pw1)) {
 		FN(PW,free)(pw1);
@@ -429,11 +428,8 @@ static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1,
 	}
 
 	n = (pw1->n + 1) * (pw2->n + 1);
-#ifdef HAS_TYPE
-	res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), pw1->type, n);
-#else
-	res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), n);
-#endif
+	res = FN(PW,alloc_size)(isl_space_copy(pw1->dim)
+				OPT_TYPE_ARG(pw1->), n);
 
 	for (i = 0; i < pw1->n; ++i) {
 		set = isl_set_copy(pw1->p[i].set);
@@ -476,15 +472,6 @@ static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1,
 	return NULL;
 }
 
-/* Private version of "union_add".  For isl_pw_qpolynomial and
- * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
- */
-static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
-{
-	return FN(PW,align_params_pw_pw_and)(pw1, pw2,
-						&FN(PW,union_add_aligned));
-}
-
 /* Make sure "pw" has room for at least "n" more pieces.
  *
  * If there is only one reference to pw, we extend it in place.
@@ -510,11 +497,7 @@ static __isl_give PW *FN(PW,grow)(__isl_take PW *pw, int n)
 		res->size = n;
 		return res;
 	}
-#ifdef HAS_TYPE
-	res = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, n);
-#else
-	res = FN(PW,alloc_size)(isl_space_copy(pw->dim), n);
-#endif
+	res = FN(PW,alloc_size)(isl_space_copy(pw->dim) OPT_TYPE_ARG(pw->), n);
 	if (!res)
 		return FN(PW,free)(pw);
 	for (i = 0; i < pw->n; ++i)
@@ -524,25 +507,23 @@ static __isl_give PW *FN(PW,grow)(__isl_take PW *pw, int n)
 	return res;
 }
 
-static __isl_give PW *FN(PW,add_disjoint_aligned)(__isl_take PW *pw1,
-	__isl_take PW *pw2)
+__isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
 {
 	int i;
 	isl_ctx *ctx;
 
-	if (!pw1 || !pw2)
+	if (FN(PW,align_params_bin)(&pw1, &pw2) < 0)
 		goto error;
 
 	if (pw1->size < pw1->n + pw2->n && pw1->n < pw2->n)
-		return FN(PW,add_disjoint_aligned)(pw2, pw1);
+		return FN(PW,add_disjoint)(pw2, pw1);
 
 	ctx = isl_space_get_ctx(pw1->dim);
-#ifdef HAS_TYPE
-	if (pw1->type != pw2->type)
+	if (!OPT_EQUAL_TYPES(pw1->, pw2->))
 		isl_die(ctx, isl_error_invalid,
 			"fold types don't match", goto error);
-#endif
-	isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
+	if (FN(PW,check_equal_space)(pw1, pw2) < 0)
+		goto error;
 
 	if (FN(PW,IS_ZERO)(pw1)) {
 		FN(PW,free)(pw1);
@@ -572,12 +553,6 @@ static __isl_give PW *FN(PW,add_disjoint_aligned)(__isl_take PW *pw1,
 	return NULL;
 }
 
-__isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
-{
-	return FN(PW,align_params_pw_pw_and)(pw1, pw2,
-						&FN(PW,add_disjoint_aligned));
-}
-
 /* This function is currently only used from isl_aff.c
  */
 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
@@ -599,11 +574,7 @@ static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
 		goto error;
 
 	n = pw1->n * pw2->n;
-#ifdef HAS_TYPE
-	res = FN(PW,alloc_size)(isl_space_copy(space), pw1->type, n);
-#else
-	res = FN(PW,alloc_size)(isl_space_copy(space), n);
-#endif
+	res = FN(PW,alloc_size)(isl_space_copy(space) OPT_TYPE_ARG(pw1->), n);
 
 	for (i = 0; i < pw1->n; ++i) {
 		for (j = 0; j < pw2->n; ++j) {
@@ -658,7 +629,7 @@ static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
 {
 	isl_space *space;
 
-	if (!pw1 || !pw2)
+	if (FN(PW,check_equal_space)(pw1, pw2) < 0)
 		goto error;
 
 	space = isl_space_copy(pw1->dim);
@@ -669,38 +640,6 @@ static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
 	return NULL;
 }
 
-#ifndef NO_NEG
-__isl_give PW *FN(PW,neg)(__isl_take PW *pw)
-{
-	int i;
-
-	if (!pw)
-		return NULL;
-
-	if (FN(PW,IS_ZERO)(pw))
-		return pw;
-
-	pw = FN(PW,cow)(pw);
-	if (!pw)
-		return NULL;
-
-	for (i = 0; i < pw->n; ++i) {
-		pw->p[i].FIELD = FN(EL,neg)(pw->p[i].FIELD);
-		if (!pw->p[i].FIELD)
-			return FN(PW,free)(pw);
-	}
-
-	return pw;
-}
-#endif
-
-#ifndef NO_SUB
-__isl_give PW *FN(PW,sub)(__isl_take PW *pw1, __isl_take PW *pw2)
-{
-	return FN(PW,add)(pw1, FN(PW,neg)(pw2));
-}
-#endif
-
 /* Return the parameter domain of "pw".
  */
 __isl_give isl_set *FN(PW,params)(__isl_take PW *pw)
@@ -812,7 +751,8 @@ __isl_give PW *FN(PW,fix_si)(__isl_take PW *pw, enum isl_dim_type type,
 
 /* Restrict the domain of "pw" by combining each cell
  * with "set" through a call to "fn", where "fn" may be
- * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
+ * isl_set_intersect, isl_set_intersect_params, isl_set_intersect_factor_domain,
+ * isl_set_intersect_factor_range or isl_set_subtract.
  */
 static __isl_give PW *FN(PW,restrict_domain_aligned)(__isl_take PW *pw,
 	__isl_take isl_set *set,
@@ -847,42 +787,43 @@ static __isl_give PW *FN(PW,restrict_domain_aligned)(__isl_take PW *pw,
 	return NULL;
 }
 
-static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw,
-	__isl_take isl_set *set)
-{
-	return FN(PW,restrict_domain_aligned)(pw, set, &isl_set_intersect);
-}
-
 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
 	__isl_take isl_set *context)
 {
-	return FN(PW,align_params_pw_set_and)(pw, context,
-					&FN(PW,intersect_domain_aligned));
+	FN(PW,align_params_set)(&pw, &context);
+	return FN(PW,restrict_domain_aligned)(pw, context, &isl_set_intersect);
 }
 
-static __isl_give PW *FN(PW,intersect_params_aligned)(__isl_take PW *pw,
-	__isl_take isl_set *set)
+/* Intersect the domain of "pw" with the parameter domain "context".
+ */
+__isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
+	__isl_take isl_set *context)
 {
-	return FN(PW,restrict_domain_aligned)(pw, set,
+	FN(PW,align_params_set)(&pw, &context);
+	return FN(PW,restrict_domain_aligned)(pw, context,
 					&isl_set_intersect_params);
 }
 
-/* Intersect the domain of "pw" with the parameter domain "context".
+/* Given a piecewise expression "pw" with domain in a space [A -> B] and
+ * a set in the space A, intersect the domain with the set.
  */
-__isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
-	__isl_take isl_set *context)
+__isl_give PW *FN(PW,intersect_domain_wrapped_domain)(__isl_take PW *pw,
+	__isl_take isl_set *set)
 {
-	return FN(PW,align_params_pw_set_and)(pw, context,
-					&FN(PW,intersect_params_aligned));
+	FN(PW,align_params_set)(&pw, &set);
+	return FN(PW,restrict_domain_aligned)(pw, set,
+					    &isl_set_intersect_factor_domain);
 }
 
-/* Subtract "domain' from the domain of "pw", assuming their
- * parameters have been aligned.
+/* Given a piecewise expression "pw" with domain in a space [A -> B] and
+ * a set in the space B, intersect the domain with the set.
  */
-static __isl_give PW *FN(PW,subtract_domain_aligned)(__isl_take PW *pw,
-	__isl_take isl_set *domain)
+__isl_give PW *FN(PW,intersect_domain_wrapped_range)(__isl_take PW *pw,
+	__isl_take isl_set *set)
 {
-	return FN(PW,restrict_domain_aligned)(pw, domain, &isl_set_subtract);
+	FN(PW,align_params_set)(&pw, &set);
+	return FN(PW,restrict_domain_aligned)(pw, set,
+					    &isl_set_intersect_factor_range);
 }
 
 /* Subtract "domain' from the domain of "pw".
@@ -890,8 +831,8 @@ static __isl_give PW *FN(PW,subtract_domain_aligned)(__isl_take PW *pw,
 __isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw,
 	__isl_take isl_set *domain)
 {
-	return FN(PW,align_params_pw_set_and)(pw, domain,
-					&FN(PW,subtract_domain_aligned));
+	FN(PW,align_params_set)(&pw, &domain);
+	return FN(PW,restrict_domain_aligned)(pw, domain, &isl_set_subtract);
 }
 
 /* Compute the gist of "pw" with respect to the domain constraints
@@ -1029,31 +970,19 @@ static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw,
 	return NULL;
 }
 
-static __isl_give PW *FN(PW,gist_domain_aligned)(__isl_take PW *pw,
-	__isl_take isl_set *set)
-{
-	return FN(PW,gist_aligned)(pw, set, &FN(EL,gist),
-					&isl_set_gist_basic_set);
-}
-
 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
 {
-	return FN(PW,align_params_pw_set_and)(pw, context,
-						&FN(PW,gist_domain_aligned));
-}
-
-static __isl_give PW *FN(PW,gist_params_aligned)(__isl_take PW *pw,
-	__isl_take isl_set *set)
-{
-	return FN(PW,gist_aligned)(pw, set, &FN(EL,gist_params),
-					&isl_set_gist_params_basic_set);
+	FN(PW,align_params_set)(&pw, &context);
+	return FN(PW,gist_aligned)(pw, context, &FN(EL,gist),
+					&isl_set_gist_basic_set);
 }
 
 __isl_give PW *FN(PW,gist_params)(__isl_take PW *pw,
 	__isl_take isl_set *context)
 {
-	return FN(PW,align_params_pw_set_and)(pw, context,
-						&FN(PW,gist_params_aligned));
+	FN(PW,align_params_set)(&pw, &context);
+	return FN(PW,gist_aligned)(pw, context, &FN(EL,gist_params),
+					&isl_set_gist_params_basic_set);
 }
 
 /* Return -1 if the piece "p1" should be sorted before "p2"
@@ -1281,9 +1210,11 @@ __isl_give PW *FN(PW,project_out)(__isl_take PW *pw,
 __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
 {
 	isl_space *space;
-	unsigned n;
+	isl_size n;
 
 	n = FN(PW,dim)(pw, isl_dim_in);
+	if (n < 0)
+		return FN(PW,free)(pw);
 	pw = FN(PW,project_out)(pw, isl_dim_in, 0, n);
 	space = FN(PW,get_domain_space)(pw);
 	space = isl_space_params(space);
@@ -1295,12 +1226,16 @@ __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
  */
 __isl_give PW *FN(PW,drop_unused_params)(__isl_take PW *pw)
 {
+	isl_size n;
 	int i;
 
 	if (FN(PW,check_named_params)(pw) < 0)
 		return FN(PW,free)(pw);
 
-	for (i = FN(PW,dim)(pw, isl_dim_param) - 1; i >= 0; i--) {
+	n = FN(PW,dim)(pw, isl_dim_param);
+	if (n < 0)
+		return FN(PW,free)(pw);
+	for (i = n - 1; i >= 0; i--) {
 		isl_bool involves;
 
 		involves = FN(PW,involves_dims)(pw, isl_dim_param, i, 1);
@@ -1313,46 +1248,6 @@ __isl_give PW *FN(PW,drop_unused_params)(__isl_take PW *pw)
 	return pw;
 }
 
-#ifndef NO_INSERT_DIMS
-__isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type,
-	unsigned first, unsigned n)
-{
-	int i;
-	enum isl_dim_type set_type;
-
-	if (!pw)
-		return NULL;
-	if (n == 0 && !isl_space_is_named_or_nested(pw->dim, type))
-		return pw;
-
-	set_type = type == isl_dim_in ? isl_dim_set : type;
-
-	pw = FN(PW,cow)(pw);
-	if (!pw)
-		return NULL;
-
-	pw->dim = isl_space_insert_dims(pw->dim, type, first, n);
-	if (!pw->dim)
-		goto error;
-
-	for (i = 0; i < pw->n; ++i) {
-		pw->p[i].set = isl_set_insert_dims(pw->p[i].set,
-							    set_type, first, n);
-		if (!pw->p[i].set)
-			goto error;
-		pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD,
-								type, first, n);
-		if (!pw->p[i].FIELD)
-			goto error;
-	}
-
-	return pw;
-error:
-	FN(PW,free)(pw);
-	return NULL;
-}
-#endif
-
 __isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw,
 	enum isl_dim_type type, unsigned pos, isl_int v)
 {
@@ -1397,9 +1292,9 @@ __isl_give PW *FN(PW,fix_val)(__isl_take PW *pw,
 	return FN(PW,free)(pw);
 }
 
-unsigned FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
+isl_size FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
 {
-	return pw ? isl_space_dim(pw->dim, type) : 0;
+	return isl_space_dim(FN(PW,peek_space)(pw), type);
 }
 
 __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
@@ -1432,63 +1327,155 @@ __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
 	return NULL;
 }
 
-#ifndef NO_OPT
-/* Compute the maximal value attained by the piecewise quasipolynomial
- * on its domain or zero if the domain is empty.
- * In the worst case, the domain is scanned completely,
- * so the domain is assumed to be bounded.
+/* Return the space of "pw".
  */
-__isl_give isl_val *FN(PW,opt)(__isl_take PW *pw, int max)
+__isl_keep isl_space *FN(PW,peek_space)(__isl_keep PW *pw)
 {
-	int i;
-	isl_val *opt;
+	return pw ? pw->dim : NULL;
+}
+
+__isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
+{
+	return isl_space_copy(FN(PW,peek_space)(pw));
+}
+
+/* Return the space of "pw".
+ * This may be either a copy or the space itself
+ * if there is only one reference to "pw".
+ * This allows the space to be modified inplace
+ * if both the piecewise expression and its space have only a single reference.
+ * The caller is not allowed to modify "pw" between this call and
+ * a subsequent call to isl_pw_*_restore_*.
+ * The only exception is that isl_pw_*_free can be called instead.
+ */
+__isl_give isl_space *FN(PW,take_space)(__isl_keep PW *pw)
+{
+	isl_space *space;
 
 	if (!pw)
 		return NULL;
+	if (pw->ref != 1)
+		return FN(PW,get_space)(pw);
+	space = pw->dim;
+	pw->dim = NULL;
+	return space;
+}
 
-	if (pw->n == 0) {
-		opt = isl_val_zero(FN(PW,get_ctx)(pw));
-		FN(PW,free)(pw);
-		return opt;
-	}
+/* Set the space of "pw" to "space", where the space of "pw" may be missing
+ * due to a preceding call to isl_pw_*_take_space.
+ * However, in this case, "pw" only has a single reference and
+ * then the call to isl_pw_*_cow has no effect.
+ */
+__isl_give PW *FN(PW,restore_space)(__isl_take PW *pw,
+	__isl_take isl_space *space)
+{
+	if (!pw || !space)
+		goto error;
 
-	opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD),
-					isl_set_copy(pw->p[0].set), max);
-	for (i = 1; i < pw->n; ++i) {
-		isl_val *opt_i;
-		opt_i = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[i].FIELD),
-						isl_set_copy(pw->p[i].set), max);
-		if (max)
-			opt = isl_val_max(opt, opt_i);
-		else
-			opt = isl_val_min(opt, opt_i);
+	if (pw->dim == space) {
+		isl_space_free(space);
+		return pw;
 	}
 
+	pw = FN(PW,cow)(pw);
+	if (!pw)
+		goto error;
+	isl_space_free(pw->dim);
+	pw->dim = space;
+
+	return pw;
+error:
 	FN(PW,free)(pw);
-	return opt;
+	isl_space_free(space);
+	return NULL;
 }
 
-__isl_give isl_val *FN(PW,max)(__isl_take PW *pw)
+/* Check that "pos" is a valid position for a cell in "pw".
+ */
+static isl_stat FN(PW,check_pos)(__isl_keep PW *pw, int pos)
 {
-	return FN(PW,opt)(pw, 1);
+	if (!pw)
+		return isl_stat_error;
+	if (pos < 0 || pos >= pw->n)
+		isl_die(FN(PW,get_ctx)(pw), isl_error_internal,
+			"position out of bounds", return isl_stat_error);
+	return isl_stat_ok;
 }
 
-__isl_give isl_val *FN(PW,min)(__isl_take PW *pw)
+/* Return the cell at position "pos" in "pw".
+ */
+static __isl_keep isl_set *FN(PW,peek_domain_at)(__isl_keep PW *pw, int pos)
 {
-	return FN(PW,opt)(pw, 0);
+	if (FN(PW,check_pos)(pw, pos) < 0)
+		return NULL;
+	return pw->p[pos].set;
 }
-#endif
 
-/* Return the space of "pw".
+/* Return a copy of the base expression associated to
+ * the cell at position "pos" in "pw".
  */
-__isl_keep isl_space *FN(PW,peek_space)(__isl_keep PW *pw)
+__isl_give EL *FN(PW,get_base_at)(__isl_keep PW *pw, int pos)
 {
-	return pw ? pw->dim : NULL;
-}
+	if (FN(PW,check_pos)(pw, pos) < 0)
+		return NULL;
+	return FN(EL,copy)(pw->p[pos].FIELD);
+}
+
+/* Return the base expression associated to
+ * the cell at position "pos" in "pw".
+ * This may be either a copy or the base expression itself
+ * if there is only one reference to "pw".
+ * This allows the base expression to be modified inplace
+ * if both the piecewise expression and this base expression
+ * have only a single reference.
+ * The caller is not allowed to modify "pw" between this call and
+ * a subsequent call to isl_pw_*_restore_*.
+ * The only exception is that isl_pw_*_free can be called instead.
+ */
+__isl_give EL *FN(PW,take_base_at)(__isl_keep PW *pw, int pos)
+{
+	EL *el;
 
-__isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
+	if (!pw)
+		return NULL;
+	if (pw->ref != 1)
+		return FN(PW,get_base_at)(pw, pos);
+	if (FN(PW,check_pos)(pw, pos) < 0)
+		return NULL;
+	el = pw->p[pos].FIELD;
+	pw->p[pos].FIELD = NULL;
+	return el;
+}
+
+/* Set the base expression associated to
+ * the cell at position "pos" in "pw" to "el",
+ * where this base expression may be missing
+ * due to a preceding call to isl_pw_*_take_base_at.
+ * However, in this case, "pw" only has a single reference and
+ * then the call to isl_pw_*_cow has no effect.
+ */
+__isl_give PW *FN(PW,restore_base_at)(__isl_take PW *pw, int pos,
+	__isl_take EL *el)
 {
-	return isl_space_copy(FN(PW,peek_space)(pw));
+	if (FN(PW,check_pos)(pw, pos) < 0 || !el)
+		goto error;
+
+	if (pw->p[pos].FIELD == el) {
+		FN(EL,free)(el);
+		return pw;
+	}
+
+	pw = FN(PW,cow)(pw);
+	if (!pw)
+		goto error;
+	FN(EL,free)(pw->p[pos].FIELD);
+	pw->p[pos].FIELD = el;
+
+	return pw;
+error:
+	FN(PW,free)(pw);
+	FN(EL,free)(el);
+	return NULL;
 }
 
 __isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw)
@@ -1508,7 +1495,37 @@ int FN(PW,find_dim_by_name)(__isl_keep PW *pw,
 	return isl_space_find_dim_by_name(pw->dim, type, name);
 }
 
-#ifndef NO_RESET_DIM
+/* Return the position of the dimension of the given type and identifier
+ * in "pw".
+ * Return -1 if no such dimension can be found.
+ */
+static int FN(PW,find_dim_by_id)(__isl_keep PW *pw,
+	enum isl_dim_type type, __isl_keep isl_id *id)
+{
+	isl_space *space;
+
+	space = FN(PW,peek_space)(pw);
+	return isl_space_find_dim_by_id(space, type, id);
+}
+
+/* Does the piecewise expression "pw" depend in any way
+ * on the parameter with identifier "id"?
+ */
+isl_bool FN(PW,involves_param_id)(__isl_keep PW *pw, __isl_keep isl_id *id)
+{
+	int pos;
+
+	if (!pw || !id)
+		return isl_bool_error;
+	if (pw->n == 0)
+		return isl_bool_false;
+
+	pos = FN(PW,find_dim_by_id)(pw, isl_dim_param, id);
+	if (pos < 0)
+		return isl_bool_false;
+	return FN(PW,involves_dims)(pw, isl_dim_param, pos, 1);
+}
+
 /* Reset the space of "pw".  Since we don't know if the elements
  * represent the spaces themselves or their domains, we pass along
  * both when we call their reset_space_and_domain.
@@ -1615,7 +1632,6 @@ __isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw,
 	isl_id_free(id);
 	return FN(PW,free)(pw);
 }
-#endif
 
 /* Reset the user pointer on all identifiers of parameters and tuples
  * of the space of "pw".
@@ -1630,59 +1646,9 @@ __isl_give PW *FN(PW,reset_user)(__isl_take PW *pw)
 	return FN(PW,reset_space)(pw, space);
 }
 
-isl_bool FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2)
-{
-	if (!pw1 || !pw2)
-		return isl_bool_error;
-
-	return isl_space_is_equal(pw1->dim, pw2->dim);
-}
-
-#ifndef NO_MORPH
-__isl_give PW *FN(PW,morph_domain)(__isl_take PW *pw,
-	__isl_take isl_morph *morph)
-{
-	int i;
-	isl_ctx *ctx;
-
-	if (!pw || !morph)
-		goto error;
-
-	ctx = isl_space_get_ctx(pw->dim);
-	isl_assert(ctx, isl_space_is_domain_internal(morph->dom->dim, pw->dim),
-		goto error);
-
-	pw = FN(PW,cow)(pw);
-	if (!pw)
-		goto error;
-	pw->dim = isl_space_extend_domain_with_range(
-			isl_space_copy(morph->ran->dim), pw->dim);
-	if (!pw->dim)
-		goto error;
-
-	for (i = 0; i < pw->n; ++i) {
-		pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
-		if (!pw->p[i].set)
-			goto error;
-		pw->p[i].FIELD = FN(EL,morph_domain)(pw->p[i].FIELD,
-						isl_morph_copy(morph));
-		if (!pw->p[i].FIELD)
-			goto error;
-	}
-
-	isl_morph_free(morph);
-
-	return pw;
-error:
-	FN(PW,free)(pw);
-	isl_morph_free(morph);
-	return NULL;
-}
-#endif
-
-int FN(PW,n_piece)(__isl_keep PW *pw)
+isl_size FN(PW,n_piece)(__isl_keep PW *pw)
 {
-	return pw ? pw->n : 0;
+	return pw ? pw->n : isl_size_error;
 }
 
 isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw,
@@ -1702,126 +1668,118 @@ isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw,
 	return isl_stat_ok;
 }
 
-#ifndef NO_LIFT
-static isl_bool any_divs(__isl_keep isl_set *set)
+/* Is "pw" defined over a single universe domain?
+ *
+ * If the default value of this piecewise type is zero,
+ * then a "pw" with a zero number of cells is also accepted
+ * as it represents the default zero value.
+ */
+isl_bool FN(FN(PW,isa),BASE)(__isl_keep PW *pw)
 {
-	int i;
+	isl_size n;
 
-	if (!set)
+	n = FN(PW,n_piece)(pw);
+	if (n < 0)
 		return isl_bool_error;
+	if (DEFAULT_IS_ZERO && n == 0)
+		return isl_bool_true;
+	if (n != 1)
+		return isl_bool_false;
+	return isl_set_plain_is_universe(FN(PW,peek_domain_at)(pw, 0));
+}
 
-	for (i = 0; i < set->n; ++i)
-		if (set->p[i]->n_div > 0)
-			return isl_bool_true;
+/* Return a zero base expression in the same space (and of the same type)
+ * as "pw".
+ */
+static __isl_give EL *FN(EL,zero_like_type)(__isl_take PW *pw OPT_TYPE_PARAM)
+{
+	isl_space *space;
 
-	return isl_bool_false;
+	space = FN(PW,get_space)(pw);
+	FN(PW,free)(pw);
+	return FN(EL,zero_in_space)(space OPT_TYPE_ARG(NO_LOC));
 }
 
-static isl_stat foreach_lifted_subset(__isl_take isl_set *set,
-	__isl_take EL *el,
-	isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
-		void *user), void *user)
+#ifndef HAS_TYPE
+/* Return a zero base expression in the same space as "pw".
+ */
+static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw)
 {
-	int i;
+	return FN(EL,zero_like_type)(pw);
+}
+#else
+/* Return a zero base expression in the same space and of the same type
+ * as "pw".
+ *
+ * Pass along the type as an explicit argument for uniform handling
+ * in isl_*_zero_like_type.
+ */
+static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw)
+{
+	enum isl_fold type;
 
-	if (!set || !el)
+	type = FN(PW,get_type)(pw);
+	if (type < 0)
 		goto error;
-
-	for (i = 0; i < set->n; ++i) {
-		isl_set *lift;
-		EL *copy;
-
-		lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
-		lift = isl_set_lift(lift);
-
-		copy = FN(EL,copy)(el);
-		copy = FN(EL,lift)(copy, isl_set_get_space(lift));
-
-		if (fn(lift, copy, user) < 0)
-			goto error;
-	}
-
-	isl_set_free(set);
-	FN(EL,free)(el);
-
-	return isl_stat_ok;
+	return FN(EL,zero_like_type)(pw, type);
 error:
-	isl_set_free(set);
-	FN(EL,free)(el);
-	return isl_stat_error;
+	FN(PW,free)(pw);
+	return NULL;
 }
+#endif
 
-isl_stat FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
-	isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
-		    void *user), void *user)
+/* Given that "pw" is defined over a single universe domain,
+ * return the base expression associated to this domain.
+ *
+ * If the number of cells is zero, then "pw" is of a piecewise type
+ * with a default zero value and effectively represents zero.
+ * In this case, create a zero base expression in the same space
+ * (and with the same type).
+ * Otherwise, simply extract the associated base expression.
+ */
+__isl_give EL *FN(FN(PW,as),BASE)(__isl_take PW *pw)
 {
-	int i;
+	isl_bool is_total;
+	isl_size n;
+	EL *el;
 
-	if (!pw)
-		return isl_stat_error;
-
-	for (i = 0; i < pw->n; ++i) {
-		isl_bool any;
-		isl_set *set;
-		EL *el;
-
-		any = any_divs(pw->p[i].set);
-		if (any < 0)
-			return isl_stat_error;
-		set = isl_set_copy(pw->p[i].set);
-		el = FN(EL,copy)(pw->p[i].FIELD);
-		if (!any) {
-			if (fn(set, el, user) < 0)
-				return isl_stat_error;
-			continue;
-		}
-		if (foreach_lifted_subset(set, el, fn, user) < 0)
-			return isl_stat_error;
-	}
-
-	return isl_stat_ok;
+	is_total = FN(FN(PW,isa),BASE)(pw);
+	if (is_total < 0)
+		goto error;
+	if (!is_total)
+		isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
+			"expecting single total function", goto error);
+	n = FN(PW,n_piece)(pw);
+	if (n < 0)
+		goto error;
+	if (n == 0)
+		return FN(EL,zero_like)(pw);
+	el = FN(PW,take_base_at)(pw, 0);
+	FN(PW,free)(pw);
+	return el;
+error:
+	FN(PW,free)(pw);
+	return NULL;
 }
-#endif
 
-#ifndef NO_MOVE_DIMS
-__isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
-	enum isl_dim_type dst_type, unsigned dst_pos,
-	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+#ifdef HAS_TYPE
+/* Negate the type of "pw".
+ */
+static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw)
 {
-	int i;
-
 	pw = FN(PW,cow)(pw);
 	if (!pw)
 		return NULL;
-
-	pw->dim = isl_space_move_dims(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
-	if (!pw->dim)
-		goto error;
-
-	for (i = 0; i < pw->n; ++i) {
-		pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
-					dst_type, dst_pos, src_type, src_pos, n);
-		if (!pw->p[i].FIELD)
-			goto error;
-	}
-
-	if (dst_type == isl_dim_in)
-		dst_type = isl_dim_set;
-	if (src_type == isl_dim_in)
-		src_type = isl_dim_set;
-
-	for (i = 0; i < pw->n; ++i) {
-		pw->p[i].set = isl_set_move_dims(pw->p[i].set,
-						dst_type, dst_pos,
-						src_type, src_pos, n);
-		if (!pw->p[i].set)
-			goto error;
-	}
-
+	pw->type = isl_fold_type_negate(pw->type);
+	return pw;
+}
+#else
+/* Negate the type of "pw".
+ * Since "pw" does not have a type, do nothing.
+ */
+static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw)
+{
 	return pw;
-error:
-	FN(PW,free)(pw);
-	return NULL;
 }
 #endif
 
@@ -1834,24 +1792,18 @@ __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
 	if (pw && DEFAULT_IS_ZERO && isl_int_is_zero(v)) {
 		PW *zero;
 		isl_space *dim = FN(PW,get_space)(pw);
-#ifdef HAS_TYPE
-		zero = FN(PW,ZERO)(dim, pw->type);
-#else
-		zero = FN(PW,ZERO)(dim);
-#endif
+		zero = FN(PW,ZERO)(dim OPT_TYPE_ARG(pw->));
 		FN(PW,free)(pw);
 		return zero;
 	}
 	pw = FN(PW,cow)(pw);
+	if (isl_int_is_neg(v))
+		pw = FN(PW,negate_type)(pw);
 	if (!pw)
 		return NULL;
 	if (pw->n == 0)
 		return pw;
 
-#ifdef HAS_TYPE
-	if (isl_int_is_neg(v))
-		pw->type = isl_fold_type_negate(pw->type);
-#endif
 	for (i = 0; i < pw->n; ++i) {
 		pw->p[i].FIELD = FN(EL,scale)(pw->p[i].FIELD, v);
 		if (!pw->p[i].FIELD)
@@ -1880,11 +1832,7 @@ __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
 	if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) {
 		PW *zero;
 		isl_space *space = FN(PW,get_space)(pw);
-#ifdef HAS_TYPE
-		zero = FN(PW,ZERO)(space, pw->type);
-#else
-		zero = FN(PW,ZERO)(space);
-#endif
+		zero = FN(PW,ZERO)(space OPT_TYPE_ARG(pw->));
 		FN(PW,free)(pw);
 		isl_val_free(v);
 		return zero;
@@ -1894,13 +1842,11 @@ __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
 		return pw;
 	}
 	pw = FN(PW,cow)(pw);
+	if (isl_val_is_neg(v))
+		pw = FN(PW,negate_type)(pw);
 	if (!pw)
 		goto error;
 
-#ifdef HAS_TYPE
-	if (isl_val_is_neg(v))
-		pw->type = isl_fold_type_negate(pw->type);
-#endif
 	for (i = 0; i < pw->n; ++i) {
 		pw->p[i].FIELD = FN(EL,scale_val)(pw->p[i].FIELD,
 						    isl_val_copy(v));
@@ -1942,13 +1888,11 @@ __isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v)
 		return pw;
 	}
 	pw = FN(PW,cow)(pw);
+	if (isl_val_is_neg(v))
+		pw = FN(PW,negate_type)(pw);
 	if (!pw)
 		goto error;
 
-#ifdef HAS_TYPE
-	if (isl_val_is_neg(v))
-		pw->type = isl_fold_type_negate(pw->type);
-#endif
 	for (i = 0; i < pw->n; ++i) {
 		pw->p[i].FIELD = FN(EL,scale_down_val)(pw->p[i].FIELD,
 						    isl_val_copy(v));
@@ -2021,8 +1965,9 @@ isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
 
 	if (pw1 == pw2)
 		return isl_bool_true;
-	if (!isl_space_is_equal(pw1->dim, pw2->dim))
-		return isl_bool_false;
+	equal = FN(PW,has_equal_space)(pw1, pw2);
+	if (equal < 0 || !equal)
+		return equal;
 
 	pw1 = FN(PW,copy)(pw1);
 	pw2 = FN(PW,copy)(pw2);
@@ -2031,7 +1976,7 @@ isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
 	if (!pw1 || !pw2)
 		goto error;
 
-	equal = pw1->n == pw2->n;
+	equal = isl_bool_ok(pw1->n == pw2->n);
 	for (i = 0; equal && i < pw1->n; ++i) {
 		equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set);
 		if (equal < 0)
@@ -2071,167 +2016,3 @@ isl_bool FN(PW,involves_nan)(__isl_keep PW *pw)
 
 	return isl_bool_false;
 }
-
-#ifndef NO_PULLBACK
-static __isl_give PW *FN(PW,align_params_pw_multi_aff_and)(__isl_take PW *pw,
-	__isl_take isl_multi_aff *ma,
-	__isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_multi_aff *ma))
-{
-	isl_ctx *ctx;
-	isl_bool equal_params;
-	isl_space *ma_space;
-
-	ma_space = isl_multi_aff_get_space(ma);
-	if (!pw || !ma || !ma_space)
-		goto error;
-	equal_params = isl_space_has_equal_params(pw->dim, ma_space);
-	if (equal_params < 0)
-		goto error;
-	if (equal_params) {
-		isl_space_free(ma_space);
-		return fn(pw, ma);
-	}
-	ctx = FN(PW,get_ctx)(pw);
-	if (FN(PW,check_named_params)(pw) < 0)
-		goto error;
-	if (!isl_space_has_named_params(ma_space))
-		isl_die(ctx, isl_error_invalid,
-			"unaligned unnamed parameters", goto error);
-	pw = FN(PW,align_params)(pw, ma_space);
-	ma = isl_multi_aff_align_params(ma, FN(PW,get_space)(pw));
-	return fn(pw, ma);
-error:
-	isl_space_free(ma_space);
-	FN(PW,free)(pw);
-	isl_multi_aff_free(ma);
-	return NULL;
-}
-
-static __isl_give PW *FN(PW,align_params_pw_pw_multi_aff_and)(__isl_take PW *pw,
-	__isl_take isl_pw_multi_aff *pma,
-	__isl_give PW *(*fn)(__isl_take PW *pw,
-		__isl_take isl_pw_multi_aff *ma))
-{
-	isl_bool equal_params;
-	isl_space *pma_space;
-
-	pma_space = isl_pw_multi_aff_get_space(pma);
-	if (!pw || !pma || !pma_space)
-		goto error;
-	equal_params = isl_space_has_equal_params(pw->dim, pma_space);
-	if (equal_params < 0)
-		goto error;
-	if (equal_params) {
-		isl_space_free(pma_space);
-		return fn(pw, pma);
-	}
-	if (FN(PW,check_named_params)(pw) < 0 ||
-	    isl_pw_multi_aff_check_named_params(pma) < 0)
-		goto error;
-	pw = FN(PW,align_params)(pw, pma_space);
-	pma = isl_pw_multi_aff_align_params(pma, FN(PW,get_space)(pw));
-	return fn(pw, pma);
-error:
-	isl_space_free(pma_space);
-	FN(PW,free)(pw);
-	isl_pw_multi_aff_free(pma);
-	return NULL;
-}
-
-/* Compute the pullback of "pw" by the function represented by "ma".
- * In other words, plug in "ma" in "pw".
- */
-static __isl_give PW *FN(PW,pullback_multi_aff_aligned)(__isl_take PW *pw,
-	__isl_take isl_multi_aff *ma)
-{
-	int i;
-	isl_space *space = NULL;
-
-	ma = isl_multi_aff_align_divs(ma);
-	pw = FN(PW,cow)(pw);
-	if (!pw || !ma)
-		goto error;
-
-	space = isl_space_join(isl_multi_aff_get_space(ma),
-				FN(PW,get_space)(pw));
-
-	for (i = 0; i < pw->n; ++i) {
-		pw->p[i].set = isl_set_preimage_multi_aff(pw->p[i].set,
-						    isl_multi_aff_copy(ma));
-		if (!pw->p[i].set)
-			goto error;
-		pw->p[i].FIELD = FN(EL,pullback_multi_aff)(pw->p[i].FIELD,
-						    isl_multi_aff_copy(ma));
-		if (!pw->p[i].FIELD)
-			goto error;
-	}
-
-	pw = FN(PW,reset_space)(pw, space);
-	isl_multi_aff_free(ma);
-	return pw;
-error:
-	isl_space_free(space);
-	isl_multi_aff_free(ma);
-	FN(PW,free)(pw);
-	return NULL;
-}
-
-__isl_give PW *FN(PW,pullback_multi_aff)(__isl_take PW *pw,
-	__isl_take isl_multi_aff *ma)
-{
-	return FN(PW,align_params_pw_multi_aff_and)(pw, ma,
-					&FN(PW,pullback_multi_aff_aligned));
-}
-
-/* Compute the pullback of "pw" by the function represented by "pma".
- * In other words, plug in "pma" in "pw".
- */
-static __isl_give PW *FN(PW,pullback_pw_multi_aff_aligned)(__isl_take PW *pw,
-	__isl_take isl_pw_multi_aff *pma)
-{
-	int i;
-	PW *res;
-
-	if (!pma)
-		goto error;
-
-	if (pma->n == 0) {
-		isl_space *space;
-		space = isl_space_join(isl_pw_multi_aff_get_space(pma),
-					FN(PW,get_space)(pw));
-		isl_pw_multi_aff_free(pma);
-		res = FN(PW,empty)(space);
-		FN(PW,free)(pw);
-		return res;
-	}
-
-	res = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
-					isl_multi_aff_copy(pma->p[0].maff));
-	res = FN(PW,intersect_domain)(res, isl_set_copy(pma->p[0].set));
-
-	for (i = 1; i < pma->n; ++i) {
-		PW *res_i;
-
-		res_i = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
-					isl_multi_aff_copy(pma->p[i].maff));
-		res_i = FN(PW,intersect_domain)(res_i,
-					isl_set_copy(pma->p[i].set));
-		res = FN(PW,add_disjoint)(res, res_i);
-	}
-
-	isl_pw_multi_aff_free(pma);
-	FN(PW,free)(pw);
-	return res;
-error:
-	isl_pw_multi_aff_free(pma);
-	FN(PW,free)(pw);
-	return NULL;
-}
-
-__isl_give PW *FN(PW,pullback_pw_multi_aff)(__isl_take PW *pw,
-	__isl_take isl_pw_multi_aff *pma)
-{
-	return FN(PW,align_params_pw_pw_multi_aff_and)(pw, pma,
-					&FN(PW,pullback_pw_multi_aff_aligned));
-}
-#endif

diff  --git a/polly/lib/External/isl/isl_range.c b/polly/lib/External/isl/isl_range.c
index 690d7b948f22..5bcfcffb7f44 100644
--- a/polly/lib/External/isl/isl_range.c
+++ b/polly/lib/External/isl/isl_range.c
@@ -26,17 +26,19 @@ static isl_stat propagate_on_domain(__isl_take isl_basic_set *bset,
  * is non-negative and if sign == -1, check that the upper bound on
  * the polynomial is non-positive.
  */
-static int has_sign(__isl_keep isl_basic_set *bset,
+static isl_bool has_sign(__isl_keep isl_basic_set *bset,
 	__isl_keep isl_qpolynomial *poly, int sign, int *signs)
 {
 	struct range_data data_m;
-	unsigned nparam;
-	isl_space *dim;
+	isl_size nparam;
+	isl_space *space;
 	isl_val *opt;
-	int r;
+	isl_bool r;
 	enum isl_fold type;
 
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (nparam < 0)
+		return isl_bool_error;
 
 	bset = isl_basic_set_copy(bset);
 	poly = isl_qpolynomial_copy(poly);
@@ -46,16 +48,16 @@ static int has_sign(__isl_keep isl_basic_set *bset,
 	poly = isl_qpolynomial_move_dims(poly, isl_dim_in, 0,
 					isl_dim_param, 0, nparam);
 
-	dim = isl_qpolynomial_get_space(poly);
-	dim = isl_space_params(dim);
-	dim = isl_space_from_domain(dim);
-	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+	space = isl_qpolynomial_get_space(poly);
+	space = isl_space_params(space);
+	space = isl_space_from_domain(space);
+	space = isl_space_add_dims(space, isl_dim_out, 1);
 
 	data_m.test_monotonicity = 0;
 	data_m.signs = signs;
 	data_m.sign = -sign;
 	type = data_m.sign < 0 ? isl_fold_min : isl_fold_max;
-	data_m.pwf = isl_pw_qpolynomial_fold_zero(dim, type);
+	data_m.pwf = isl_pw_qpolynomial_fold_zero(space, type);
 	data_m.tight = 0;
 	data_m.pwf_tight = NULL;
 
@@ -68,20 +70,20 @@ static int has_sign(__isl_keep isl_basic_set *bset,
 		opt = isl_pw_qpolynomial_fold_max(data_m.pwf);
 
 	if (!opt)
-		r = -1;
+		r = isl_bool_error;
 	else if (isl_val_is_nan(opt) ||
 		 isl_val_is_infty(opt) ||
 		 isl_val_is_neginfty(opt))
-		r = 0;
+		r = isl_bool_false;
 	else
-		r = sign * isl_val_sgn(opt) >= 0;
+		r = isl_bool_ok(sign * isl_val_sgn(opt) >= 0);
 
 	isl_val_free(opt);
 
 	return r;
 error:
 	isl_pw_qpolynomial_fold_free(data_m.pwf);
-	return -1;
+	return isl_bool_error;
 }
 
 /* Return  1 if poly is monotonically increasing in the last set variable,
@@ -95,21 +97,24 @@ static int monotonicity(__isl_keep isl_basic_set *bset,
 	__isl_keep isl_qpolynomial *poly, struct range_data *data)
 {
 	isl_ctx *ctx;
-	isl_space *dim;
+	isl_space *space;
 	isl_qpolynomial *sub = NULL;
 	isl_qpolynomial *
diff  = NULL;
 	int result = 0;
-	int s;
-	unsigned nvar;
-
-	ctx = isl_qpolynomial_get_ctx(poly);
-	dim = isl_qpolynomial_get_domain_space(poly);
+	isl_bool s;
+	isl_size nvar;
 
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0)
+		return -2;
+
+	ctx = isl_qpolynomial_get_ctx(poly);
+	space = isl_qpolynomial_get_domain_space(poly);
 
-	sub = isl_qpolynomial_var_on_domain(isl_space_copy(dim), isl_dim_set, nvar - 1);
+	sub = isl_qpolynomial_var_on_domain(isl_space_copy(space),
+						isl_dim_set, nvar - 1);
 	sub = isl_qpolynomial_add(sub,
-		isl_qpolynomial_rat_cst_on_domain(dim, ctx->one, ctx->one));
+		isl_qpolynomial_rat_cst_on_domain(space, ctx->one, ctx->one));
 
 	
diff  = isl_qpolynomial_substitute(isl_qpolynomial_copy(poly),
 			isl_dim_in, nvar - 1, 1, &sub);
@@ -159,7 +164,7 @@ static __isl_give isl_qpolynomial *bound2poly(__isl_take isl_constraint *bound,
 	return isl_qpolynomial_from_constraint(bound, isl_dim_set, pos);
 }
 
-static int bound_is_integer(__isl_take isl_constraint *bound, unsigned pos)
+static int bound_is_integer(__isl_keep isl_constraint *bound, unsigned pos)
 {
 	isl_int c;
 	int is_int;
@@ -192,30 +197,36 @@ static isl_stat collect_fixed_sign_terms(__isl_take isl_term *term, void *user)
 	isl_int n;
 	int i;
 	int sign;
-	unsigned nparam;
-	unsigned nvar;
-
-	if (!term)
-		return isl_stat_error;
+	isl_size nparam;
+	isl_size nvar;
+	isl_size exp;
 
 	nparam = isl_term_dim(term, isl_dim_param);
 	nvar = isl_term_dim(term, isl_dim_set);
+	if (nparam < 0 || nvar < 0)
+		return isl_stat_error;
 
 	isl_int_init(n);
-
 	isl_term_get_num(term, &n);
-
 	sign = isl_int_sgn(n);
+	isl_int_clear(n);
+
 	for (i = 0; i < nparam; ++i) {
 		if (data->signs[i] > 0)
 			continue;
-		if (isl_term_get_exp(term, isl_dim_param, i) % 2)
+		exp = isl_term_get_exp(term, isl_dim_param, i);
+		if (exp < 0)
+			return isl_stat_error;
+		if (exp % 2)
 			sign = -sign;
 	}
 	for (i = 0; i < nvar; ++i) {
 		if (data->signs[nparam + i] > 0)
 			continue;
-		if (isl_term_get_exp(term, isl_dim_set, i) % 2)
+		exp = isl_term_get_exp(term, isl_dim_set, i);
+		if (exp < 0)
+			return isl_stat_error;
+		if (exp % 2)
 			sign = -sign;
 	}
 
@@ -226,8 +237,6 @@ static isl_stat collect_fixed_sign_terms(__isl_take isl_term *term, void *user)
 	} else
 		isl_term_free(term);
 
-	isl_int_clear(n);
-
 	return isl_stat_ok;
 }
 
@@ -348,22 +357,25 @@ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
 	int save_tight = data->tight;
 	isl_qpolynomial *poly;
 	isl_stat r;
-	unsigned nvar;
+	isl_size nvar, nparam;
 
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (nvar < 0 || nparam < 0)
+		goto error;
 
 	if (data->monotonicity) {
 		isl_qpolynomial *sub;
-		isl_space *dim = isl_qpolynomial_get_domain_space(data->poly);
+		isl_space *space = isl_qpolynomial_get_domain_space(data->poly);
 		if (data->monotonicity * data->sign > 0) {
 			if (data->tight)
 				data->tight = bound_is_integer(upper, nvar);
-			sub = bound2poly(upper, dim, nvar, 1);
+			sub = bound2poly(upper, space, nvar, 1);
 			isl_constraint_free(lower);
 		} else {
 			if (data->tight)
 				data->tight = bound_is_integer(lower, nvar);
-			sub = bound2poly(lower, dim, nvar, -1);
+			sub = bound2poly(lower, space, nvar, -1);
 			isl_constraint_free(upper);
 		}
 		poly = isl_qpolynomial_copy(data->poly);
@@ -372,14 +384,13 @@ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
 	} else {
 		isl_qpolynomial *l, *u;
 		isl_qpolynomial *pos, *neg;
-		isl_space *dim = isl_qpolynomial_get_domain_space(data->poly);
-		unsigned nparam = isl_basic_set_dim(bset, isl_dim_param);
+		isl_space *space = isl_qpolynomial_get_domain_space(data->poly);
 		int sign = data->sign * data->signs[nparam + nvar];
 
 		data->tight = 0;
 
-		u = bound2poly(upper, isl_space_copy(dim), nvar, 1);
-		l = bound2poly(lower, dim, nvar, -1);
+		u = bound2poly(upper, isl_space_copy(space), nvar, 1);
+		l = bound2poly(lower, space, nvar, -1);
 
 		pos = isl_qpolynomial_terms_of_sign(data->poly, data->signs, sign);
 		neg = isl_qpolynomial_terms_of_sign(data->poly, data->signs, -sign);
@@ -391,7 +402,7 @@ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
 		poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1);
 	}
 
-	if (isl_basic_set_dim(bset, isl_dim_set) == 0)
+	if (nvar == 0)
 		r = add_guarded_poly(bset, poly, data);
 	else
 		r = propagate_on_domain(bset, poly, data);
@@ -399,6 +410,11 @@ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
 	data->tight = save_tight;
 
 	return r;
+error:
+	isl_constraint_free(lower);
+	isl_constraint_free(upper);
+	isl_basic_set_free(bset);
+	return isl_stat_error;
 }
 
 /* Recursively perform range propagation on the polynomial "poly"
@@ -407,19 +423,21 @@ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
 static isl_stat propagate_on_domain(__isl_take isl_basic_set *bset,
 	__isl_take isl_qpolynomial *poly, struct range_data *data)
 {
+	isl_bool is_cst;
 	isl_ctx *ctx;
 	isl_qpolynomial *save_poly = data->poly;
 	int save_monotonicity = data->monotonicity;
-	unsigned d;
+	isl_size d;
 
-	if (!bset || !poly)
+	d = isl_basic_set_dim(bset, isl_dim_set);
+	is_cst = isl_qpolynomial_is_cst(poly, NULL, NULL);
+	if (d < 0 || is_cst < 0)
 		goto error;
 
 	ctx = isl_basic_set_get_ctx(bset);
-	d = isl_basic_set_dim(bset, isl_dim_set);
 	isl_assert(ctx, d >= 1, goto error);
 
-	if (isl_qpolynomial_is_cst(poly, NULL, NULL)) {
+	if (is_cst) {
 		bset = isl_basic_set_project_out(bset, isl_dim_set, 0, d);
 		poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, 0, d);
 		return add_guarded_poly(bset, poly, data);
@@ -456,15 +474,18 @@ static isl_stat basic_guarded_poly_bound(__isl_take isl_basic_set *bset,
 {
 	struct range_data *data = (struct range_data *)user;
 	isl_ctx *ctx;
-	unsigned nparam = isl_basic_set_dim(bset, isl_dim_param);
-	unsigned dim = isl_basic_set_dim(bset, isl_dim_set);
+	isl_size nparam = isl_basic_set_dim(bset, isl_dim_param);
+	isl_size dim = isl_basic_set_dim(bset, isl_dim_set);
+	isl_size total = isl_basic_set_dim(bset, isl_dim_all);
 	isl_stat r;
 
 	data->signs = NULL;
 
+	if (nparam < 0 || dim < 0 || total < 0)
+		goto error;
+
 	ctx = isl_basic_set_get_ctx(bset);
-	data->signs = isl_alloc_array(ctx, int,
-					isl_basic_set_dim(bset, isl_dim_all));
+	data->signs = isl_alloc_array(ctx, int, total);
 
 	if (isl_basic_set_dims_get_sign(bset, isl_dim_set, 0, dim,
 					data->signs + nparam) < 0)
@@ -488,11 +509,11 @@ static isl_stat qpolynomial_bound_on_domain_range(
 	__isl_take isl_basic_set *bset, __isl_take isl_qpolynomial *poly,
 	struct range_data *data)
 {
-	unsigned nparam = isl_basic_set_dim(bset, isl_dim_param);
-	unsigned nvar = isl_basic_set_dim(bset, isl_dim_set);
+	isl_size nparam = isl_basic_set_dim(bset, isl_dim_param);
+	isl_size nvar = isl_basic_set_dim(bset, isl_dim_set);
 	isl_set *set = NULL;
 
-	if (!bset)
+	if (nparam < 0 || nvar < 0)
 		goto error;
 
 	if (nvar == 0)

diff  --git a/polly/lib/External/isl/isl_reordering.c b/polly/lib/External/isl/isl_reordering.c
index 754033d26903..33a8976fbc69 100644
--- a/polly/lib/External/isl/isl_reordering.c
+++ b/polly/lib/External/isl/isl_reordering.c
@@ -143,8 +143,10 @@ __isl_give isl_reordering *isl_parameter_alignment_reordering(
 			exp->pos[i] = j;
 			isl_id_free(id_i);
 		} else {
-			int pos;
+			isl_size pos;
 			pos = isl_space_dim(exp->space, isl_dim_param);
+			if (pos < 0)
+				exp->space = isl_space_free(exp->space);
 			exp->space = isl_space_add_dims(exp->space,
 						isl_dim_param, 1);
 			exp->space = isl_space_set_dim_id(exp->space,
@@ -161,6 +163,76 @@ __isl_give isl_reordering *isl_parameter_alignment_reordering(
 	return NULL;
 }
 
+/* Return a reordering that moves the parameters identified by
+ * the elements of "tuple" to a domain tuple inserted into "space".
+ * The parameters that remain, are moved from their original positions
+ * in the list of parameters to their new positions in this list.
+ * The parameters that get removed, are moved to the corresponding
+ * positions in the new domain.  Note that these set dimensions
+ * do not necessarily need to appear as parameters in "space".
+ * Any other dimensions are shifted by the number of extra dimensions
+ * introduced, i.e., the number of dimensions in the new domain
+ * that did not appear as parameters in "space".
+ */
+__isl_give isl_reordering *isl_reordering_unbind_params_insert_domain(
+	__isl_keep isl_space *space, __isl_keep isl_multi_id *tuple)
+{
+	int i, n;
+	int offset, first;
+	isl_ctx *ctx;
+	isl_reordering *r;
+
+	if (!space || !tuple)
+		return NULL;
+
+	ctx = isl_space_get_ctx(space);
+	r = isl_reordering_alloc(ctx, isl_space_dim(space, isl_dim_all));
+	if (!r)
+		return NULL;
+
+	r->space = isl_space_copy(space);
+	r->space = isl_space_unbind_params_insert_domain(r->space, tuple);
+	if (!r->space)
+		return isl_reordering_free(r);
+
+	n = isl_space_dim(r->space, isl_dim_param);
+	for (i = 0; i < n; ++i) {
+		int pos;
+		isl_id *id;
+
+		id = isl_space_get_dim_id(r->space, isl_dim_param, i);
+		if (!id)
+			return isl_reordering_free(r);
+		pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
+		isl_id_free(id);
+		r->pos[pos] = i;
+	}
+
+	offset = isl_space_dim(r->space, isl_dim_param);
+	n = isl_multi_id_size(tuple);
+	for (i = 0; i < n; ++i) {
+		int pos;
+		isl_id *id;
+
+		id = isl_multi_id_get_id(tuple, i);
+		if (!id)
+			return isl_reordering_free(r);
+		pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
+		isl_id_free(id);
+		if (pos < 0)
+			continue;
+		r->pos[pos] = offset + i;
+	}
+
+	offset = isl_space_dim(r->space, isl_dim_all) - r->len;
+	first = isl_space_dim(space, isl_dim_param);
+	n = r->len - first;
+	for (i = 0; i < n; ++i)
+		r->pos[first + i] = first + offset + i;
+
+	return r;
+}
+
 __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
 	unsigned extra)
 {
@@ -169,6 +241,7 @@ __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
 	isl_space *space;
 	isl_reordering *res;
 	int offset;
+	isl_size dim;
 
 	if (!exp)
 		return NULL;
@@ -177,7 +250,10 @@ __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
 
 	ctx = isl_reordering_get_ctx(exp);
 	space = isl_reordering_peek_space(exp);
-	offset = isl_space_dim(space, isl_dim_all) - exp->len;
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0)
+		return isl_reordering_free(exp);
+	offset = dim - exp->len;
 	res = isl_reordering_alloc(ctx, exp->len + extra);
 	if (!res)
 		goto error;
@@ -200,12 +276,13 @@ __isl_give isl_reordering *isl_reordering_extend_space(
 {
 	isl_space *exp_space;
 	isl_reordering *res;
+	isl_size dim;
 
-	if (!exp || !space)
+	dim = isl_space_dim(space, isl_dim_all);
+	if (!exp || dim < 0)
 		goto error;
 
-	res = isl_reordering_extend(isl_reordering_copy(exp),
-				isl_space_dim(space, isl_dim_all) - exp->len);
+	res = isl_reordering_extend(isl_reordering_copy(exp), dim - exp->len);
 	res = isl_reordering_cow(res);
 	if (!res)
 		goto error;

diff  --git a/polly/lib/External/isl/isl_reordering.h b/polly/lib/External/isl/isl_reordering.h
index f7cf1fee86ba..6664749b0ec6 100644
--- a/polly/lib/External/isl/isl_reordering.h
+++ b/polly/lib/External/isl/isl_reordering.h
@@ -24,6 +24,8 @@ __isl_keep isl_space *isl_reordering_peek_space(__isl_keep isl_reordering *r);
 __isl_give isl_space *isl_reordering_get_space(__isl_keep isl_reordering *r);
 __isl_give isl_reordering *isl_parameter_alignment_reordering(
 	__isl_keep isl_space *alignee, __isl_keep isl_space *aligner);
+__isl_give isl_reordering *isl_reordering_unbind_params_insert_domain(
+	__isl_keep isl_space *space, __isl_keep isl_multi_id *tuple);
 __isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp);
 __isl_null isl_reordering *isl_reordering_free(__isl_take isl_reordering *exp);
 __isl_give isl_reordering *isl_reordering_extend_space(

diff  --git a/polly/lib/External/isl/isl_sample.c b/polly/lib/External/isl/isl_sample.c
index 058d689cef5f..ec3a3b63f05f 100644
--- a/polly/lib/External/isl/isl_sample.c
+++ b/polly/lib/External/isl/isl_sample.c
@@ -39,10 +39,12 @@ static __isl_give isl_vec *empty_sample(__isl_take isl_basic_set *bset)
  */
 static __isl_give isl_vec *zero_sample(__isl_take isl_basic_set *bset)
 {
-	unsigned dim;
+	isl_size dim;
 	struct isl_vec *sample;
 
-	dim = isl_basic_set_total_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0)
+		goto error;
 	sample = isl_vec_alloc(bset->ctx, 1 + dim);
 	if (sample) {
 		isl_int_set_si(sample->el[0], 1);
@@ -50,6 +52,9 @@ static __isl_give isl_vec *zero_sample(__isl_take isl_basic_set *bset)
 	}
 	isl_basic_set_free(bset);
 	return sample;
+error:
+	isl_basic_set_free(bset);
+	return NULL;
 }
 
 static __isl_give isl_vec *interval_sample(__isl_take isl_basic_set *bset)
@@ -535,17 +540,18 @@ static __isl_give isl_vec *factored_sample(__isl_take isl_basic_set *bset,
 	int i, n;
 	isl_vec *sample = NULL;
 	isl_ctx *ctx;
-	unsigned nparam;
-	unsigned nvar;
+	isl_size nparam;
+	isl_size nvar;
+	isl_size total;
 
 	ctx = isl_basic_set_get_ctx(bset);
-	if (!ctx)
-		goto error;
-
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (!ctx || nparam < 0 || nvar < 0 || total < 0)
+		goto error;
 
-	sample = isl_vec_alloc(ctx, 1 + isl_basic_set_total_dim(bset));
+	sample = isl_vec_alloc(ctx, 1 + total);
 	if (!sample)
 		goto error;
 	isl_int_set_si(sample->el[0], 1);
@@ -603,7 +609,7 @@ static __isl_give isl_vec *factored_sample(__isl_take isl_basic_set *bset,
  */ 
 static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset)
 {
-	unsigned dim;
+	isl_size dim;
 	struct isl_vec *sample;
 	struct isl_tab *tab = NULL;
 	isl_factorizer *f;
@@ -614,7 +620,9 @@ static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset)
 	if (isl_basic_set_plain_is_empty(bset))
 		return empty_sample(bset);
 
-	dim = isl_basic_set_total_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0)
+		bset = isl_basic_set_free(bset);
 	if (dim == 0)
 		return zero_sample(bset);
 	if (dim == 1)
@@ -676,13 +684,13 @@ static __isl_give isl_basic_set *plug_in(__isl_take isl_basic_set *bset,
 	__isl_take isl_vec *sample)
 {
 	int i;
-	unsigned total;
+	isl_size total;
 	struct isl_mat *T;
 
-	if (!bset || !sample)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0 || !sample)
 		goto error;
 
-	total = isl_basic_set_total_dim(bset);
 	T = isl_mat_alloc(bset->ctx, 1 + total, 1 + total - (sample->size - 1));
 	if (!T)
 		goto error;
@@ -762,17 +770,16 @@ static __isl_give isl_basic_set *shift_cone(__isl_take isl_basic_set *cone,
 	__isl_take isl_vec *vec)
 {
 	int i, j, k;
-	unsigned total;
+	isl_size total;
 
 	struct isl_basic_set *shift = NULL;
 
-	if (!cone || !vec)
+	total = isl_basic_set_dim(cone, isl_dim_all);
+	if (total < 0 || !vec)
 		goto error;
 
 	isl_assert(cone->ctx, cone->n_eq == 0, goto error);
 
-	total = isl_basic_set_total_dim(cone);
-
 	shift = isl_basic_set_alloc_space(isl_basic_set_get_space(cone),
 					0, 0, cone->n_ineq);
 
@@ -819,7 +826,7 @@ static __isl_give isl_basic_set *shift_cone(__isl_take isl_basic_set *cone,
 static __isl_give isl_vec *round_up_in_cone(__isl_take isl_vec *vec,
 	__isl_take isl_basic_set *cone, __isl_take isl_mat *U)
 {
-	unsigned total;
+	isl_size total;
 
 	if (!vec || !cone || !U)
 		goto error;
@@ -831,7 +838,9 @@ static __isl_give isl_vec *round_up_in_cone(__isl_take isl_vec *vec,
 		return vec;
 	}
 
-	total = isl_basic_set_total_dim(cone);
+	total = isl_basic_set_dim(cone, isl_dim_all);
+	if (total < 0)
+		goto error;
 	cone = isl_basic_set_preimage(cone, U);
 	cone = isl_basic_set_remove_dims(cone, isl_dim_set,
 					 0, total - (vec->size - 1));
@@ -920,7 +929,7 @@ static __isl_give isl_vec *vec_concat(__isl_take isl_vec *vec1,
 __isl_give isl_vec *isl_basic_set_sample_with_cone(
 	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *cone)
 {
-	unsigned total;
+	isl_size total;
 	unsigned cone_dim;
 	struct isl_mat *M, *U;
 	struct isl_vec *sample;
@@ -928,11 +937,11 @@ __isl_give isl_vec *isl_basic_set_sample_with_cone(
 	struct isl_ctx *ctx;
 	struct isl_basic_set *bounded;
 
-	if (!bset || !cone)
+	total = isl_basic_set_dim(cone, isl_dim_all);
+	if (!bset || total < 0)
 		goto error;
 
 	ctx = isl_basic_set_get_ctx(bset);
-	total = isl_basic_set_total_dim(cone);
 	cone_dim = total - cone->n_eq;
 
 	M = isl_mat_sub_alloc6(ctx, cone->eq, 0, cone->n_eq, 1, total);
@@ -1103,10 +1112,12 @@ int isl_tab_set_initial_basis_with_cone(struct isl_tab *tab,
  */
 static __isl_give isl_vec *gbr_sample(__isl_take isl_basic_set *bset)
 {
-	unsigned dim;
+	isl_size dim;
 	struct isl_basic_set *cone;
 
-	dim = isl_basic_set_total_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0)
+		goto error;
 
 	cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset));
 	if (!cone)
@@ -1126,7 +1137,7 @@ static __isl_give isl_vec *basic_set_sample(__isl_take isl_basic_set *bset,
 	int bounded)
 {
 	struct isl_ctx *ctx;
-	unsigned dim;
+	isl_size dim;
 	if (!bset)
 		return NULL;
 
@@ -1134,9 +1145,11 @@ static __isl_give isl_vec *basic_set_sample(__isl_take isl_basic_set *bset,
 	if (isl_basic_set_plain_is_empty(bset))
 		return empty_sample(bset);
 
-	dim = isl_basic_set_n_dim(bset);
-	isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
-	isl_assert(ctx, bset->n_div == 0, goto error);
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0 ||
+	    isl_basic_set_check_no_params(bset) < 0 ||
+	    isl_basic_set_check_no_locals(bset) < 0)
+		goto error;
 
 	if (bset->sample && bset->sample->size == 1 + dim) {
 		int contains = isl_basic_set_contains(bset, bset->sample);
@@ -1184,7 +1197,7 @@ __isl_give isl_basic_set *isl_basic_set_from_vec(__isl_take isl_vec *vec)
 	int k;
 	struct isl_basic_set *bset = NULL;
 	struct isl_ctx *ctx;
-	unsigned dim;
+	isl_size dim;
 
 	if (!vec)
 		return NULL;
@@ -1192,9 +1205,9 @@ __isl_give isl_basic_set *isl_basic_set_from_vec(__isl_take isl_vec *vec)
 	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)
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
 		goto error;
-	dim = isl_basic_set_n_dim(bset);
 	for (i = dim - 1; i >= 0; --i) {
 		k = isl_basic_set_alloc_equality(bset);
 		if (k < 0)
@@ -1272,13 +1285,13 @@ __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_vec *vec;
-	isl_space *dim;
+	isl_space *space;
 
-	dim = isl_basic_set_get_space(bset);
+	space = isl_basic_set_get_space(bset);
 	bset = isl_basic_set_underlying_set(bset);
 	vec = isl_basic_set_sample_vec(bset);
 
-	return isl_point_alloc(dim, vec);
+	return isl_point_alloc(space, vec);
 }
 
 __isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set)

diff  --git a/polly/lib/External/isl/isl_scan.c b/polly/lib/External/isl/isl_scan.c
index fea42f150d37..c4666ed1b463 100644
--- a/polly/lib/External/isl/isl_scan.c
+++ b/polly/lib/External/isl/isl_scan.c
@@ -102,7 +102,7 @@ static isl_stat scan_0D(__isl_take isl_basic_set *bset,
 isl_stat isl_basic_set_scan(__isl_take isl_basic_set *bset,
 	struct isl_scan_callback *callback)
 {
-	unsigned dim;
+	isl_size dim;
 	struct isl_mat *B = NULL;
 	struct isl_tab *tab = NULL;
 	struct isl_vec *min;
@@ -112,10 +112,12 @@ isl_stat isl_basic_set_scan(__isl_take isl_basic_set *bset,
 	int init;
 	enum isl_lp_result res;
 
-	if (!bset)
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0) {
+		bset = isl_basic_set_free(bset);
 		return isl_stat_error;
+	}
 
-	dim = isl_basic_set_total_dim(bset);
 	if (dim == 0)
 		return scan_0D(bset, callback);
 

diff  --git a/polly/lib/External/isl/isl_schedule_band.c b/polly/lib/External/isl/isl_schedule_band.c
index d29bb9d3c961..668579a42d78 100644
--- a/polly/lib/External/isl/isl_schedule_band.c
+++ b/polly/lib/External/isl/isl_schedule_band.c
@@ -48,19 +48,21 @@ static __isl_give isl_schedule_band *isl_schedule_band_alloc(isl_ctx *ctx)
 __isl_give isl_schedule_band *isl_schedule_band_from_multi_union_pw_aff(
 	__isl_take isl_multi_union_pw_aff *mupa)
 {
+	isl_size dim;
 	isl_ctx *ctx;
 	isl_schedule_band *band;
 	isl_space *space;
 
 	mupa = isl_multi_union_pw_aff_floor(mupa);
-	if (!mupa)
-		return NULL;
+	dim = isl_multi_union_pw_aff_size(mupa);
+	if (dim < 0)
+		goto error;
 	ctx = isl_multi_union_pw_aff_get_ctx(mupa);
 	band = isl_schedule_band_alloc(ctx);
 	if (!band)
 		goto error;
 
-	band->n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+	band->n = dim;
 	band->coincident = isl_calloc_array(ctx, int, band->n);
 	band->mupa = mupa;
 	space = isl_space_params_alloc(ctx, 0);
@@ -221,9 +223,9 @@ isl_bool isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band *band1,
 
 /* Return the number of scheduling dimensions in the band.
  */
-int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band)
+isl_size isl_schedule_band_n_member(__isl_keep isl_schedule_band *band)
 {
-	return band ? band->n : 0;
+	return band ? band->n : isl_size_error;
 }
 
 /* Is the given scheduling dimension coincident within the band and
@@ -239,7 +241,7 @@ isl_bool isl_schedule_band_member_get_coincident(
 		isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
 			"invalid member position", return isl_bool_error);
 
-	return band->coincident[pos];
+	return isl_bool_ok(band->coincident[pos]);
 }
 
 /* Mark the given scheduling dimension as being coincident or not
@@ -272,7 +274,7 @@ isl_bool isl_schedule_band_get_permutable(__isl_keep isl_schedule_band *band)
 {
 	if (!band)
 		return isl_bool_error;
-	return band->permutable;
+	return isl_bool_ok(band->permutable);
 }
 
 /* Mark the schedule band permutable or not according to "permutable"?
@@ -571,18 +573,30 @@ __isl_give isl_union_set *isl_schedule_band_get_ast_build_options(
 	return options;
 }
 
-/* Does "uset" contain any set that satisfies "is"?
- * "is" is assumed to set its integer argument to 1 if it is satisfied.
+/* Internal data structure for not().
  */
-static int has_any(__isl_keep isl_union_set *uset,
-	isl_stat (*is)(__isl_take isl_set *set, void *user))
+struct isl_not_data {
+	isl_bool (*is)(__isl_keep isl_set *set);
+};
+
+/* Does "set" not satisfy data->is()?
+ */
+static isl_bool not(__isl_keep isl_set *set, void *user)
 {
-	int found = 0;
+	struct isl_not_data *data = user;
+
+	return isl_bool_not(data->is(set));
+}
 
-	if (isl_union_set_foreach_set(uset, is, &found) < 0 && !found)
-		return -1;
+/* Does "uset" contain any set that satisfies "is"?
+ * In other words, is it not the case that all of them do not satisfy "is"?
+ */
+static isl_bool has_any(__isl_keep isl_union_set *uset,
+	isl_bool (*is)(__isl_keep isl_set *set))
+{
+	struct isl_not_data data = { is };
 
-	return found;
+	return isl_bool_not(isl_union_set_every_set(uset, &not, &data));
 }
 
 /* Does "set" live in a space of the form
@@ -590,22 +604,17 @@ static int has_any(__isl_keep isl_union_set *uset,
  *	isolate[[...] -> [...]]
  *
  * ?
- *
- * If so, set *found and abort the search.
  */
-static isl_stat is_isolate(__isl_take isl_set *set, void *user)
+static isl_bool is_isolate(__isl_keep isl_set *set)
 {
-	int *found = user;
-
 	if (isl_set_has_tuple_name(set)) {
 		const char *name;
 		name = isl_set_get_tuple_name(set);
 		if (isl_set_is_wrapping(set) && !strcmp(name, "isolate"))
-			*found = 1;
+			return isl_bool_true;
 	}
-	isl_set_free(set);
 
-	return *found ? isl_stat_error : isl_stat_ok;
+	return isl_bool_false;
 }
 
 /* Does "options" include an option of the ofrm
@@ -614,19 +623,21 @@ static isl_stat is_isolate(__isl_take isl_set *set, void *user)
  *
  * ?
  */
-static int has_isolate_option(__isl_keep isl_union_set *options)
+static isl_bool has_isolate_option(__isl_keep isl_union_set *options)
 {
 	return has_any(options, &is_isolate);
 }
 
 /* Does "set" encode a loop AST generation option?
  */
-static isl_stat is_loop_type_option(__isl_take isl_set *set, void *user)
+static isl_bool is_loop_type_option(__isl_keep isl_set *set)
 {
-	int *found = user;
+	isl_size dim;
 
-	if (isl_set_dim(set, isl_dim_set) == 1 &&
-	    isl_set_has_tuple_name(set)) {
+	dim = isl_set_dim(set, isl_dim_set);
+	if (dim < 0)
+		return isl_bool_error;
+	if (dim == 1 && isl_set_has_tuple_name(set)) {
 		const char *name;
 		enum isl_ast_loop_type type;
 		name = isl_set_get_tuple_name(set);
@@ -634,13 +645,11 @@ static isl_stat is_loop_type_option(__isl_take isl_set *set, void *user)
 		    type <= isl_ast_loop_separate; ++type) {
 			if (strcmp(name, option_str[type]))
 				continue;
-			*found = 1;
-			break;
+			return isl_bool_true;
 		}
 	}
-	isl_set_free(set);
 
-	return *found ? isl_stat_error : isl_stat_ok;
+	return isl_bool_false;
 }
 
 /* Does "set" encode a loop AST generation option for the isolated part?
@@ -650,22 +659,19 @@ static isl_stat is_loop_type_option(__isl_take isl_set *set, void *user)
  *
  * with t equal to "atomic", "unroll" or "separate"?
  */
-static isl_stat is_isolate_loop_type_option(__isl_take isl_set *set, void *user)
+static isl_bool is_isolate_loop_type_option(__isl_keep isl_set *set)
 {
-	int *found = user;
 	const char *name;
 	enum isl_ast_loop_type type;
 	isl_map *map;
 
-	if (!isl_set_is_wrapping(set)) {
-		isl_set_free(set);
-		return isl_stat_ok;
-	}
-	map = isl_set_unwrap(set);
+	if (!isl_set_is_wrapping(set))
+		return isl_bool_false;
+	map = isl_set_unwrap(isl_set_copy(set));
 	if (!isl_map_has_tuple_name(map, isl_dim_in) ||
 	    !isl_map_has_tuple_name(map, isl_dim_out)) {
 		isl_map_free(map);
-		return isl_stat_ok;
+		return isl_bool_false;
 	}
 	name = isl_map_get_tuple_name(map, isl_dim_in);
 	if (!strcmp(name, "isolate")) {
@@ -674,26 +680,26 @@ static isl_stat is_isolate_loop_type_option(__isl_take isl_set *set, void *user)
 		    type <= isl_ast_loop_separate; ++type) {
 			if (strcmp(name, option_str[type]))
 				continue;
-			*found = 1;
-			break;
+			isl_map_free(map);
+			return isl_bool_true;
 		}
 	}
 	isl_map_free(map);
 
-	return *found ? isl_stat_error : isl_stat_ok;
+	return isl_bool_false;
 }
 
 /* Does "options" encode any loop AST generation options
  * for the isolated part?
  */
-static int has_isolate_loop_type_options(__isl_keep isl_union_set *options)
+static isl_bool has_isolate_loop_type_options(__isl_keep isl_union_set *options)
 {
 	return has_any(options, &is_isolate_loop_type_option);
 }
 
 /* Does "options" encode any loop AST generation options?
  */
-static int has_loop_type_options(__isl_keep isl_union_set *options)
+static isl_bool has_loop_type_options(__isl_keep isl_union_set *options)
 {
 	return has_any(options, &is_loop_type_option);
 }
@@ -859,7 +865,7 @@ static __isl_give isl_union_set *clear_isolate_loop_types(
 __isl_give isl_schedule_band *isl_schedule_band_set_ast_build_options(
 	__isl_take isl_schedule_band *band, __isl_take isl_union_set *options)
 {
-	int has_isolate, has_loop_type, has_isolate_loop_type;
+	isl_bool has_isolate, has_loop_type, has_isolate_loop_type;
 
 	band = isl_schedule_band_cow(band);
 	if (!band || !options)
@@ -1076,14 +1082,17 @@ static isl_multi_union_pw_aff *isl_multi_union_pw_aff_tile(
 	__isl_take isl_multi_val *sizes)
 {
 	isl_ctx *ctx;
-	int i, n;
+	int i;
+	isl_size n;
 	isl_val *v;
 	int scale;
 
 	ctx = isl_multi_val_get_ctx(sizes);
 	scale = isl_options_get_tile_scale_tile_loops(ctx);
 
-	n = isl_multi_union_pw_aff_dim(sched, isl_dim_set);
+	n = isl_multi_union_pw_aff_size(sched);
+	if (n < 0)
+		sched = isl_multi_union_pw_aff_free(sched);
 	for (i = 0; i < n; ++i) {
 		isl_union_pw_aff *upa;
 

diff  --git a/polly/lib/External/isl/isl_schedule_band.h b/polly/lib/External/isl/isl_schedule_band.h
index dcf16eb5d49c..fa4e5ca3f6e2 100644
--- a/polly/lib/External/isl/isl_schedule_band.h
+++ b/polly/lib/External/isl/isl_schedule_band.h
@@ -86,7 +86,7 @@ __isl_give isl_schedule_band *isl_schedule_band_replace_ast_build_option(
 	__isl_take isl_schedule_band *band, __isl_take isl_set *drop,
 	__isl_take isl_set *add);
 
-int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band);
+isl_size isl_schedule_band_n_member(__isl_keep isl_schedule_band *band);
 isl_bool isl_schedule_band_member_get_coincident(
 	__isl_keep isl_schedule_band *band, int pos);
 __isl_give isl_schedule_band *isl_schedule_band_member_set_coincident(

diff  --git a/polly/lib/External/isl/isl_schedule_constraints.c b/polly/lib/External/isl/isl_schedule_constraints.c
index 13e8e5f0265a..3d92b53592f4 100644
--- a/polly/lib/External/isl/isl_schedule_constraints.c
+++ b/polly/lib/External/isl/isl_schedule_constraints.c
@@ -479,6 +479,18 @@ static char *key_str[] = {
 	[isl_sc_key_context] = "context",
 };
 
+#undef BASE
+#define BASE set
+#include "print_yaml_field_templ.c"
+
+#undef BASE
+#define BASE union_set
+#include "print_yaml_field_templ.c"
+
+#undef BASE
+#define BASE union_map
+#include "print_yaml_field_templ.c"
+
 /* Print a key, value pair for the edge of type "type" in "sc" to "p".
  *
  * If the edge relation is empty, then it is not printed since
@@ -495,10 +507,7 @@ static __isl_give isl_printer *print_constraint(__isl_take isl_printer *p,
 	if (empty)
 		return p;
 
-	p = isl_printer_print_str(p, key_str[type]);
-	p = isl_printer_yaml_next(p);
-	p = isl_printer_print_union_map(p, sc->constraint[type]);
-	p = isl_printer_yaml_next(p);
+	p = print_yaml_field_union_map(p, key_str[type], sc->constraint[type]);
 
 	return p;
 }
@@ -518,19 +527,14 @@ __isl_give isl_printer *isl_printer_print_schedule_constraints(
 		return isl_printer_free(p);
 
 	p = isl_printer_yaml_start_mapping(p);
-	p = isl_printer_print_str(p, key_str[isl_sc_key_domain]);
-	p = isl_printer_yaml_next(p);
-	p = isl_printer_print_union_set(p, sc->domain);
-	p = isl_printer_yaml_next(p);
+	p = print_yaml_field_union_set(p, key_str[isl_sc_key_domain],
+					sc->domain);
 	universe = isl_set_plain_is_universe(sc->context);
 	if (universe < 0)
 		return isl_printer_free(p);
-	if (!universe) {
-		p = isl_printer_print_str(p, key_str[isl_sc_key_context]);
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_set(p, sc->context);
-		p = isl_printer_yaml_next(p);
-	}
+	if (!universe)
+		p = print_yaml_field_set(p, key_str[isl_sc_key_context],
+						sc->context);
 	p = print_constraint(p, sc, isl_edge_validity);
 	p = print_constraint(p, sc, isl_edge_proximity);
 	p = print_constraint(p, sc, isl_edge_coincidence);
@@ -710,11 +714,13 @@ isl_schedule_constraints_align_params(__isl_take isl_schedule_constraints *sc)
 static isl_stat add_n_basic_map(__isl_take isl_map *map, void *user)
 {
 	int *n = user;
+	isl_size n_basic_map;
 
-	*n += isl_map_n_basic_map(map);
+	n_basic_map = isl_map_n_basic_map(map);
+	*n += n_basic_map;
 	isl_map_free(map);
 
-	return isl_stat_ok;
+	return n_basic_map < 0 ? isl_stat_error : isl_stat_ok;
 }
 
 /* Return the total number of isl_basic_maps in the constraints of "sc".
@@ -738,13 +744,19 @@ int isl_schedule_constraints_n_basic_map(
 
 /* Return the total number of isl_maps in the constraints of "sc".
  */
-int isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints *sc)
+isl_size isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints *sc)
 {
 	enum isl_edge_type i;
 	int n = 0;
 
-	for (i = isl_edge_first; i <= isl_edge_last; ++i)
-		n += isl_union_map_n_map(sc->constraint[i]);
+	for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+		isl_size n_i;
+
+		n_i = isl_union_map_n_map(sc->constraint[i]);
+		if (n_i < 0)
+			return isl_size_error;
+		n += n_i;
+	}
 
 	return n;
 }

diff  --git a/polly/lib/External/isl/isl_schedule_constraints.h b/polly/lib/External/isl/isl_schedule_constraints.h
index a50ec62ccd70..8ec3864d5f4a 100644
--- a/polly/lib/External/isl/isl_schedule_constraints.h
+++ b/polly/lib/External/isl/isl_schedule_constraints.h
@@ -25,6 +25,7 @@ __isl_give isl_schedule_constraints *isl_schedule_constraints_add(
 
 int isl_schedule_constraints_n_basic_map(
 	__isl_keep isl_schedule_constraints *sc);
-int isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints *sc);
+isl_size isl_schedule_constraints_n_map(
+	__isl_keep isl_schedule_constraints *sc);
 
 #endif

diff  --git a/polly/lib/External/isl/isl_schedule_node.c b/polly/lib/External/isl/isl_schedule_node.c
index ba484621f013..5e37276253b1 100644
--- a/polly/lib/External/isl/isl_schedule_node.c
+++ b/polly/lib/External/isl/isl_schedule_node.c
@@ -29,11 +29,12 @@ __isl_give isl_schedule_node *isl_schedule_node_alloc(
 {
 	isl_ctx *ctx;
 	isl_schedule_node *node;
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!schedule || !tree || !ancestors)
-		goto error;
 	n = isl_schedule_tree_list_n_schedule_tree(ancestors);
+	if (!schedule || !tree || n < 0)
+		goto error;
 	if (n > 0 && !child_pos)
 		goto error;
 	ctx = isl_schedule_get_ctx(schedule);
@@ -134,6 +135,7 @@ enum isl_schedule_node_type isl_schedule_node_get_type(
 enum isl_schedule_node_type isl_schedule_node_get_parent_type(
 	__isl_keep isl_schedule_node *node)
 {
+	isl_size n;
 	int pos;
 	int has_parent;
 	isl_schedule_tree *parent;
@@ -147,8 +149,11 @@ enum isl_schedule_node_type isl_schedule_node_get_parent_type(
 	if (!has_parent)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
 			"node has no parent", return isl_schedule_node_error);
+	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_schedule_node_error;
 
-	pos = isl_schedule_tree_list_n_schedule_tree(node->ancestors) - 1;
+	pos = n - 1;
 	parent = isl_schedule_tree_list_get_schedule_tree(node->ancestors, pos);
 	type = isl_schedule_tree_get_type(parent);
 	isl_schedule_tree_free(parent);
@@ -243,7 +248,8 @@ __isl_null isl_schedule_node *isl_schedule_node_free(
 isl_bool isl_schedule_node_is_equal(__isl_keep isl_schedule_node *node1,
 	__isl_keep isl_schedule_node *node2)
 {
-	int i, n1, n2;
+	int i;
+	isl_size n1, n2;
 
 	if (!node1 || !node2)
 		return isl_bool_error;
@@ -254,6 +260,8 @@ isl_bool isl_schedule_node_is_equal(__isl_keep isl_schedule_node *node1,
 
 	n1 = isl_schedule_node_get_tree_depth(node1);
 	n2 = isl_schedule_node_get_tree_depth(node2);
+	if (n1 < 0 || n2 < 0)
+		return isl_bool_error;
 	if (n1 != n2)
 		return isl_bool_false;
 	for (i = 0; i < n1; ++i)
@@ -266,27 +274,36 @@ isl_bool isl_schedule_node_is_equal(__isl_keep isl_schedule_node *node1,
 /* Return the number of outer schedule dimensions of "node"
  * in its schedule tree.
  *
- * Return -1 on error.
+ * Return isl_size_error on error.
  */
-int isl_schedule_node_get_schedule_depth(__isl_keep isl_schedule_node *node)
+isl_size isl_schedule_node_get_schedule_depth(
+	__isl_keep isl_schedule_node *node)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	int depth = 0;
 
 	if (!node)
-		return -1;
+		return isl_size_error;
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_size_error;
 	for (i = n - 1; i >= 0; --i) {
 		isl_schedule_tree *tree;
+		isl_size n;
 
 		tree = isl_schedule_tree_list_get_schedule_tree(
 						    node->ancestors, i);
 		if (!tree)
-			return -1;
+			return isl_size_error;
+		n = 0;
 		if (tree->type == isl_schedule_node_band)
-			depth += isl_schedule_tree_band_n_member(tree);
+			n = isl_schedule_tree_band_n_member(tree);
+		depth += n;
 		isl_schedule_tree_free(tree);
+		if (n < 0)
+			return isl_size_error;
 	}
 
 	return depth;
@@ -314,7 +331,7 @@ struct isl_schedule_node_get_filter_prefix_data {
 	isl_multi_union_pw_aff *prefix;
 };
 
-static int collect_filter_prefix(__isl_keep isl_schedule_tree_list *list,
+static isl_stat collect_filter_prefix(__isl_keep isl_schedule_tree_list *list,
 	int n, struct isl_schedule_node_get_filter_prefix_data *data);
 
 /* Update the filter and prefix information in "data" based on the first "n"
@@ -325,7 +342,8 @@ static int collect_filter_prefix(__isl_keep isl_schedule_tree_list *list,
  * Then we map the results to the expanded space and combined them
  * with the results already in "data".
  */
-static int collect_filter_prefix_expansion(__isl_take isl_schedule_tree *tree,
+static isl_stat collect_filter_prefix_expansion(
+	__isl_take isl_schedule_tree *tree,
 	__isl_keep isl_schedule_tree_list *list, int n,
 	struct isl_schedule_node_get_filter_prefix_data *data)
 {
@@ -378,7 +396,7 @@ static int collect_filter_prefix_expansion(__isl_take isl_schedule_tree *tree,
 	isl_union_map_free(exp);
 	isl_schedule_tree_free(tree);
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Update the filter information in "data" based on the first "n"
@@ -389,7 +407,8 @@ static int collect_filter_prefix_expansion(__isl_take isl_schedule_tree *tree,
  * add it to the universe range of the extension (intersected
  * with the already collected filter, if any).
  */
-static int collect_universe_domain_extension(__isl_take isl_schedule_tree *tree,
+static isl_stat collect_universe_domain_extension(
+	__isl_take isl_schedule_tree *tree,
 	__isl_keep isl_schedule_tree_list *list, int n,
 	struct isl_schedule_node_get_filter_prefix_data *data)
 {
@@ -419,7 +438,7 @@ static int collect_universe_domain_extension(__isl_take isl_schedule_tree *tree,
 
 	isl_schedule_tree_free(tree);
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Update "data" based on the tree node "tree" in case "data" has
@@ -437,30 +456,31 @@ static int collect_universe_domain_extension(__isl_take isl_schedule_tree *tree,
  * to the universe of the schedule domain and replace the zero-dimensional
  * data->prefix by the band schedule (if data->collect_prefix is set).
  */
-static int collect_filter_prefix_init(__isl_keep isl_schedule_tree *tree,
+static isl_stat collect_filter_prefix_init(__isl_keep isl_schedule_tree *tree,
 	struct isl_schedule_node_get_filter_prefix_data *data)
 {
 	enum isl_schedule_node_type type;
 	isl_multi_union_pw_aff *mupa;
 	isl_union_set *filter;
+	isl_size n;
 
 	type = isl_schedule_tree_get_type(tree);
 	switch (type) {
 	case isl_schedule_node_error:
-		return -1;
+		return isl_stat_error;
 	case isl_schedule_node_expansion:
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
-			"should be handled by caller", return -1);
+			"should be handled by caller", return isl_stat_error);
 	case isl_schedule_node_extension:
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
-			"cannot handle extension nodes", return -1);
+			"cannot handle extension nodes", return isl_stat_error);
 	case isl_schedule_node_context:
 	case isl_schedule_node_leaf:
 	case isl_schedule_node_guard:
 	case isl_schedule_node_mark:
 	case isl_schedule_node_sequence:
 	case isl_schedule_node_set:
-		return 0;
+		return isl_stat_ok;
 	case isl_schedule_node_domain:
 		filter = isl_schedule_tree_domain_get_domain(tree);
 		if (data->universe_domain)
@@ -468,8 +488,11 @@ static int collect_filter_prefix_init(__isl_keep isl_schedule_tree *tree,
 		data->filter = filter;
 		break;
 	case isl_schedule_node_band:
-		if (isl_schedule_tree_band_n_member(tree) == 0)
-			return 0;
+		n = isl_schedule_tree_band_n_member(tree);
+		if (n < 0)
+			return isl_stat_error;
+		if (n == 0)
+			return isl_stat_ok;
 		mupa = isl_schedule_tree_band_get_partial_schedule(tree);
 		if (data->collect_prefix) {
 			isl_multi_union_pw_aff_free(data->prefix);
@@ -490,11 +513,11 @@ static int collect_filter_prefix_init(__isl_keep isl_schedule_tree *tree,
 	}
 
 	if ((data->collect_prefix && !data->prefix) || !data->filter)
-		return -1;
+		return isl_stat_error;
 
 	data->initialized = 1;
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Update "data" based on the tree node "tree" in case "data" has
@@ -511,22 +534,23 @@ static int collect_filter_prefix_init(__isl_keep isl_schedule_tree *tree,
  * If "tree" is an extension, then we make sure that we are not collecting
  * information on any extended domain elements.
  */
-static int collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
+static isl_stat collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
 	struct isl_schedule_node_get_filter_prefix_data *data)
 {
 	enum isl_schedule_node_type type;
 	isl_multi_union_pw_aff *mupa;
 	isl_union_set *filter;
 	isl_union_map *extension;
-	int empty;
+	isl_bool empty;
+	isl_size n;
 
 	type = isl_schedule_tree_get_type(tree);
 	switch (type) {
 	case isl_schedule_node_error:
-		return -1;
+		return isl_stat_error;
 	case isl_schedule_node_expansion:
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
-			"should be handled by caller", return -1);
+			"should be handled by caller", return isl_stat_error);
 	case isl_schedule_node_extension:
 		extension = isl_schedule_tree_extension_get_extension(tree);
 		extension = isl_union_map_intersect_range(extension,
@@ -534,11 +558,11 @@ static int collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
 		empty = isl_union_map_is_empty(extension);
 		isl_union_map_free(extension);
 		if (empty < 0)
-			return -1;
+			return isl_stat_error;
 		if (empty)
 			break;
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
-			"cannot handle extension nodes", return -1);
+			"cannot handle extension nodes", return isl_stat_error);
 	case isl_schedule_node_context:
 	case isl_schedule_node_leaf:
 	case isl_schedule_node_guard:
@@ -553,7 +577,10 @@ static int collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
 		data->filter = isl_union_set_intersect(data->filter, filter);
 		break;
 	case isl_schedule_node_band:
-		if (isl_schedule_tree_band_n_member(tree) == 0)
+		n = isl_schedule_tree_band_n_member(tree);
+		if (n < 0)
+			return isl_stat_error;
+		if (n == 0)
 			break;
 		if (!data->collect_prefix)
 			break;
@@ -561,7 +588,7 @@ static int collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
 		data->prefix = isl_multi_union_pw_aff_flat_range_product(mupa,
 								data->prefix);
 		if (!data->prefix)
-			return -1;
+			return isl_stat_error;
 		break;
 	case isl_schedule_node_filter:
 		filter = isl_schedule_tree_filter_get_filter(tree);
@@ -569,11 +596,11 @@ static int collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
 			filter = isl_union_set_universe(filter);
 		data->filter = isl_union_set_intersect(data->filter, filter);
 		if (!data->filter)
-			return -1;
+			return isl_stat_error;
 		break;
 	}
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Collect filter and/or prefix information from the first "n"
@@ -602,22 +629,22 @@ static int collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
  * On successful return, data->initialized will be set since the outermost
  * ancestor is a domain node, which always results in an initialization.
  */
-static int collect_filter_prefix(__isl_keep isl_schedule_tree_list *list,
+static isl_stat collect_filter_prefix(__isl_keep isl_schedule_tree_list *list,
 	int n, struct isl_schedule_node_get_filter_prefix_data *data)
 {
 	int i;
 
 	if (!list)
-		return -1;
+		return isl_stat_error;
 
 	for (i = n - 1; i >= 0; --i) {
 		isl_schedule_tree *tree;
 		enum isl_schedule_node_type type;
-		int r;
+		isl_stat r;
 
 		tree = isl_schedule_tree_list_get_schedule_tree(list, i);
 		if (!tree)
-			return -1;
+			return isl_stat_error;
 		type = isl_schedule_tree_get_type(tree);
 		if (type == isl_schedule_node_expansion)
 			return collect_filter_prefix_expansion(tree, list, i,
@@ -632,10 +659,10 @@ static int collect_filter_prefix(__isl_keep isl_schedule_tree_list *list,
 			r = collect_filter_prefix_update(tree, data);
 		isl_schedule_tree_free(tree);
 		if (r < 0)
-			return -1;
+			return isl_stat_error;
 	}
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Return the concatenation of the partial schedules of all outer band
@@ -656,7 +683,7 @@ __isl_give isl_multi_union_pw_aff *
 isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(
 	__isl_keep isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 	isl_space *space;
 	struct isl_schedule_node_get_filter_prefix_data data;
 
@@ -676,7 +703,7 @@ isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(
 	data.prefix = isl_multi_union_pw_aff_zero(space);
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
-	if (collect_filter_prefix(node->ancestors, n, &data) < 0)
+	if (n < 0 || collect_filter_prefix(node->ancestors, n, &data) < 0)
 		data.prefix = isl_multi_union_pw_aff_free(data.prefix);
 
 	data.prefix = isl_multi_union_pw_aff_intersect_domain(data.prefix,
@@ -708,7 +735,7 @@ __isl_give isl_union_pw_multi_aff *
 isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(
 	__isl_keep isl_schedule_node *node)
 {
-	int n;
+	isl_size n, dim;
 	isl_space *space;
 	isl_union_pw_multi_aff *prefix;
 	struct isl_schedule_node_get_filter_prefix_data data;
@@ -729,11 +756,13 @@ isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(
 	data.prefix = isl_multi_union_pw_aff_zero(space);
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
-	if (collect_filter_prefix(node->ancestors, n, &data) < 0)
+	if (n < 0 || collect_filter_prefix(node->ancestors, n, &data) < 0)
 		data.prefix = isl_multi_union_pw_aff_free(data.prefix);
 
-	if (data.prefix &&
-	    isl_multi_union_pw_aff_dim(data.prefix, isl_dim_set) == 0) {
+	dim = isl_multi_union_pw_aff_dim(data.prefix, isl_dim_set);
+	if (dim < 0)
+		data.prefix = isl_multi_union_pw_aff_free(data.prefix);
+	if (data.prefix && dim == 0) {
 		isl_multi_union_pw_aff_free(data.prefix);
 		prefix = isl_union_pw_multi_aff_from_domain(data.filter);
 	} else {
@@ -773,7 +802,7 @@ __isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_union_map(
 __isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_relation(
 	__isl_keep isl_schedule_node *node)
 {
-	int n;
+	isl_size n, dim;
 	isl_space *space;
 	isl_union_map *prefix;
 	struct isl_schedule_node_get_filter_prefix_data data;
@@ -794,11 +823,13 @@ __isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_relation(
 	data.prefix = isl_multi_union_pw_aff_zero(space);
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
-	if (collect_filter_prefix(node->ancestors, n, &data) < 0)
+	if (n < 0 || collect_filter_prefix(node->ancestors, n, &data) < 0)
 		data.prefix = isl_multi_union_pw_aff_free(data.prefix);
 
-	if (data.prefix &&
-	    isl_multi_union_pw_aff_dim(data.prefix, isl_dim_set) == 0) {
+	dim = isl_multi_union_pw_aff_dim(data.prefix, isl_dim_set);
+	if (dim < 0)
+		data.prefix = isl_multi_union_pw_aff_free(data.prefix);
+	if (data.prefix && dim == 0) {
 		isl_multi_union_pw_aff_free(data.prefix);
 		prefix = isl_union_map_from_domain(data.filter);
 	} else {
@@ -824,7 +855,7 @@ __isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_relation(
 __isl_give isl_union_set *isl_schedule_node_get_domain(
 	__isl_keep isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 	struct isl_schedule_node_get_filter_prefix_data data;
 
 	if (!node)
@@ -845,7 +876,7 @@ __isl_give isl_union_set *isl_schedule_node_get_domain(
 	data.prefix = NULL;
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
-	if (collect_filter_prefix(node->ancestors, n, &data) < 0)
+	if (n < 0 || collect_filter_prefix(node->ancestors, n, &data) < 0)
 		data.filter = isl_union_set_free(data.filter);
 
 	return data.filter;
@@ -863,7 +894,7 @@ __isl_give isl_union_set *isl_schedule_node_get_domain(
 __isl_give isl_union_set *isl_schedule_node_get_universe_domain(
 	__isl_keep isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 	struct isl_schedule_node_get_filter_prefix_data data;
 
 	if (!node)
@@ -884,7 +915,7 @@ __isl_give isl_union_set *isl_schedule_node_get_universe_domain(
 	data.prefix = NULL;
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
-	if (collect_filter_prefix(node->ancestors, n, &data) < 0)
+	if (n < 0 || collect_filter_prefix(node->ancestors, n, &data) < 0)
 		data.filter = isl_union_set_free(data.filter);
 
 	return data.filter;
@@ -926,10 +957,10 @@ __isl_give isl_union_map *isl_schedule_node_get_subtree_schedule_union_map(
 
 /* Return the number of ancestors of "node" in its schedule tree.
  */
-int isl_schedule_node_get_tree_depth(__isl_keep isl_schedule_node *node)
+isl_size isl_schedule_node_get_tree_depth(__isl_keep isl_schedule_node *node)
 {
 	if (!node)
-		return -1;
+		return isl_size_error;
 	return isl_schedule_tree_list_n_schedule_tree(node->ancestors);
 }
 
@@ -939,32 +970,33 @@ int isl_schedule_node_get_tree_depth(__isl_keep isl_schedule_node *node)
  */
 isl_bool isl_schedule_node_has_parent(__isl_keep isl_schedule_node *node)
 {
-	if (!node)
-		return isl_bool_error;
-	if (!node->ancestors)
-		return isl_bool_error;
+	isl_size depth;
 
-	return isl_schedule_tree_list_n_schedule_tree(node->ancestors) != 0;
+	depth = isl_schedule_node_get_tree_depth(node);
+	if (depth < 0)
+		return isl_bool_error;
+	return isl_bool_ok(depth != 0);
 }
 
 /* Return the position of "node" among the children of its parent.
  */
-int isl_schedule_node_get_child_position(__isl_keep isl_schedule_node *node)
+isl_size isl_schedule_node_get_child_position(
+	__isl_keep isl_schedule_node *node)
 {
-	int n;
-	int has_parent;
+	isl_size n;
+	isl_bool has_parent;
 
 	if (!node)
-		return -1;
+		return isl_size_error;
 	has_parent = isl_schedule_node_has_parent(node);
 	if (has_parent < 0)
-		return -1;
+		return isl_size_error;
 	if (!has_parent)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
-			"node has no parent", return -1);
+			"node has no parent", return isl_size_error);
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
-	return node->child_pos[n - 1];
+	return n < 0 ? isl_size_error : node->child_pos[n - 1];
 }
 
 /* Does the parent (if any) of "node" have any children with a smaller child
@@ -973,7 +1005,7 @@ int isl_schedule_node_get_child_position(__isl_keep isl_schedule_node *node)
 isl_bool isl_schedule_node_has_previous_sibling(
 	__isl_keep isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 	isl_bool has_parent;
 
 	if (!node)
@@ -983,8 +1015,10 @@ isl_bool isl_schedule_node_has_previous_sibling(
 		return has_parent;
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_bool_error;
 
-	return node->child_pos[n - 1] > 0;
+	return isl_bool_ok(node->child_pos[n - 1] > 0);
 }
 
 /* Does the parent (if any) of "node" have any children with a greater child
@@ -992,7 +1026,7 @@ isl_bool isl_schedule_node_has_previous_sibling(
  */
 isl_bool isl_schedule_node_has_next_sibling(__isl_keep isl_schedule_node *node)
 {
-	int n, n_child;
+	isl_size n, n_child;
 	isl_bool has_parent;
 	isl_schedule_tree *tree;
 
@@ -1003,13 +1037,15 @@ isl_bool isl_schedule_node_has_next_sibling(__isl_keep isl_schedule_node *node)
 		return has_parent;
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
-	tree = isl_schedule_tree_list_get_schedule_tree(node->ancestors, n - 1);
-	if (!tree)
+	if (n < 0)
 		return isl_bool_error;
-	n_child = isl_schedule_tree_list_n_schedule_tree(tree->children);
+	tree = isl_schedule_tree_list_get_schedule_tree(node->ancestors, n - 1);
+	n_child = isl_schedule_tree_n_children(tree);
 	isl_schedule_tree_free(tree);
+	if (n_child < 0)
+		return isl_bool_error;
 
-	return node->child_pos[n - 1] + 1 < n_child;
+	return isl_bool_ok(node->child_pos[n - 1] + 1 < n_child);
 }
 
 /* Does "node" have any children?
@@ -1022,7 +1058,7 @@ isl_bool isl_schedule_node_has_children(__isl_keep isl_schedule_node *node)
 {
 	if (!node)
 		return isl_bool_error;
-	return !isl_schedule_tree_is_leaf(node->tree);
+	return isl_bool_ok(!isl_schedule_tree_is_leaf(node->tree));
 }
 
 /* Return the number of children of "node"?
@@ -1035,17 +1071,19 @@ isl_bool isl_schedule_node_has_children(__isl_keep isl_schedule_node *node)
  * to the number of children of "node".  If it has zero children,
  * then "node" still has a leaf node as child.
  */
-int isl_schedule_node_n_children(__isl_keep isl_schedule_node *node)
+isl_size isl_schedule_node_n_children(__isl_keep isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 
 	if (!node)
-		return -1;
+		return isl_size_error;
 
 	if (isl_schedule_tree_is_leaf(node->tree))
 		return 0;
 
 	n = isl_schedule_tree_n_children(node->tree);
+	if (n < 0)
+		return isl_size_error;
 	if (n == 0)
 		return 1;
 
@@ -1059,7 +1097,7 @@ int isl_schedule_node_n_children(__isl_keep isl_schedule_node *node)
 __isl_give isl_schedule_node *isl_schedule_node_ancestor(
 	__isl_take isl_schedule_node *node, int generation)
 {
-	int n;
+	isl_size n;
 	isl_schedule_tree *tree;
 
 	if (!node)
@@ -1108,7 +1146,7 @@ __isl_give isl_schedule_node *isl_schedule_node_parent(
 __isl_give isl_schedule_node *isl_schedule_node_root(
 	__isl_take isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 
 	if (!node)
 		return NULL;
@@ -1124,7 +1162,7 @@ __isl_give isl_schedule_node *isl_schedule_node_root(
 __isl_give isl_schedule_node *isl_schedule_node_child(
 	__isl_take isl_schedule_node *node, int pos)
 {
-	int n;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_schedule_tree *tree;
 	int *child_pos;
@@ -1139,6 +1177,8 @@ __isl_give isl_schedule_node *isl_schedule_node_child(
 
 	ctx = isl_schedule_node_get_ctx(node);
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	child_pos = isl_realloc_array(ctx, node->child_pos, int, n + 1);
 	if (!child_pos)
 		return isl_schedule_node_free(node);
@@ -1176,7 +1216,7 @@ __isl_give isl_schedule_node *isl_schedule_node_first_child(
 __isl_give isl_schedule_node *isl_schedule_node_previous_sibling(
 	__isl_take isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 	isl_schedule_tree *parent, *tree;
 
 	node = isl_schedule_node_cow(node);
@@ -1188,6 +1228,8 @@ __isl_give isl_schedule_node *isl_schedule_node_previous_sibling(
 			return isl_schedule_node_free(node));
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	parent = isl_schedule_tree_list_get_schedule_tree(node->ancestors,
 									n - 1);
 	if (!parent)
@@ -1210,7 +1252,7 @@ __isl_give isl_schedule_node *isl_schedule_node_previous_sibling(
 __isl_give isl_schedule_node *isl_schedule_node_next_sibling(
 	__isl_take isl_schedule_node *node)
 {
-	int n;
+	isl_size n;
 	isl_schedule_tree *parent, *tree;
 
 	node = isl_schedule_node_cow(node);
@@ -1222,6 +1264,8 @@ __isl_give isl_schedule_node *isl_schedule_node_next_sibling(
 			return isl_schedule_node_free(node));
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	parent = isl_schedule_tree_list_get_schedule_tree(node->ancestors,
 									n - 1);
 	if (!parent)
@@ -1260,23 +1304,27 @@ static __isl_give isl_schedule_node *traverse(
 		__isl_take isl_schedule_node *node, void *user),
 	void *user)
 {
-	int depth;
-
-	if (!node)
-		return NULL;
+	isl_size depth;
+	isl_size node_depth;
 
 	depth = isl_schedule_node_get_tree_depth(node);
+	if (depth < 0)
+		return isl_schedule_node_free(node);
+
 	do {
 		node = enter(node, user);
 		node = leave(node, user);
-		while (node && isl_schedule_node_get_tree_depth(node) > depth &&
+		while ((node_depth = isl_schedule_node_get_tree_depth(node)) >
+				depth &&
 				!isl_schedule_node_has_next_sibling(node)) {
 			node = isl_schedule_node_parent(node);
 			node = leave(node, user);
 		}
-		if (node && isl_schedule_node_get_tree_depth(node) > depth)
+		if (node_depth < 0)
+			return isl_schedule_node_free(node);
+		if (node_depth > depth)
 			node = isl_schedule_node_next_sibling(node);
-	} while (node && isl_schedule_node_get_tree_depth(node) > depth);
+	} while (node_depth > depth);
 
 	return node;
 }
@@ -1478,12 +1526,13 @@ isl_stat isl_schedule_node_foreach_ancestor_top_down(
 	isl_stat (*fn)(__isl_keep isl_schedule_node *node, void *user),
 	void *user)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!node)
+	n = isl_schedule_node_get_tree_depth(node);
+	if (n < 0)
 		return isl_stat_error;
 
-	n = isl_schedule_node_get_tree_depth(node);
 	for (i = 0; i < n; ++i) {
 		isl_schedule_node *ancestor;
 		isl_stat r;
@@ -1512,9 +1561,11 @@ isl_bool isl_schedule_node_is_subtree_anchored(
 
 /* Return the number of members in the given band node.
  */
-unsigned isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node)
+isl_size isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node)
 {
-	return node ? isl_schedule_tree_band_n_member(node->tree) : 0;
+	if (!node)
+		return isl_size_error;
+	return isl_schedule_tree_band_n_member(node->tree);
 }
 
 /* Is the band member at position "pos" of the band node "node"
@@ -1614,6 +1665,7 @@ __isl_give isl_multi_union_pw_aff *isl_schedule_node_band_get_partial_schedule(
 __isl_give isl_union_map *isl_schedule_node_band_get_partial_schedule_union_map(
 	__isl_keep isl_schedule_node *node)
 {
+	isl_size n;
 	isl_multi_union_pw_aff *mupa;
 
 	if (!node)
@@ -1622,7 +1674,10 @@ __isl_give isl_union_map *isl_schedule_node_band_get_partial_schedule_union_map(
 	if (isl_schedule_node_get_type(node) != isl_schedule_node_band)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
 			"not a band node", return NULL);
-	if (isl_schedule_node_band_n_member(node) == 0) {
+	n = isl_schedule_node_band_n_member(node);
+	if (n < 0)
+		return NULL;
+	if (n == 0) {
 		isl_union_set *domain;
 
 		domain = isl_schedule_node_get_universe_domain(node);
@@ -1729,12 +1784,12 @@ __isl_give isl_schedule_node *isl_schedule_node_band_set_ast_build_options(
 __isl_give isl_set *isl_schedule_node_band_get_ast_isolate_option(
 	__isl_keep isl_schedule_node *node)
 {
-	int depth;
+	isl_size depth;
 
-	if (!node)
+	depth = isl_schedule_node_get_schedule_depth(node);
+	if (depth < 0)
 		return NULL;
 
-	depth = isl_schedule_node_get_schedule_depth(node);
 	return isl_schedule_tree_band_get_ast_isolate_option(node->tree, depth);
 }
 
@@ -1980,7 +2035,8 @@ __isl_give isl_schedule_node *isl_schedule_node_band_sink(
 	enum isl_schedule_node_type type;
 	isl_schedule_tree *tree, *child;
 	isl_union_pw_multi_aff *contraction;
-	int anchored;
+	isl_bool anchored;
+	isl_size n;
 
 	if (!node)
 		return NULL;
@@ -1996,7 +2052,10 @@ __isl_give isl_schedule_node *isl_schedule_node_band_sink(
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
 			"cannot sink band node in anchored subtree",
 			return isl_schedule_node_free(node));
-	if (isl_schedule_tree_n_children(node->tree) == 0)
+	n = isl_schedule_tree_n_children(node->tree);
+	if (n < 0)
+		return isl_schedule_node_free(node);
+	if (n == 0)
 		return node;
 
 	contraction = isl_schedule_node_get_subtree_contraction(node);
@@ -2019,10 +2078,12 @@ __isl_give isl_schedule_node *isl_schedule_node_band_sink(
 __isl_give isl_schedule_node *isl_schedule_node_band_split(
 	__isl_take isl_schedule_node *node, int pos)
 {
-	int depth;
+	isl_size depth;
 	isl_schedule_tree *tree;
 
 	depth = isl_schedule_node_get_schedule_depth(node);
+	if (depth < 0)
+		return isl_schedule_node_free(node);
 	tree = isl_schedule_node_get_tree(node);
 	tree = isl_schedule_tree_band_split(tree, pos, depth);
 	return isl_schedule_node_graft_tree(node, tree);
@@ -2250,7 +2311,8 @@ __isl_give isl_schedule_node *isl_schedule_node_sequence_splice(
 __isl_give isl_schedule_node *isl_schedule_node_sequence_splice_child(
 	__isl_take isl_schedule_node *node, int pos)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_union_set *filter;
 	isl_schedule_node *child;
 	isl_schedule_tree *tree;
@@ -2267,10 +2329,12 @@ __isl_give isl_schedule_node *isl_schedule_node_sequence_splice_child(
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
 			"not a sequence node",
 			return isl_schedule_node_free(node));
+	n = isl_schedule_node_n_children(node);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	child = isl_schedule_node_copy(node);
 	node = isl_schedule_node_parent(node);
 	filter = isl_schedule_node_filter_get_filter(node);
-	n = isl_schedule_node_n_children(child);
 	for (i = 0; i < n; ++i) {
 		child = isl_schedule_node_child(child, i);
 		child = isl_schedule_node_filter_intersect_filter(child,
@@ -2306,7 +2370,8 @@ static __isl_give isl_schedule_node *update_ancestors(
 	__isl_give isl_schedule_tree *(*fn)(__isl_take isl_schedule_tree *tree,
 		__isl_keep isl_schedule_node *pos, void *user), void *user)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	int is_leaf;
 	isl_schedule_tree *tree;
 	isl_schedule_node *pos = NULL;
@@ -2319,6 +2384,8 @@ static __isl_give isl_schedule_node *update_ancestors(
 		return isl_schedule_node_free(pos);
 
 	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_schedule_node_free(pos);
 	tree = isl_schedule_tree_copy(node->tree);
 
 	for (i = n - 1; i >= 0; --i) {
@@ -2572,7 +2639,8 @@ static __isl_give isl_schedule_node *isl_schedule_node_insert_children(
 	enum isl_schedule_node_type type,
 	__isl_take isl_union_set_list *filters)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_schedule_tree *tree;
 	isl_schedule_tree_list *list;
@@ -2580,11 +2648,11 @@ static __isl_give isl_schedule_node *isl_schedule_node_insert_children(
 	if (check_insert(node) < 0)
 		node = isl_schedule_node_free(node);
 
-	if (!node || !filters)
+	n = isl_union_set_list_n_union_set(filters);
+	if (!node || n < 0)
 		goto error;
 
 	ctx = isl_schedule_node_get_ctx(node);
-	n = isl_union_set_list_n_union_set(filters);
 	list = isl_schedule_tree_list_alloc(ctx, n);
 	for (i = 0; i < n; ++i) {
 		isl_schedule_node *node_i;
@@ -2677,18 +2745,19 @@ __isl_give isl_schedule_node *isl_schedule_node_cut(
 __isl_give isl_schedule_node *isl_schedule_node_delete(
 	__isl_take isl_schedule_node *node)
 {
-	int n;
+	isl_size n, depth;
 	isl_schedule_tree *tree;
 	enum isl_schedule_node_type type;
 
-	if (!node)
-		return NULL;
+	depth = isl_schedule_node_get_tree_depth(node);
+	n = isl_schedule_node_n_children(node);
+	if (depth < 0 || n < 0)
+		return isl_schedule_node_free(node);
 
-	if (isl_schedule_node_get_tree_depth(node) == 0)
+	if (depth == 0)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
 			"cannot delete root node",
 			return isl_schedule_node_free(node));
-	n = isl_schedule_node_n_children(node);
 	if (n != 1)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
 			"can only delete node with a single child",
@@ -2760,10 +2829,10 @@ struct isl_schedule_group_data {
 
 /* Is domain covered by data->domain within data->domain_universe?
  */
-static int locally_covered_by_domain(__isl_keep isl_union_set *domain,
+static isl_bool locally_covered_by_domain(__isl_keep isl_union_set *domain,
 	struct isl_schedule_group_data *data)
 {
-	int is_subset;
+	isl_bool is_subset;
 	isl_union_set *test;
 
 	test = isl_union_set_copy(domain);
@@ -2794,8 +2863,9 @@ static __isl_give isl_schedule_tree *group_band(
 	isl_union_set *domain;
 	isl_multi_aff *ma;
 	isl_multi_union_pw_aff *mupa, *partial;
-	int is_covered;
-	int depth, n, has_id;
+	isl_bool is_covered;
+	isl_size depth, n;
+	isl_bool has_id;
 
 	domain = isl_schedule_node_get_domain(pos);
 	is_covered = locally_covered_by_domain(domain, data);
@@ -2810,6 +2880,8 @@ static __isl_give isl_schedule_tree *group_band(
 		return isl_schedule_tree_free(tree);
 	depth = isl_schedule_node_get_schedule_depth(pos);
 	n = isl_schedule_tree_band_n_member(tree);
+	if (depth < 0 || n < 0)
+		return isl_schedule_tree_free(tree);
 	ma = isl_multi_aff_copy(data->sched);
 	ma = isl_multi_aff_drop_dims(ma, isl_dim_out, 0, depth);
 	ma = isl_multi_aff_drop_dims(ma, isl_dim_out, n, data->dim - depth - n);
@@ -2836,10 +2908,12 @@ static __isl_give isl_schedule_tree *group_band(
 static __isl_give isl_union_set *union_set_drop_extra_params(
 	__isl_take isl_union_set *uset, __isl_keep isl_space *space, int n)
 {
-	int n2;
+	isl_size n2;
 
 	uset = isl_union_set_align_params(uset, isl_space_copy(space));
 	n2 = isl_union_set_dim(uset, isl_dim_param);
+	if (n2 < 0)
+		return isl_union_set_free(uset);
 	uset = isl_union_set_project_out(uset, isl_dim_param, n, n2 - n);
 
 	return uset;
@@ -2860,10 +2934,14 @@ static __isl_give isl_schedule_tree *group_context(
 {
 	isl_space *space;
 	isl_union_set *domain;
-	int n1, n2;
-	int involves;
+	isl_size n1, n2;
+	isl_bool involves;
+	isl_size depth;
 
-	if (isl_schedule_node_get_tree_depth(pos) == 1)
+	depth = isl_schedule_node_get_tree_depth(pos);
+	if (depth < 0)
+		return isl_schedule_tree_free(tree);
+	if (depth == 1)
 		return tree;
 
 	domain = isl_schedule_node_get_universe_domain(pos);
@@ -2874,7 +2952,7 @@ static __isl_give isl_schedule_tree *group_context(
 	data->expansion = isl_union_map_align_params(data->expansion, space);
 	n2 = isl_union_map_dim(data->expansion, isl_dim_param);
 
-	if (!data->expansion)
+	if (n1 < 0 || n2 < 0)
 		return isl_schedule_tree_free(tree);
 	if (n1 == n2)
 		return tree;
@@ -2895,6 +2973,9 @@ static __isl_give isl_schedule_tree *group_context(
 	data->contraction = isl_union_pw_multi_aff_align_params(
 				data->contraction, isl_space_copy(space));
 	n2 = isl_union_pw_multi_aff_dim(data->contraction, isl_dim_param);
+	if (n2 < 0)
+		data->contraction =
+				isl_union_pw_multi_aff_free(data->contraction);
 	data->contraction = isl_union_pw_multi_aff_drop_dims(data->contraction,
 				isl_dim_param, n1, n2 - n1);
 
@@ -2908,6 +2989,8 @@ static __isl_give isl_schedule_tree *group_context(
 	data->sched = isl_multi_aff_align_params(data->sched,
 				isl_space_copy(space));
 	n2 = isl_multi_aff_dim(data->sched, isl_dim_param);
+	if (n2 < 0)
+		data->sched = isl_multi_aff_free(data->sched);
 	data->sched = isl_multi_aff_drop_dims(data->sched,
 				isl_dim_param, n1, n2 - n1);
 
@@ -2930,7 +3013,7 @@ static __isl_give isl_schedule_tree *group_domain(
 	struct isl_schedule_group_data *data)
 {
 	isl_union_set *domain;
-	int is_subset;
+	isl_bool is_subset;
 
 	domain = isl_schedule_tree_domain_get_domain(tree);
 	is_subset = isl_union_set_is_subset(data->domain, domain);
@@ -3033,7 +3116,7 @@ static __isl_give isl_schedule_tree *group_ancestor(
 {
 	struct isl_schedule_group_data *data = user;
 	isl_union_set *domain;
-	int is_covered;
+	isl_bool is_covered;
 
 	if (!tree || !pos)
 		return isl_schedule_tree_free(tree);
@@ -3114,9 +3197,11 @@ __isl_give isl_schedule_node *isl_schedule_node_group(
 	isl_union_set *domain;
 	isl_union_pw_multi_aff *contraction;
 	isl_union_map *expansion;
-	int disjoint;
+	isl_bool disjoint;
+	isl_size depth;
 
-	if (!node || !group_id)
+	depth = isl_schedule_node_get_schedule_depth(node);
+	if (depth < 0 || !group_id)
 		goto error;
 	if (check_insert(node) < 0)
 		goto error;
@@ -3126,7 +3211,7 @@ __isl_give isl_schedule_node *isl_schedule_node_group(
 	data.domain_universe = isl_union_set_copy(domain);
 	data.domain_universe = isl_union_set_universe(data.domain_universe);
 
-	data.dim = isl_schedule_node_get_schedule_depth(node);
+	data.dim = depth;
 	if (data.dim == 0) {
 		isl_ctx *ctx;
 		isl_set *set;
@@ -3236,7 +3321,7 @@ struct isl_node_gist_data {
 static __isl_give isl_schedule_node *gist_enter_expansion(
 	__isl_take isl_schedule_node *node, struct isl_node_gist_data *data)
 {
-	int n;
+	isl_size n;
 	isl_union_set *inner;
 	isl_union_map *expansion;
 	isl_union_pw_multi_aff *contraction;
@@ -3244,6 +3329,8 @@ static __isl_give isl_schedule_node *gist_enter_expansion(
 	data->n_expansion++;
 
 	n = isl_union_set_list_n_union_set(data->filters);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	inner = isl_union_set_list_get_union_set(data->filters, n - 1);
 	expansion = isl_schedule_node_expansion_get_expansion(node);
 	inner = isl_union_set_apply(inner, expansion);
@@ -3275,7 +3362,7 @@ static __isl_give isl_schedule_node *gist_enter_expansion(
 static __isl_give isl_schedule_node *gist_leave_expansion(
 	__isl_take isl_schedule_node *node, struct isl_node_gist_data *data)
 {
-	int n;
+	isl_size n;
 	isl_bool identity;
 	isl_union_map *expansion;
 
@@ -3289,6 +3376,8 @@ static __isl_give isl_schedule_node *gist_leave_expansion(
 		node = isl_schedule_node_delete(node);
 
 	n = isl_union_set_list_n_union_set(data->filters);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	data->filters = isl_union_set_list_drop(data->filters, n - 1, 1);
 
 	data->n_expansion--;
@@ -3305,11 +3394,13 @@ static __isl_give isl_schedule_node *gist_leave_expansion(
 static __isl_give isl_schedule_node *gist_enter_extension(
 	__isl_take isl_schedule_node *node, struct isl_node_gist_data *data)
 {
-	int n;
+	isl_size n;
 	isl_union_set *inner, *extra;
 	isl_union_map *extension;
 
 	n = isl_union_set_list_n_union_set(data->filters);
+	if (n < 0)
+		return isl_schedule_node_free(node);
 	inner = isl_union_set_list_get_union_set(data->filters, n - 1);
 	extension = isl_schedule_node_extension_get_extension(node);
 	extra = isl_union_map_range(extension);
@@ -3327,14 +3418,14 @@ static __isl_give isl_schedule_node *gist_enter_extension(
  * this test since the current domain elements are incomparable
  * to the domain elements in the original context.
  */
-static int gist_done(__isl_keep isl_schedule_node *node,
+static isl_bool gist_done(__isl_keep isl_schedule_node *node,
 	struct isl_node_gist_data *data)
 {
 	isl_union_set *filter, *outer;
-	int subset;
+	isl_bool subset;
 
 	if (data->n_expansion != 0)
-		return 0;
+		return isl_bool_false;
 
 	filter = isl_schedule_node_filter_get_filter(node);
 	outer = isl_union_set_list_get_union_set(data->filters, 0);
@@ -3381,8 +3472,8 @@ static __isl_give isl_schedule_node *gist_enter(
 
 	do {
 		isl_union_set *filter, *inner;
-		int done, empty;
-		int n;
+		isl_bool done, empty;
+		isl_size n;
 
 		switch (isl_schedule_node_get_type(node)) {
 		case isl_schedule_node_error:
@@ -3407,14 +3498,14 @@ static __isl_give isl_schedule_node *gist_enter(
 		}
 		done = gist_done(node, data);
 		filter = isl_schedule_node_filter_get_filter(node);
-		if (done < 0 || done) {
+		n = isl_union_set_list_n_union_set(data->filters);
+		if (n < 0 || done < 0 || done) {
 			data->filters = isl_union_set_list_add(data->filters,
 								filter);
-			if (done < 0)
+			if (n < 0 || done < 0)
 				return isl_schedule_node_free(node);
 			return node;
 		}
-		n = isl_union_set_list_n_union_set(data->filters);
 		inner = isl_union_set_list_get_union_set(data->filters, n - 1);
 		filter = isl_union_set_gist(filter, isl_union_set_copy(inner));
 		node = isl_schedule_node_filter_set_filter(node,
@@ -3467,7 +3558,8 @@ static __isl_give isl_schedule_node *gist_leave(
 {
 	struct isl_node_gist_data *data = user;
 	isl_schedule_tree *tree;
-	int i, n;
+	int i;
+	isl_size n;
 	isl_union_set *filter;
 
 	switch (isl_schedule_node_get_type(node)) {
@@ -3479,11 +3571,15 @@ static __isl_give isl_schedule_node *gist_leave(
 	case isl_schedule_node_extension:
 	case isl_schedule_node_filter:
 		n = isl_union_set_list_n_union_set(data->filters);
+		if (n < 0)
+			return isl_schedule_node_free(node);
 		data->filters = isl_union_set_list_drop(data->filters,
 							n - 1, 1);
 		break;
 	case isl_schedule_node_band:
 		n = isl_union_set_list_n_union_set(data->filters);
+		if (n < 0)
+			return isl_schedule_node_free(node);
 		filter = isl_union_set_list_get_union_set(data->filters, n - 1);
 		node = isl_schedule_node_band_gist(node, filter);
 		break;
@@ -3491,10 +3587,12 @@ static __isl_give isl_schedule_node *gist_leave(
 	case isl_schedule_node_sequence:
 		tree = isl_schedule_node_get_tree(node);
 		n = isl_schedule_tree_n_children(tree);
+		if (n < 0)
+			tree = isl_schedule_tree_free(tree);
 		for (i = n - 1; i >= 0; --i) {
 			isl_schedule_tree *child;
 			isl_union_set *filter;
-			int empty;
+			isl_bool empty;
 
 			child = isl_schedule_tree_get_child(tree, i);
 			filter = isl_schedule_tree_filter_get_filter(child);
@@ -3507,6 +3605,8 @@ static __isl_give isl_schedule_node *gist_leave(
 				tree = isl_schedule_tree_drop_child(tree, i);
 		}
 		n = isl_schedule_tree_n_children(tree);
+		if (n < 0)
+			tree = isl_schedule_tree_free(tree);
 		node = isl_schedule_node_graft_tree(node, tree);
 		if (n == 1) {
 			node = isl_schedule_node_delete(node);
@@ -3662,7 +3762,7 @@ static __isl_give isl_schedule_node *subtree_expansion_enter(
 		enum isl_schedule_node_type type;
 		isl_union_set *filter;
 		isl_union_map *inner, *expansion;
-		int n;
+		isl_size n;
 
 		switch (isl_schedule_node_get_type(node)) {
 		case isl_schedule_node_error:
@@ -3674,6 +3774,9 @@ static __isl_give isl_schedule_node *subtree_expansion_enter(
 				break;
 			filter = isl_schedule_node_filter_get_filter(node);
 			n = isl_union_map_list_n_union_map(data->expansions);
+			if (n < 0)
+				data->expansions =
+				    isl_union_map_list_free(data->expansions);
 			inner =
 			    isl_union_map_list_get_union_map(data->expansions,
 								n - 1);
@@ -3683,6 +3786,9 @@ static __isl_give isl_schedule_node *subtree_expansion_enter(
 			break;
 		case isl_schedule_node_expansion:
 			n = isl_union_map_list_n_union_map(data->expansions);
+			if (n < 0)
+				data->expansions =
+				    isl_union_map_list_free(data->expansions);
 			expansion =
 				isl_schedule_node_expansion_get_expansion(node);
 			inner =
@@ -3724,7 +3830,7 @@ static __isl_give isl_schedule_node *subtree_expansion_leave(
 	__isl_take isl_schedule_node *node, void *user)
 {
 	struct isl_subtree_expansion_data *data = user;
-	int n;
+	isl_size n;
 	isl_union_map *inner;
 	enum isl_schedule_node_type type;
 
@@ -3737,11 +3843,17 @@ static __isl_give isl_schedule_node *subtree_expansion_leave(
 		    type != isl_schedule_node_sequence)
 			break;
 		n = isl_union_map_list_n_union_map(data->expansions);
+		if (n < 0)
+			data->expansions =
+				    isl_union_map_list_free(data->expansions);
 		data->expansions = isl_union_map_list_drop(data->expansions,
 							n - 1, 1);
 		break;
 	case isl_schedule_node_leaf:
 		n = isl_union_map_list_n_union_map(data->expansions);
+		if (n < 0)
+			data->expansions =
+				    isl_union_map_list_free(data->expansions);
 		inner = isl_union_map_list_get_union_map(data->expansions,
 							n - 1);
 		data->res = isl_union_map_union(data->res, inner);
@@ -3835,7 +3947,7 @@ static __isl_give isl_schedule_node *subtree_contraction_enter(
 		enum isl_schedule_node_type type;
 		isl_union_set *filter;
 		isl_union_pw_multi_aff *inner, *contraction;
-		int n;
+		isl_size n;
 
 		switch (isl_schedule_node_get_type(node)) {
 		case isl_schedule_node_error:
@@ -3848,6 +3960,10 @@ static __isl_give isl_schedule_node *subtree_contraction_enter(
 			filter = isl_schedule_node_filter_get_filter(node);
 			n = isl_union_pw_multi_aff_list_n_union_pw_multi_aff(
 						data->contractions);
+			if (n < 0)
+				data->contractions =
+				    isl_union_pw_multi_aff_list_free(
+							    data->contractions);
 			inner =
 			    isl_union_pw_multi_aff_list_get_union_pw_multi_aff(
 						data->contractions, n - 1);
@@ -3860,6 +3976,10 @@ static __isl_give isl_schedule_node *subtree_contraction_enter(
 		case isl_schedule_node_expansion:
 			n = isl_union_pw_multi_aff_list_n_union_pw_multi_aff(
 						data->contractions);
+			if (n < 0)
+				data->contractions =
+				    isl_union_pw_multi_aff_list_free(
+							    data->contractions);
 			contraction =
 			    isl_schedule_node_expansion_get_contraction(node);
 			inner =
@@ -3903,7 +4023,7 @@ static __isl_give isl_schedule_node *subtree_contraction_leave(
 	__isl_take isl_schedule_node *node, void *user)
 {
 	struct isl_subtree_contraction_data *data = user;
-	int n;
+	isl_size n;
 	isl_union_pw_multi_aff *inner;
 	enum isl_schedule_node_type type;
 
@@ -3917,6 +4037,9 @@ static __isl_give isl_schedule_node *subtree_contraction_leave(
 			break;
 		n = isl_union_pw_multi_aff_list_n_union_pw_multi_aff(
 						data->contractions);
+		if (n < 0)
+			data->contractions = isl_union_pw_multi_aff_list_free(
+							    data->contractions);
 		data->contractions =
 			isl_union_pw_multi_aff_list_drop(data->contractions,
 							n - 1, 1);
@@ -3924,6 +4047,9 @@ static __isl_give isl_schedule_node *subtree_contraction_leave(
 	case isl_schedule_node_leaf:
 		n = isl_union_pw_multi_aff_list_n_union_pw_multi_aff(
 						data->contractions);
+		if (n < 0)
+			data->contractions = isl_union_pw_multi_aff_list_free(
+							    data->contractions);
 		inner = isl_union_pw_multi_aff_list_get_union_pw_multi_aff(
 						data->contractions, n - 1);
 		data->res = isl_union_pw_multi_aff_union_add(data->res, inner);
@@ -3987,17 +4113,20 @@ __isl_give isl_union_pw_multi_aff *isl_schedule_node_get_subtree_contraction(
 /* Do the nearest "n" ancestors of "node" have the types given in "types"
  * (starting at the parent of "node")?
  */
-static int has_ancestors(__isl_keep isl_schedule_node *node,
+static isl_bool has_ancestors(__isl_keep isl_schedule_node *node,
 	int n, enum isl_schedule_node_type *types)
 {
-	int i, n_ancestor;
+	int i;
+	isl_size n_ancestor;
 
 	if (!node)
-		return -1;
+		return isl_bool_error;
 
 	n_ancestor = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n_ancestor < 0)
+		return isl_bool_error;
 	if (n_ancestor < n)
-		return 0;
+		return isl_bool_false;
 
 	for (i = 0; i < n; ++i) {
 		isl_schedule_tree *tree;
@@ -4006,14 +4135,14 @@ static int has_ancestors(__isl_keep isl_schedule_node *node,
 		tree = isl_schedule_tree_list_get_schedule_tree(node->ancestors,
 							    n_ancestor - 1 - i);
 		if (!tree)
-			return -1;
+			return isl_bool_error;
 		correct_type = isl_schedule_tree_get_type(tree) == types[i];
 		isl_schedule_tree_free(tree);
 		if (!correct_type)
-			return 0;
+			return isl_bool_false;
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 /* Given a node "node" that appears in an extension (i.e., it is the child
@@ -4058,12 +4187,14 @@ static int is_disjoint_extension(__isl_keep isl_schedule_node *node,
 static __isl_give isl_schedule_node *extend_extension(
 	__isl_take isl_schedule_node *node, __isl_take isl_union_map *extension)
 {
-	int pos;
-	int disjoint;
+	isl_size pos;
+	isl_bool disjoint;
 	isl_union_map *node_extension;
 
 	node = isl_schedule_node_parent(node);
 	pos = isl_schedule_node_get_child_position(node);
+	if (pos < 0)
+		node = isl_schedule_node_free(node);
 	node = isl_schedule_node_parent(node);
 	node = isl_schedule_node_parent(node);
 	node_extension = isl_schedule_node_extension_get_extension(node);
@@ -4142,7 +4273,7 @@ static __isl_give isl_schedule_node *insert_extension(
 		  isl_schedule_node_extension };
 	isl_union_set *domain;
 	isl_union_set *filter;
-	int in_ext;
+	isl_bool in_ext;
 
 	in_ext = has_ancestors(node, 3, ancestors);
 	if (in_ext < 0)
@@ -4183,11 +4314,13 @@ static __isl_give isl_schedule_node *graft_or_splice(
 	__isl_take isl_schedule_node *node, __isl_take isl_schedule_tree *tree,
 	int tree_pos)
 {
-	int pos;
+	isl_size pos;
 
 	if (isl_schedule_node_get_parent_type(node) ==
 	    isl_schedule_node_sequence) {
 		pos = isl_schedule_node_get_child_position(node);
+		if (pos < 0)
+			node = isl_schedule_node_free(node);
 		node = isl_schedule_node_parent(node);
 		node = isl_schedule_node_sequence_splice(node, pos, tree);
 	} else {
@@ -4266,21 +4399,21 @@ static __isl_give isl_schedule_node *extension_from_domain(
 	isl_union_set *universe;
 	isl_union_set *domain;
 	isl_union_map *ext;
-	int depth;
-	int anchored;
+	isl_size depth;
+	isl_bool anchored;
 	isl_space *space;
 	isl_schedule_node *res;
 	isl_schedule_tree *tree;
 
+	depth = isl_schedule_node_get_schedule_depth(pos);
 	anchored = isl_schedule_node_is_subtree_anchored(node);
-	if (anchored < 0)
+	if (depth < 0 || anchored < 0)
 		return isl_schedule_node_free(node);
 	if (anchored)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_unsupported,
 			"cannot graft anchored tree with domain root",
 			return isl_schedule_node_free(node));
 
-	depth = isl_schedule_node_get_schedule_depth(pos);
 	domain = isl_schedule_node_domain_get_domain(node);
 	space = isl_union_set_get_space(domain);
 	space = isl_space_set_from_params(space);
@@ -4414,8 +4547,8 @@ static __isl_give isl_schedule_node *isl_schedule_node_order_before_or_after(
 	isl_union_set *node_domain, *node_filter = NULL, *parent_filter;
 	isl_schedule_node *node2;
 	isl_schedule_tree *tree1, *tree2;
-	int empty1, empty2;
-	int in_seq;
+	isl_bool empty1, empty2;
+	isl_bool in_seq;
 
 	if (!node || !filter)
 		goto error;
@@ -4649,33 +4782,32 @@ __isl_give isl_schedule_node *isl_schedule_node_expand(
  * of "ancestor".  "node" is assumed to be a descendant of "ancestor".
  * In particular, both nodes should point to the same schedule tree.
  *
- * Return -1 on error.
+ * Return isl_size_error on error.
  */
-int isl_schedule_node_get_ancestor_child_position(
+isl_size isl_schedule_node_get_ancestor_child_position(
 	__isl_keep isl_schedule_node *node,
 	__isl_keep isl_schedule_node *ancestor)
 {
-	int n1, n2;
+	isl_size n1, n2;
 	isl_schedule_tree *tree;
 
-	if (!node || !ancestor)
-		return -1;
+	n1 = isl_schedule_node_get_tree_depth(ancestor);
+	n2 = isl_schedule_node_get_tree_depth(node);
+	if (n1 < 0 || n2 < 0)
+		return isl_size_error;
 
 	if (node->schedule != ancestor->schedule)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
-			"not a descendant", return -1);
-
-	n1 = isl_schedule_node_get_tree_depth(ancestor);
-	n2 = isl_schedule_node_get_tree_depth(node);
+			"not a descendant", return isl_size_error);
 
 	if (n1 >= n2)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
-			"not a descendant", return -1);
+			"not a descendant", return isl_size_error);
 	tree = isl_schedule_tree_list_get_schedule_tree(node->ancestors, n1);
 	isl_schedule_tree_free(tree);
 	if (tree != ancestor->tree)
 		isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
-			"not a descendant", return -1);
+			"not a descendant", return isl_size_error);
 
 	return node->child_pos[n1];
 }
@@ -4695,15 +4827,16 @@ __isl_give isl_schedule_node *isl_schedule_node_get_shared_ancestor(
 	__isl_keep isl_schedule_node *node1,
 	__isl_keep isl_schedule_node *node2)
 {
-	int i, n1, n2;
+	int i;
+	isl_size n1, n2;
 
-	if (!node1 || !node2)
+	n1 = isl_schedule_node_get_tree_depth(node1);
+	n2 = isl_schedule_node_get_tree_depth(node2);
+	if (n1 < 0 || n2 < 0)
 		return NULL;
 	if (node1->schedule != node2->schedule)
 		isl_die(isl_schedule_node_get_ctx(node1), isl_error_invalid,
 			"not part of same schedule", return NULL);
-	n1 = isl_schedule_node_get_tree_depth(node1);
-	n2 = isl_schedule_node_get_tree_depth(node2);
 	if (n2 < n1)
 		return isl_schedule_node_get_shared_ancestor(node2, node1);
 	if (n1 == 0)
@@ -4724,10 +4857,14 @@ __isl_give isl_schedule_node *isl_schedule_node_get_shared_ancestor(
 __isl_give isl_printer *isl_printer_print_schedule_node(
 	__isl_take isl_printer *p, __isl_keep isl_schedule_node *node)
 {
+	isl_size n;
+
 	if (!node)
 		return isl_printer_free(p);
-	return isl_printer_print_schedule_tree_mark(p, node->schedule->root,
-			isl_schedule_tree_list_n_schedule_tree(node->ancestors),
+	n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+	if (n < 0)
+		return isl_printer_free(p);
+	return isl_printer_print_schedule_tree_mark(p, node->schedule->root, n,
 			node->child_pos);
 }
 

diff  --git a/polly/lib/External/isl/isl_schedule_read.c b/polly/lib/External/isl/isl_schedule_read.c
index 9b81e391ef87..71fdeed50d76 100644
--- a/polly/lib/External/isl/isl_schedule_read.c
+++ b/polly/lib/External/isl/isl_schedule_read.c
@@ -478,10 +478,12 @@ static __isl_give isl_schedule_band *set_coincident(
 	__isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
 {
 	int i;
-	int n, m;
+	isl_size n, m;
 
 	n = isl_schedule_band_n_member(band);
 	m = isl_val_list_n_val(coincident);
+	if (n < 0 || m < 0)
+		band = isl_schedule_band_free(band);
 
 	for (i = 0; i < n && i < m; ++i) {
 		isl_val *v;

diff  --git a/polly/lib/External/isl/isl_schedule_tree.c b/polly/lib/External/isl/isl_schedule_tree.c
index 0b2076ba424f..2a20a336ff25 100644
--- a/polly/lib/External/isl/isl_schedule_tree.c
+++ b/polly/lib/External/isl/isl_schedule_tree.c
@@ -25,8 +25,8 @@
 
 #include <isl_list_templ.h>
 
-#undef BASE
-#define BASE schedule_tree
+#undef EL_BASE
+#define EL_BASE schedule_tree
 
 #include <isl_list_templ.c>
 
@@ -442,7 +442,7 @@ __isl_give isl_schedule_tree *isl_schedule_tree_from_mark(
 isl_bool isl_schedule_tree_is_subtree_anchored(
 	__isl_keep isl_schedule_tree *tree)
 {
-	return tree ? tree->anchored : isl_bool_error;
+	return tree ? isl_bool_ok(tree->anchored) : isl_bool_error;
 }
 
 /* Does the root node of "tree" depend on its position in the complete
@@ -487,17 +487,15 @@ int isl_schedule_tree_is_anchored(__isl_keep isl_schedule_tree *tree)
 __isl_give isl_schedule_tree *isl_schedule_tree_update_anchored(
 	__isl_take isl_schedule_tree *tree)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	int anchored;
 
-	if (!tree)
-		return NULL;
-
 	anchored = isl_schedule_tree_is_anchored(tree);
-	if (anchored < 0)
+	n = isl_schedule_tree_n_children(tree);
+	if (anchored < 0 || n < 0)
 		return isl_schedule_tree_free(tree);
 
-	n = isl_schedule_tree_list_n_schedule_tree(tree->children);
 	for (i = 0; !anchored && i < n; ++i) {
 		isl_schedule_tree *child;
 
@@ -631,7 +629,8 @@ isl_bool isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree *tree1,
 	__isl_keep isl_schedule_tree *tree2)
 {
 	isl_bool equal;
-	int i, n;
+	int i;
+	isl_size n1, n2;
 
 	if (!tree1 || !tree2)
 		return isl_bool_error;
@@ -669,7 +668,7 @@ isl_bool isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree *tree1,
 		equal = isl_set_is_equal(tree1->guard, tree2->guard);
 		break;
 	case isl_schedule_node_mark:
-		equal = tree1->mark == tree2->mark;
+		equal = isl_bool_ok(tree1->mark == tree2->mark);
 		break;
 	case isl_schedule_node_leaf:
 	case isl_schedule_node_sequence:
@@ -684,10 +683,13 @@ isl_bool isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree *tree1,
 	if (equal < 0 || !equal)
 		return equal;
 
-	n = isl_schedule_tree_n_children(tree1);
-	if (n != isl_schedule_tree_n_children(tree2))
+	n1 = isl_schedule_tree_n_children(tree1);
+	n2 = isl_schedule_tree_n_children(tree2);
+	if (n1 < 0 || n2 < 0)
+		return isl_bool_error;
+	if (n1 != n2)
 		return isl_bool_false;
-	for (i = 0; i < n; ++i) {
+	for (i = 0; i < n1; ++i) {
 		isl_schedule_tree *child1, *child2;
 
 		child1 = isl_schedule_tree_get_child(tree1, i);
@@ -714,12 +716,16 @@ int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree *tree)
 }
 
 /* Return the number of children of "tree", excluding implicit leaves.
+ * The "children" field is NULL if there are
+ * no children (except for the implicit leaves).
  */
-int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree)
+isl_size isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree)
 {
 	if (!tree)
-		return -1;
+		return isl_size_error;
 
+	if (!tree->children)
+		return 0;
 	return isl_schedule_tree_list_n_schedule_tree(tree->children);
 }
 
@@ -767,17 +773,17 @@ __isl_give isl_schedule_tree *isl_schedule_tree_reset_children(
 __isl_give isl_schedule_tree *isl_schedule_tree_drop_child(
 	__isl_take isl_schedule_tree *tree, int pos)
 {
-	int n;
+	isl_size n;
 
 	tree = isl_schedule_tree_cow(tree);
-	if (!tree)
-		return NULL;
 
-	if (!isl_schedule_tree_has_children(tree))
+	n = isl_schedule_tree_n_children(tree);
+	if (n < 0)
+		return isl_schedule_tree_free(tree);
+	if (n == 0)
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
 			"tree does not have any explicit children",
 			return isl_schedule_tree_free(tree));
-	n = isl_schedule_tree_list_n_schedule_tree(tree->children);
 	if (pos < 0 || pos >= n)
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
 			"position out of bounds",
@@ -809,10 +815,15 @@ __isl_give isl_schedule_tree *isl_schedule_tree_replace_child(
 		goto error;
 
 	if (isl_schedule_tree_is_leaf(child)) {
+		isl_size n;
+
 		isl_schedule_tree_free(child);
 		if (!tree->children && pos == 0)
 			return tree;
-		if (isl_schedule_tree_n_children(tree) != 1)
+		n = isl_schedule_tree_n_children(tree);
+		if (n < 0)
+			return isl_schedule_tree_free(tree);
+		if (n != 1)
 			isl_die(isl_schedule_tree_get_ctx(tree),
 				isl_error_internal,
 				"can only replace single child by leaf",
@@ -947,12 +958,13 @@ __isl_give isl_schedule_tree *isl_schedule_tree_insert_filter(
 __isl_give isl_schedule_tree *isl_schedule_tree_children_insert_filter(
 	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!tree || !filter)
+	n = isl_schedule_tree_n_children(tree);
+	if (n < 0 || !filter)
 		goto error;
 
-	n = isl_schedule_tree_n_children(tree);
 	for (i = 0; i < n; ++i) {
 		isl_schedule_tree *child;
 
@@ -996,14 +1008,14 @@ __isl_give isl_schedule_tree *isl_schedule_tree_insert_mark(
 
 /* Return the number of members in the band tree root.
  */
-unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree)
+isl_size isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree)
 {
 	if (!tree)
-		return 0;
+		return isl_size_error;
 
 	if (tree->type != isl_schedule_node_band)
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
-			"not a band node", return 0);
+			"not a band node", return isl_size_error);
 
 	return isl_schedule_band_n_member(tree->band);
 }
@@ -1528,7 +1540,7 @@ __isl_give isl_id *isl_schedule_tree_mark_get_id(
  */
 static isl_stat set_range_dim(__isl_take isl_map *map, void *user)
 {
-	int *dim = user;
+	isl_size *dim = user;
 
 	*dim = isl_map_dim(map, isl_dim_out);
 	isl_map_free(map);
@@ -1542,15 +1554,17 @@ static isl_stat set_range_dim(__isl_take isl_map *map, void *user)
  *
  * We extract the range dimension from the first map in "umap".
  */
-static int range_dim(__isl_keep isl_union_map *umap)
+static isl_size range_dim(__isl_keep isl_union_map *umap)
 {
-	int dim = -1;
+	isl_size dim = isl_size_error;
+	isl_size n;
 
-	if (!umap)
-		return -1;
-	if (isl_union_map_n_map(umap) == 0)
+	n = isl_union_map_n_map(umap);
+	if (n < 0)
+		return isl_size_error;
+	if (n == 0)
 		isl_die(isl_union_map_get_ctx(umap), isl_error_internal,
-			"unexpected empty input", return -1);
+			"unexpected empty input", return isl_size_error);
 
 	isl_union_map_foreach_map(umap, &set_range_dim, &dim);
 
@@ -1595,18 +1609,20 @@ static __isl_give isl_union_map *append_range(__isl_take isl_union_map *umap,
  * from an extension node, but extension nodes are not supported
  * by the caller and it will error out on them.
  */
-static int domain_less(__isl_keep isl_schedule_tree *tree)
+static isl_bool domain_less(__isl_keep isl_schedule_tree *tree)
 {
 	enum isl_schedule_node_type type;
+	isl_size n;
 
 	type = isl_schedule_tree_get_type(tree);
 	switch (type) {
 	case isl_schedule_node_band:
-		return isl_schedule_tree_band_n_member(tree) == 0;
+		n = isl_schedule_tree_band_n_member(tree);
+		return n < 0 ? isl_bool_error : isl_bool_ok(n == 0);
 	case isl_schedule_node_context:
 	case isl_schedule_node_guard:
 	case isl_schedule_node_mark:
-		return 1;
+		return isl_bool_true;
 	case isl_schedule_node_leaf:
 	case isl_schedule_node_error:
 	case isl_schedule_node_domain:
@@ -1615,11 +1631,11 @@ static int domain_less(__isl_keep isl_schedule_tree *tree)
 	case isl_schedule_node_filter:
 	case isl_schedule_node_set:
 	case isl_schedule_node_sequence:
-		return 0;
+		return isl_bool_false;
 	}
 
 	isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
-		"unhandled case", return 0);
+		"unhandled case", return isl_bool_error);
 }
 
 /* Move down to the first descendant of "tree" that contains any schedule
@@ -1628,7 +1644,9 @@ static int domain_less(__isl_keep isl_schedule_tree *tree)
 __isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
 	__isl_take isl_schedule_tree *tree, __isl_keep isl_schedule_tree *leaf)
 {
-	while (domain_less(tree)) {
+	isl_bool down;
+
+	while ((down = domain_less(tree)) == isl_bool_true) {
 		if (!isl_schedule_tree_has_children(tree)) {
 			isl_schedule_tree_free(tree);
 			return isl_schedule_tree_copy(leaf);
@@ -1636,6 +1654,9 @@ __isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
 		tree = isl_schedule_tree_child(tree, 0);
 	}
 
+	if (down < 0)
+		return isl_schedule_tree_free(tree);
+
 	return tree;
 }
 
@@ -1710,8 +1731,9 @@ static __isl_give isl_space *extract_space_from_filter_child(
 static __isl_give isl_union_map *subtree_schedule_extend_from_children(
 	__isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
 {
-	int i, n;
-	int dim;
+	int i;
+	isl_size n;
+	isl_size dim;
 	int separate;
 	isl_ctx *ctx;
 	isl_val *v = NULL;
@@ -1719,18 +1741,14 @@ static __isl_give isl_union_map *subtree_schedule_extend_from_children(
 	isl_space *space;
 	isl_union_map *umap;
 
-	if (!tree)
-		return NULL;
-
-	ctx = isl_schedule_tree_get_ctx(tree);
-	if (!tree->children)
-		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
-			"missing children", return NULL);
-	n = isl_schedule_tree_list_n_schedule_tree(tree->children);
+	n = isl_schedule_tree_n_children(tree);
+	if (n < 0)
+		return isl_union_map_free(outer);
 	if (n == 0)
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
-			"missing children", return NULL);
+			"missing children", return isl_union_map_free(outer));
 
+	ctx = isl_schedule_tree_get_ctx(tree);
 	separate = n > 1 && (tree->type == isl_schedule_node_sequence ||
 			    isl_options_get_schedule_separate_components(ctx));
 
@@ -1745,14 +1763,16 @@ static __isl_give isl_union_map *subtree_schedule_extend_from_children(
 	mv = isl_multi_val_zero(space);
 
 	dim = isl_multi_val_dim(mv, isl_dim_set);
+	if (dim < 0)
+		umap = isl_union_map_free(umap);
 	for (i = 0; i < n; ++i) {
 		isl_multi_val *mv_copy;
 		isl_union_pw_multi_aff *upma;
 		isl_union_map *umap_i;
 		isl_union_set *dom;
 		isl_schedule_tree *child;
-		int dim_i;
-		int empty;
+		isl_size dim_i;
+		isl_bool empty;
 
 		child = isl_schedule_tree_list_get_schedule_tree(
 							tree->children, i);
@@ -1815,6 +1835,7 @@ static __isl_give isl_union_map *subtree_schedule_extend(
 	isl_multi_union_pw_aff *mupa;
 	isl_union_map *umap;
 	isl_union_set *domain;
+	isl_size n;
 
 	if (!tree)
 		return NULL;
@@ -1832,7 +1853,10 @@ static __isl_give isl_union_map *subtree_schedule_extend(
 	case isl_schedule_node_mark:
 		return subtree_schedule_extend_child(tree, outer);
 	case isl_schedule_node_band:
-		if (isl_schedule_tree_band_n_member(tree) == 0)
+		n = isl_schedule_tree_band_n_member(tree);
+		if (n < 0)
+			return isl_union_map_free(outer);
+		if (n == 0)
 			return subtree_schedule_extend_child(tree, outer);
 		mupa = isl_schedule_band_get_partial_schedule(tree->band);
 		umap = isl_union_map_from_multi_union_pw_aff(mupa);
@@ -1878,14 +1902,14 @@ static __isl_give isl_union_set *initial_domain(
 static __isl_give isl_union_set *initial_domain_from_children(
 	__isl_keep isl_schedule_tree *tree)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_space *space;
 	isl_union_set *domain;
 
-	if (!tree->children)
-		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
-			"missing children", return NULL);
-	n = isl_schedule_tree_list_n_schedule_tree(tree->children);
+	n = isl_schedule_tree_n_children(tree);
+	if (n < 0)
+		return NULL;
 	if (n == 0)
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
 			"missing children", return NULL);
@@ -1917,6 +1941,7 @@ static __isl_give isl_union_set *initial_domain(
 	isl_multi_union_pw_aff *mupa;
 	isl_union_set *domain;
 	isl_union_map *exp;
+	isl_size n;
 
 	if (!tree)
 		return NULL;
@@ -1941,7 +1966,10 @@ static __isl_give isl_union_set *initial_domain(
 			"cannot construct subtree schedule of tree "
 			"with extension nodes", return NULL);
 	case isl_schedule_node_band:
-		if (isl_schedule_tree_band_n_member(tree) == 0)
+		n = isl_schedule_tree_band_n_member(tree);
+		if (n < 0)
+			return NULL;
+		if (n == 0)
 			isl_die(isl_schedule_tree_get_ctx(tree),
 				isl_error_internal,
 				"0D band should be handled by caller",
@@ -2113,7 +2141,7 @@ __isl_give isl_schedule_tree *isl_schedule_tree_sequence_splice(
 	__isl_take isl_schedule_tree *tree, int pos,
 	__isl_take isl_schedule_tree *child)
 {
-	int n;
+	isl_size n;
 	isl_schedule_tree_list *list1, *list2;
 
 	tree = isl_schedule_tree_cow(tree);
@@ -2123,6 +2151,8 @@ __isl_give isl_schedule_tree *isl_schedule_tree_sequence_splice(
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
 			"not a sequence node", goto error);
 	n = isl_schedule_tree_n_children(tree);
+	if (n < 0)
+		goto error;
 	if (pos < 0 || pos >= n)
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
 			"position out of bounds", goto error);
@@ -2276,7 +2306,7 @@ static __isl_give isl_set *isolate_final(__isl_keep isl_set *isolate,
 __isl_give isl_schedule_tree *isl_schedule_tree_band_split(
 	__isl_take isl_schedule_tree *tree, int pos, int depth)
 {
-	int n;
+	isl_size n;
 	isl_set *isolate, *tree_isolate, *child_isolate;
 	isl_schedule_tree *child;
 
@@ -2287,6 +2317,8 @@ __isl_give isl_schedule_tree *isl_schedule_tree_band_split(
 			"not a band node", return isl_schedule_tree_free(tree));
 
 	n = isl_schedule_tree_band_n_member(tree);
+	if (n < 0)
+		return isl_schedule_tree_free(tree);
 	if (pos < 0 || pos > n)
 		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
 			"position out of bounds",
@@ -2330,11 +2362,12 @@ __isl_give isl_schedule_tree *isl_schedule_tree_append_to_leaves(
 	__isl_take isl_schedule_tree *tree1,
 	__isl_take isl_schedule_tree *tree2)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!tree1 || !tree2)
-		goto error;
 	n = isl_schedule_tree_n_children(tree1);
+	if (n < 0 || !tree2)
+		goto error;
 	if (n == 0) {
 		isl_schedule_tree_list *list;
 		list = isl_schedule_tree_list_from_schedule_tree(tree2);
@@ -2618,16 +2651,23 @@ __isl_give isl_schedule_tree *isl_schedule_tree_band_gist(
 
 /* Are any members in "band" marked coincident?
  */
-static int any_coincident(__isl_keep isl_schedule_band *band)
+static isl_bool any_coincident(__isl_keep isl_schedule_band *band)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_schedule_band_n_member(band);
-	for (i = 0; i < n; ++i)
-		if (isl_schedule_band_member_get_coincident(band, i))
-			return 1;
+	if (n < 0)
+		return isl_bool_error;
+	for (i = 0; i < n; ++i) {
+		isl_bool coincident;
+
+		coincident = isl_schedule_band_member_get_coincident(band, i);
+		if (coincident < 0 || coincident)
+			return coincident;
+	}
 
-	return 0;
+	return isl_bool_false;
 }
 
 /* Print the band node "band" to "p".
@@ -2640,7 +2680,8 @@ static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
 	__isl_keep isl_schedule_band *band)
 {
 	isl_union_set *options;
-	int empty;
+	isl_bool empty;
+	isl_bool coincident;
 
 	p = isl_printer_print_str(p, "schedule");
 	p = isl_printer_yaml_next(p);
@@ -2653,8 +2694,12 @@ static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
 		p = isl_printer_yaml_next(p);
 		p = isl_printer_print_int(p, 1);
 	}
-	if (any_coincident(band)) {
-		int i, n;
+	coincident = any_coincident(band);
+	if (coincident < 0)
+		return isl_printer_free(p);
+	if (coincident) {
+		int i;
+		isl_size n;
 		int style;
 
 		p = isl_printer_yaml_next(p);
@@ -2664,6 +2709,8 @@ static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
 		p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
 		p = isl_printer_yaml_start_sequence(p);
 		n = isl_schedule_band_n_member(band);
+		if (n < 0)
+			return isl_printer_free(p);
 		for (i = 0; i < n; ++i) {
 			p = isl_printer_print_int(p,
 			    isl_schedule_band_member_get_coincident(band, i));
@@ -2689,6 +2736,27 @@ static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
 	return p;
 }
 
+#undef BASE
+#define BASE str
+#define isl_str const char
+#include "print_yaml_field_templ.c"
+
+#undef BASE
+#define BASE set
+#include "print_yaml_field_templ.c"
+
+#undef BASE
+#define BASE union_set
+#include "print_yaml_field_templ.c"
+
+#undef BASE
+#define BASE union_map
+#include "print_yaml_field_templ.c"
+
+#undef BASE
+#define BASE union_pw_multi_aff
+#include "print_yaml_field_templ.c"
+
 /* Print "tree" to "p".
  *
  * If "n_ancestor" is non-negative, then "child_pos" contains the child
@@ -2704,7 +2772,8 @@ __isl_give isl_printer *isl_printer_print_schedule_tree_mark(
 	__isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree,
 	int n_ancestor, int *child_pos)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	int sequence = 0;
 	int block;
 
@@ -2719,80 +2788,56 @@ __isl_give isl_printer *isl_printer_print_schedule_tree_mark(
 	switch (tree->type) {
 	case isl_schedule_node_error:
 		p = isl_printer_print_str(p, "ERROR");
+		p = isl_printer_yaml_next(p);
 		break;
 	case isl_schedule_node_leaf:
 		p = isl_printer_print_str(p, "leaf");
+		p = isl_printer_yaml_next(p);
 		break;
 	case isl_schedule_node_sequence:
 		p = isl_printer_print_str(p, "sequence");
+		p = isl_printer_yaml_next(p);
 		sequence = 1;
 		break;
 	case isl_schedule_node_set:
 		p = isl_printer_print_str(p, "set");
+		p = isl_printer_yaml_next(p);
 		sequence = 1;
 		break;
 	case isl_schedule_node_context:
-		p = isl_printer_print_str(p, "context");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_set(p, tree->context);
-		p = isl_printer_print_str(p, "\"");
+		p = print_yaml_field_set(p, "context", tree->context);
 		break;
 	case isl_schedule_node_domain:
-		p = isl_printer_print_str(p, "domain");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_union_set(p, tree->domain);
-		p = isl_printer_print_str(p, "\"");
+		p = print_yaml_field_union_set(p, "domain", tree->domain);
 		break;
 	case isl_schedule_node_expansion:
-		p = isl_printer_print_str(p, "contraction");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_union_pw_multi_aff(p, tree->contraction);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "expansion");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_union_map(p, tree->expansion);
-		p = isl_printer_print_str(p, "\"");
+		p = print_yaml_field_union_pw_multi_aff(p, "contraction",
+							tree->contraction);
+		p = print_yaml_field_union_map(p, "expansion", tree->expansion);
 		break;
 	case isl_schedule_node_extension:
-		p = isl_printer_print_str(p, "extension");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_union_map(p, tree->extension);
-		p = isl_printer_print_str(p, "\"");
+		p = print_yaml_field_union_map(p, "extension", tree->extension);
 		break;
 	case isl_schedule_node_filter:
-		p = isl_printer_print_str(p, "filter");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_union_set(p, tree->filter);
-		p = isl_printer_print_str(p, "\"");
+		p = print_yaml_field_union_set(p, "filter", tree->filter);
 		break;
 	case isl_schedule_node_guard:
-		p = isl_printer_print_str(p, "guard");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_set(p, tree->guard);
-		p = isl_printer_print_str(p, "\"");
+		p = print_yaml_field_set(p, "guard", tree->guard);
 		break;
 	case isl_schedule_node_mark:
-		p = isl_printer_print_str(p, "mark");
-		p = isl_printer_yaml_next(p);
-		p = isl_printer_print_str(p, "\"");
-		p = isl_printer_print_str(p, isl_id_get_name(tree->mark));
-		p = isl_printer_print_str(p, "\"");
+		p = print_yaml_field_str(p, "mark",
+					isl_id_get_name(tree->mark));
 		break;
 	case isl_schedule_node_band:
 		p = print_tree_band(p, tree->band);
+		p = isl_printer_yaml_next(p);
 		break;
 	}
-	p = isl_printer_yaml_next(p);
 
-	if (!tree->children) {
+	n = isl_schedule_tree_n_children(tree);
+	if (n < 0)
+		return isl_printer_free(p);
+	if (n == 0) {
 		if (n_ancestor > 0 && block) {
 			isl_schedule_tree *leaf;
 
@@ -2814,7 +2859,6 @@ __isl_give isl_printer *isl_printer_print_schedule_tree_mark(
 		p = isl_printer_yaml_next(p);
 	}
 
-	n = isl_schedule_tree_list_n_schedule_tree(tree->children);
 	for (i = 0; i < n; ++i) {
 		isl_schedule_tree *t;
 

diff  --git a/polly/lib/External/isl/isl_schedule_tree.h b/polly/lib/External/isl/isl_schedule_tree.h
index 8bc4cf2018e1..a1ecfadda52a 100644
--- a/polly/lib/External/isl/isl_schedule_tree.h
+++ b/polly/lib/External/isl/isl_schedule_tree.h
@@ -178,7 +178,7 @@ __isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
 __isl_give isl_union_map *isl_schedule_tree_get_subtree_schedule_union_map(
 	__isl_keep isl_schedule_tree *tree);
 
-unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree);
+isl_size isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree);
 
 isl_bool isl_schedule_tree_band_member_get_coincident(
 	__isl_keep isl_schedule_tree *tree, int pos);
@@ -190,7 +190,7 @@ __isl_give isl_schedule_tree *isl_schedule_tree_band_set_permutable(
 	__isl_take isl_schedule_tree *tree, int permutable);
 
 int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree *tree);
-int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree);
+isl_size isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree);
 __isl_give isl_schedule_tree *isl_schedule_tree_get_child(
 	__isl_keep isl_schedule_tree *tree, int pos);
 

diff  --git a/polly/lib/External/isl/isl_scheduler.c b/polly/lib/External/isl/isl_scheduler.c
index 4e08d2012c3d..1e2058891778 100644
--- a/polly/lib/External/isl/isl_scheduler.c
+++ b/polly/lib/External/isl/isl_scheduler.c
@@ -106,7 +106,7 @@ struct isl_sched_node {
 	int	compressed;
 	isl_set	*hull;
 	isl_multi_aff *compress;
-	isl_multi_aff *decompress;
+	isl_pw_multi_aff *decompress;
 	isl_mat *sched;
 	isl_map *sched_map;
 	int	 rank;
@@ -126,7 +126,7 @@ struct isl_sched_node {
 	isl_vec *max;
 };
 
-static int node_has_tuples(const void *entry, const void *val)
+static isl_bool node_has_tuples(const void *entry, const void *val)
 {
 	struct isl_sched_node *node = (struct isl_sched_node *)entry;
 	isl_space *space = (isl_space *) val;
@@ -436,8 +436,12 @@ static struct isl_sched_node *graph_find_node(isl_ctx *ctx,
 	hash = isl_space_get_tuple_hash(space);
 	entry = isl_hash_table_find(ctx, graph->node_table, hash,
 				    &node_has_tuples, space, 0);
+	if (!entry)
+		return NULL;
+	if (entry == isl_hash_table_entry_none)
+		return graph->node + graph->n;
 
-	return entry ? entry->data : graph->node + graph->n;
+	return entry->data;
 }
 
 /* Is "node" a node in "graph"?
@@ -448,12 +452,12 @@ static int is_node(struct isl_sched_graph *graph,
 	return node && node >= &graph->node[0] && node < &graph->node[graph->n];
 }
 
-static int edge_has_src_and_dst(const void *entry, const void *val)
+static isl_bool edge_has_src_and_dst(const void *entry, const void *val)
 {
 	const struct isl_sched_edge *edge = entry;
 	const struct isl_sched_edge *temp = val;
 
-	return edge->src == temp->src && edge->dst == temp->dst;
+	return isl_bool_ok(edge->src == temp->src && edge->dst == temp->dst);
 }
 
 /* Add the given edge to graph->edge_table[type].
@@ -535,17 +539,21 @@ static struct isl_hash_table_entry *graph_find_edge_entry(
 
 /* If graph->edge_table[type] contains an edge from the given source
  * to the given destination, then return this edge.
- * Otherwise, return NULL.
+ * Return "none" if no such edge can be found.
+ * Return NULL on error.
  */
 static struct isl_sched_edge *graph_find_edge(struct isl_sched_graph *graph,
 	enum isl_edge_type type,
-	struct isl_sched_node *src, struct isl_sched_node *dst)
+	struct isl_sched_node *src, struct isl_sched_node *dst,
+	struct isl_sched_edge *none)
 {
 	struct isl_hash_table_entry *entry;
 
 	entry = graph_find_edge_entry(graph, type, src, dst);
 	if (!entry)
 		return NULL;
+	if (entry == isl_hash_table_entry_none)
+		return none;
 
 	return entry->data;
 }
@@ -557,18 +565,19 @@ static isl_bool graph_has_edge(struct isl_sched_graph *graph,
 	enum isl_edge_type type,
 	struct isl_sched_node *src, struct isl_sched_node *dst)
 {
+	struct isl_sched_edge dummy;
 	struct isl_sched_edge *edge;
 	isl_bool empty;
 
-	edge = graph_find_edge(graph, type, src, dst);
+	edge = graph_find_edge(graph, type, src, dst, &dummy);
 	if (!edge)
+		return isl_bool_error;
+	if (edge == &dummy)
 		return isl_bool_false;
 
 	empty = isl_map_plain_is_empty(edge->map);
-	if (empty < 0)
-		return isl_bool_error;
 
-	return !empty;
+	return isl_bool_not(empty);
 }
 
 /* Look for any edge with the same src, dst and map fields as "model".
@@ -586,8 +595,10 @@ static struct isl_sched_edge *graph_find_matching_edge(
 	for (i = isl_edge_first; i <= isl_edge_last; ++i) {
 		int is_equal;
 
-		edge = graph_find_edge(graph, i, model->src, model->dst);
+		edge = graph_find_edge(graph, i, model->src, model->dst, model);
 		if (!edge)
+			return NULL;
+		if (edge == model)
 			continue;
 		is_equal = isl_map_plain_is_equal(model->map, edge->map);
 		if (is_equal < 0)
@@ -601,7 +612,7 @@ static struct isl_sched_edge *graph_find_matching_edge(
 
 /* Remove the given edge from all the edge_tables that refer to it.
  */
-static void graph_remove_edge(struct isl_sched_graph *graph,
+static isl_stat graph_remove_edge(struct isl_sched_graph *graph,
 	struct isl_sched_edge *edge)
 {
 	isl_ctx *ctx = isl_map_get_ctx(edge->map);
@@ -612,11 +623,15 @@ static void graph_remove_edge(struct isl_sched_graph *graph,
 
 		entry = graph_find_edge_entry(graph, i, edge->src, edge->dst);
 		if (!entry)
+			return isl_stat_error;
+		if (entry == isl_hash_table_entry_none)
 			continue;
 		if (entry->data != edge)
 			continue;
 		isl_hash_table_remove(ctx, graph->edge_table[i], entry);
 	}
+
+	return isl_stat_ok;
 }
 
 /* Check whether the dependence graph has any edge
@@ -703,7 +718,7 @@ static void clear_node(struct isl_sched_graph *graph,
 	isl_space_free(node->space);
 	isl_set_free(node->hull);
 	isl_multi_aff_free(node->compress);
-	isl_multi_aff_free(node->decompress);
+	isl_pw_multi_aff_free(node->decompress);
 	isl_mat_free(node->sched);
 	isl_map_free(node->sched_map);
 	isl_mat_free(node->indep);
@@ -748,7 +763,7 @@ static void graph_free(isl_ctx *ctx, struct isl_sched_graph *graph)
 static isl_stat init_n_maxvar(__isl_take isl_set *set, void *user)
 {
 	struct isl_sched_graph *graph = user;
-	int nvar = isl_set_dim(set, isl_dim_set);
+	isl_size nvar = isl_set_dim(set, isl_dim_set);
 
 	graph->n++;
 	if (nvar > graph->maxvar)
@@ -756,6 +771,8 @@ static isl_stat init_n_maxvar(__isl_take isl_set *set, void *user)
 
 	isl_set_free(set);
 
+	if (nvar < 0)
+		return isl_stat_error;
 	return isl_stat_ok;
 }
 
@@ -791,12 +808,13 @@ static isl_stat compute_max_row(struct isl_sched_graph *graph,
  */
 static isl_bool has_any_defining_equality(__isl_keep isl_basic_set *bset)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
-	if (!bset)
+	n = isl_basic_set_dim(bset, isl_dim_set);
+	if (n < 0)
 		return isl_bool_error;
 
-	n = isl_basic_set_dim(bset, isl_dim_set);
 	for (i = 0; i < n; ++i) {
 		isl_bool has;
 
@@ -890,6 +908,57 @@ static isl_stat compute_max_coefficient(isl_ctx *ctx,
 	return isl_stat_error;
 }
 
+/* Construct an identifier for node "node", which will represent "set".
+ * The name of the identifier is either "compressed" or
+ * "compressed_<name>", with <name> the name of the space of "set".
+ * The user pointer of the identifier points to "node".
+ */
+static __isl_give isl_id *construct_compressed_id(__isl_keep isl_set *set,
+	struct isl_sched_node *node)
+{
+	isl_bool has_name;
+	isl_ctx *ctx;
+	isl_id *id;
+	isl_printer *p;
+	const char *name;
+	char *id_name;
+
+	has_name = isl_set_has_tuple_name(set);
+	if (has_name < 0)
+		return NULL;
+
+	ctx = isl_set_get_ctx(set);
+	if (!has_name)
+		return isl_id_alloc(ctx, "compressed", node);
+
+	p = isl_printer_to_str(ctx);
+	name = isl_set_get_tuple_name(set);
+	p = isl_printer_print_str(p, "compressed_");
+	p = isl_printer_print_str(p, name);
+	id_name = isl_printer_get_str(p);
+	isl_printer_free(p);
+
+	id = isl_id_alloc(ctx, id_name, node);
+	free(id_name);
+
+	return id;
+}
+
+/* Construct a map that isolates the variable in position "pos" in "set".
+ *
+ * That is, construct
+ *
+ *	[i_0, ..., i_pos-1, i_pos+1, ...] -> [i_pos]
+ */
+static __isl_give isl_map *isolate(__isl_take isl_set *set, int pos)
+{
+	isl_map *map;
+
+	map = isl_set_project_onto_map(set, isl_dim_set, pos, 1);
+	map = isl_map_project_out(map, isl_dim_in, pos, 1);
+	return map;
+}
+
 /* Compute and return the size of "set" in dimension "dim".
  * The size is taken to be the 
diff erence in values for that variable
  * for fixed values of the other variables.
@@ -913,8 +982,7 @@ static __isl_give isl_val *compute_size(__isl_take isl_set *set, int dim)
 	isl_aff *obj;
 	isl_val *v;
 
-	map = isl_set_project_onto_map(set, isl_dim_set, dim, 1);
-	map = isl_map_project_out(map, isl_dim_in, dim, 1);
+	map = isolate(set, dim);
 	map = isl_map_range_product(map, isl_map_copy(map));
 	map = isl_set_unwrap(isl_map_range(map));
 	set = isl_map_deltas(map);
@@ -927,51 +995,184 @@ static __isl_give isl_val *compute_size(__isl_take isl_set *set, int dim)
 	return v;
 }
 
-/* Compute the size of the instance set "set" of "node", after compression,
- * as well as bounds on the corresponding coefficients, if needed.
+/* Perform a compression on "node" where "hull" represents the constraints
+ * that were used to derive the compression, while "compress" and
+ * "decompress" map the original space to the compressed space and
+ * vice versa.
  *
- * The sizes are needed when the schedule_treat_coalescing option is set.
- * The bounds are needed when the schedule_treat_coalescing option or
- * the schedule_max_coefficient option is set.
+ * If "node" was not compressed already, then simply store
+ * the compression information.
+ * Otherwise the "original" space is actually the result
+ * of a previous compression, which is then combined
+ * with the present compression.
  *
- * If the schedule_treat_coalescing option is not set, then at most
- * the bounds need to be set and this is done in set_max_coefficient.
- * Otherwise, compress the domain if needed, compute the size
- * in each direction and store the results in node->size.
+ * The dimensionality of the compressed domain is also adjusted.
+ * Other information, such as the sizes and the maximal coefficient values,
+ * has not been computed yet and therefore does not need to be adjusted.
+ */
+static isl_stat compress_node(struct isl_sched_node *node,
+	__isl_take isl_set *hull, __isl_take isl_multi_aff *compress,
+	__isl_take isl_pw_multi_aff *decompress)
+{
+	node->nvar = isl_multi_aff_dim(compress, isl_dim_out);
+	if (!node->compressed) {
+		node->compressed = 1;
+		node->hull = hull;
+		node->compress = compress;
+		node->decompress = decompress;
+	} else {
+		hull = isl_set_preimage_multi_aff(hull,
+					    isl_multi_aff_copy(node->compress));
+		node->hull = isl_set_intersect(node->hull, hull);
+		node->compress = isl_multi_aff_pullback_multi_aff(
+						compress, node->compress);
+		node->decompress = isl_pw_multi_aff_pullback_pw_multi_aff(
+						node->decompress, decompress);
+	}
+
+	if (!node->hull || !node->compress || !node->decompress)
+		return isl_stat_error;
+
+	return isl_stat_ok;
+}
+
+/* Given that dimension "pos" in "set" has a fixed value
+ * in terms of the other dimensions, (further) compress "node"
+ * by projecting out this dimension.
+ * "set" may be the result of a previous compression.
+ * "uncompressed" is the original domain (without compression).
+ *
+ * The compression function simply projects out the dimension.
+ * The decompression function adds back the dimension
+ * in the right position as an expression of the other dimensions
+ * derived from "set".
+ * As in extract_node, the compressed space has an identifier
+ * that references "node" such that each compressed space is unique and
+ * such that the node can be recovered from the compressed space.
+ *
+ * The constraint removed through the compression is added to the "hull"
+ * such that only edges that relate to the original domains
+ * are taken into account.
+ * In particular, it is obtained by composing compression and decompression and
+ * taking the relation among the variables in the range.
+ */
+static isl_stat project_out_fixed(struct isl_sched_node *node,
+	__isl_keep isl_set *uncompressed, __isl_take isl_set *set, int pos)
+{
+	isl_id *id;
+	isl_space *space;
+	isl_set *domain;
+	isl_map *map;
+	isl_multi_aff *compress;
+	isl_pw_multi_aff *decompress, *pma;
+	isl_multi_pw_aff *mpa;
+	isl_set *hull;
+
+	map = isolate(isl_set_copy(set), pos);
+	pma = isl_pw_multi_aff_from_map(map);
+	domain = isl_pw_multi_aff_domain(isl_pw_multi_aff_copy(pma));
+	pma = isl_pw_multi_aff_gist(pma, domain);
+	space = isl_pw_multi_aff_get_domain_space(pma);
+	mpa = isl_multi_pw_aff_identity(isl_space_map_from_set(space));
+	mpa = isl_multi_pw_aff_range_splice(mpa, pos,
+				    isl_multi_pw_aff_from_pw_multi_aff(pma));
+	decompress = isl_pw_multi_aff_from_multi_pw_aff(mpa);
+	space = isl_set_get_space(set);
+	compress = isl_multi_aff_project_out_map(space, isl_dim_set, pos, 1);
+	id = construct_compressed_id(uncompressed, node);
+	compress = isl_multi_aff_set_tuple_id(compress, isl_dim_out, id);
+	space = isl_space_reverse(isl_multi_aff_get_space(compress));
+	decompress = isl_pw_multi_aff_reset_space(decompress, space);
+	pma = isl_pw_multi_aff_pullback_multi_aff(
+	    isl_pw_multi_aff_copy(decompress), isl_multi_aff_copy(compress));
+	hull = isl_map_range(isl_map_from_pw_multi_aff(pma));
+
+	isl_set_free(set);
+
+	return compress_node(node, hull, compress, decompress);
+}
+
+/* Compute the size of the compressed domain in each dimension and
+ * store the results in node->sizes.
+ * "uncompressed" is the original domain (without compression).
+ *
+ * First compress the domain if needed and then compute the size
+ * in each direction.
  * If the domain is not convex, then the sizes are computed
  * on a convex superset in order to avoid picking up sizes
  * that are valid for the individual disjuncts, but not for
  * the domain as a whole.
- * Finally, set the bounds on the coefficients based on the sizes
- * and the schedule_max_coefficient option in compute_max_coefficient.
+ *
+ * If any of the sizes turns out to be zero, then this means
+ * that this dimension has a fixed value in terms of
+ * the other dimensions.  Perform an (extra) compression
+ * to remove this dimensions.
  */
-static isl_stat compute_sizes_and_max(isl_ctx *ctx, struct isl_sched_node *node,
-	__isl_take isl_set *set)
+static isl_stat compute_sizes(struct isl_sched_node *node,
+	__isl_keep isl_set *uncompressed)
 {
-	int j, n;
+	int j;
+	isl_size n;
 	isl_multi_val *mv;
-
-	if (!isl_options_get_schedule_treat_coalescing(ctx)) {
-		isl_set_free(set);
-		return set_max_coefficient(ctx, node);
-	}
+	isl_set *set = isl_set_copy(uncompressed);
 
 	if (node->compressed)
-		set = isl_set_preimage_multi_aff(set,
-					isl_multi_aff_copy(node->decompress));
+		set = isl_set_preimage_pw_multi_aff(set,
+				    isl_pw_multi_aff_copy(node->decompress));
 	set = isl_set_from_basic_set(isl_set_simple_hull(set));
 	mv = isl_multi_val_zero(isl_set_get_space(set));
 	n = isl_set_dim(set, isl_dim_set);
+	if (n < 0)
+		mv = isl_multi_val_free(mv);
 	for (j = 0; j < n; ++j) {
+		isl_bool is_zero;
 		isl_val *v;
 
 		v = compute_size(isl_set_copy(set), j);
+		is_zero = isl_val_is_zero(v);
 		mv = isl_multi_val_set_val(mv, j, v);
+		if (is_zero >= 0 && is_zero) {
+			isl_multi_val_free(mv);
+			if (project_out_fixed(node, uncompressed, set, j) < 0)
+				return isl_stat_error;
+			return compute_sizes(node, uncompressed);
+		}
 	}
 	node->sizes = mv;
 	isl_set_free(set);
 	if (!node->sizes)
 		return isl_stat_error;
+	return isl_stat_ok;
+}
+
+/* Compute the size of the instance set "set" of "node", after compression,
+ * as well as bounds on the corresponding coefficients, if needed.
+ *
+ * The sizes are needed when the schedule_treat_coalescing option is set.
+ * The bounds are needed when the schedule_treat_coalescing option or
+ * the schedule_max_coefficient option is set.
+ *
+ * If the schedule_treat_coalescing option is not set, then at most
+ * the bounds need to be set and this is done in set_max_coefficient.
+ * Otherwise, compute the size of the compressed domain
+ * in each direction and store the results in node->size.
+ * Finally, set the bounds on the coefficients based on the sizes
+ * and the schedule_max_coefficient option in compute_max_coefficient.
+ */
+static isl_stat compute_sizes_and_max(isl_ctx *ctx, struct isl_sched_node *node,
+	__isl_take isl_set *set)
+{
+	isl_stat r;
+
+	if (!isl_options_get_schedule_treat_coalescing(ctx)) {
+		isl_set_free(set);
+		return set_max_coefficient(ctx, node);
+	}
+
+	r = compute_sizes(node, set);
+	isl_set_free(set);
+	if (r < 0)
+		return isl_stat_error;
 	return compute_max_coefficient(ctx, node);
 }
 
@@ -992,20 +1193,20 @@ static isl_stat compute_sizes_and_max(isl_ctx *ctx, struct isl_sched_node *node,
 static isl_stat add_node(struct isl_sched_graph *graph,
 	__isl_take isl_set *set, int nvar, int compressed,
 	__isl_take isl_set *hull, __isl_take isl_multi_aff *compress,
-	__isl_take isl_multi_aff *decompress)
+	__isl_take isl_pw_multi_aff *decompress)
 {
-	int nparam;
+	isl_size nparam;
 	isl_ctx *ctx;
 	isl_mat *sched;
 	isl_space *space;
 	int *coincident;
 	struct isl_sched_node *node;
 
-	if (!set)
-		return isl_stat_error;
+	nparam = isl_set_dim(set, isl_dim_param);
+	if (nparam < 0)
+		goto error;
 
 	ctx = isl_set_get_ctx(set);
-	nparam = isl_set_dim(set, isl_dim_param);
 	if (!ctx->opt->schedule_parametric)
 		nparam = 0;
 	sched = isl_mat_alloc(ctx, 0, 1 + nparam + nvar);
@@ -1032,42 +1233,12 @@ static isl_stat add_node(struct isl_sched_graph *graph,
 		return isl_stat_error;
 
 	return isl_stat_ok;
-}
-
-/* Construct an identifier for node "node", which will represent "set".
- * The name of the identifier is either "compressed" or
- * "compressed_<name>", with <name> the name of the space of "set".
- * The user pointer of the identifier points to "node".
- */
-static __isl_give isl_id *construct_compressed_id(__isl_keep isl_set *set,
-	struct isl_sched_node *node)
-{
-	isl_bool has_name;
-	isl_ctx *ctx;
-	isl_id *id;
-	isl_printer *p;
-	const char *name;
-	char *id_name;
-
-	has_name = isl_set_has_tuple_name(set);
-	if (has_name < 0)
-		return NULL;
-
-	ctx = isl_set_get_ctx(set);
-	if (!has_name)
-		return isl_id_alloc(ctx, "compressed", node);
-
-	p = isl_printer_to_str(ctx);
-	name = isl_set_get_tuple_name(set);
-	p = isl_printer_print_str(p, "compressed_");
-	p = isl_printer_print_str(p, name);
-	id_name = isl_printer_get_str(p);
-	isl_printer_free(p);
-
-	id = isl_id_alloc(ctx, id_name, node);
-	free(id_name);
-
-	return id;
+error:
+	isl_set_free(set);
+	isl_set_free(hull);
+	isl_multi_aff_free(compress);
+	isl_pw_multi_aff_free(decompress);
+	return isl_stat_error;
 }
 
 /* Add a new node to the graph representing the given set.
@@ -1081,13 +1252,14 @@ static __isl_give isl_id *construct_compressed_id(__isl_keep isl_set *set,
  */
 static isl_stat extract_node(__isl_take isl_set *set, void *user)
 {
-	int nvar;
+	isl_size nvar;
 	isl_bool has_equality;
 	isl_id *id;
 	isl_basic_set *hull;
 	isl_set *hull_set;
 	isl_morph *morph;
-	isl_multi_aff *compress, *decompress;
+	isl_multi_aff *compress, *decompress_ma;
+	isl_pw_multi_aff *decompress;
 	struct isl_sched_graph *graph = user;
 
 	hull = isl_set_affine_hull(isl_set_copy(set));
@@ -1095,7 +1267,7 @@ static isl_stat extract_node(__isl_take isl_set *set, void *user)
 	nvar = isl_set_dim(set, isl_dim_set);
 	has_equality = has_any_defining_equality(hull);
 
-	if (has_equality < 0)
+	if (nvar < 0 || has_equality < 0)
 		goto error;
 	if (!has_equality) {
 		isl_basic_set_free(hull);
@@ -1103,13 +1275,15 @@ static isl_stat extract_node(__isl_take isl_set *set, void *user)
 	}
 
 	id = construct_compressed_id(set, &graph->node[graph->n]);
-	morph = isl_basic_set_variable_compression_with_id(hull,
-							    isl_dim_set, id);
+	morph = isl_basic_set_variable_compression_with_id(hull, id);
 	isl_id_free(id);
 	nvar = isl_morph_ran_dim(morph, isl_dim_set);
+	if (nvar < 0)
+		set = isl_set_free(set);
 	compress = isl_morph_get_var_multi_aff(morph);
 	morph = isl_morph_inverse(morph);
-	decompress = isl_morph_get_var_multi_aff(morph);
+	decompress_ma = isl_morph_get_var_multi_aff(morph);
+	decompress = isl_pw_multi_aff_from_multi_aff(decompress_ma);
 	isl_morph_free(morph);
 
 	hull_set = isl_set_from_basic_set(hull);
@@ -1393,6 +1567,7 @@ static isl_stat graph_init(struct isl_sched_graph *graph,
 	struct isl_extract_edge_data data;
 	enum isl_edge_type i;
 	isl_stat r;
+	isl_size n;
 
 	if (!sc)
 		return isl_stat_error;
@@ -1400,11 +1575,14 @@ static isl_stat graph_init(struct isl_sched_graph *graph,
 	ctx = isl_schedule_constraints_get_ctx(sc);
 
 	domain = isl_schedule_constraints_get_domain(sc);
-	graph->n = isl_union_set_n_set(domain);
+	n = isl_union_set_n_set(domain);
+	graph->n = n;
 	isl_union_set_free(domain);
+	if (n < 0)
+		return isl_stat_error;
 
-	if (graph_alloc(ctx, graph, graph->n,
-	    isl_schedule_constraints_n_map(sc)) < 0)
+	n = isl_schedule_constraints_n_map(sc);
+	if (n < 0 || graph_alloc(ctx, graph, graph->n, n) < 0)
 		return isl_stat_error;
 
 	if (compute_max_row(graph, sc) < 0)
@@ -1421,10 +1599,13 @@ static isl_stat graph_init(struct isl_sched_graph *graph,
 	if (graph_init_table(ctx, graph) < 0)
 		return isl_stat_error;
 	for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+		isl_size n;
+
 		c = isl_schedule_constraints_get(sc, i);
-		graph->max_edge[i] = isl_union_map_n_map(c);
+		n = isl_union_map_n_map(c);
+		graph->max_edge[i] = n;
 		isl_union_map_free(c);
-		if (!c)
+		if (n < 0)
 			return isl_stat_error;
 	}
 	if (graph_init_edge_tables(ctx, graph) < 0)
@@ -1551,17 +1732,15 @@ static __isl_give isl_basic_set *get_size_bounds(struct isl_sched_node *node)
 	isl_space *space;
 	isl_basic_set *bounds;
 	int i;
-	unsigned nparam;
 
 	if (node->bounds)
 		return isl_basic_set_copy(node->bounds);
 
 	if (node->compressed)
-		space = isl_multi_aff_get_domain_space(node->decompress);
+		space = isl_pw_multi_aff_get_domain_space(node->decompress);
 	else
 		space = isl_space_copy(node->space);
-	nparam = isl_space_dim(space, isl_dim_param);
-	space = isl_space_drop_dims(space, isl_dim_param, 0, nparam);
+	space = isl_space_drop_all_params(space);
 	bounds = isl_basic_set_universe(space);
 
 	for (i = 0; i < node->nvar; ++i) {
@@ -1584,6 +1763,22 @@ static __isl_give isl_basic_set *get_size_bounds(struct isl_sched_node *node)
 	return bounds;
 }
 
+/* Compress the dependence relation "map", if needed, i.e.,
+ * when the source node "src" and/or the destination node "dst"
+ * has been compressed.
+ */
+static __isl_give isl_map *compress(__isl_take isl_map *map,
+	struct isl_sched_node *src, struct isl_sched_node *dst)
+{
+	if (src->compressed)
+		map = isl_map_preimage_domain_pw_multi_aff(map,
+					isl_pw_multi_aff_copy(src->decompress));
+	if (dst->compressed)
+		map = isl_map_preimage_range_pw_multi_aff(map,
+					isl_pw_multi_aff_copy(dst->decompress));
+	return map;
+}
+
 /* Drop some constraints from "delta" that could be exploited
  * to construct loop coalescing schedules.
  * In particular, drop those constraint that bound the 
diff erence
@@ -1593,12 +1788,15 @@ static __isl_give isl_basic_set *get_size_bounds(struct isl_sched_node *node)
 static __isl_give isl_set *drop_coalescing_constraints(
 	__isl_take isl_set *delta, struct isl_sched_node *node)
 {
-	unsigned nparam;
+	isl_size nparam;
 	isl_basic_set *bounds;
 
+	nparam = isl_set_dim(delta, isl_dim_param);
+	if (nparam < 0)
+		return isl_set_free(delta);
+
 	bounds = get_size_bounds(node);
 
-	nparam = isl_set_dim(delta, isl_dim_param);
 	delta = isl_set_project_out(delta, isl_dim_param, 0, nparam);
 	delta = isl_set_remove_divs(delta);
 	delta = isl_set_plain_gist_basic_set(delta, bounds);
@@ -1662,12 +1860,7 @@ static __isl_give isl_basic_set *intra_coefficients(
 	}
 
 	key = isl_map_copy(map);
-	if (node->compressed) {
-		map = isl_map_preimage_domain_multi_aff(map,
-				    isl_multi_aff_copy(node->decompress));
-		map = isl_map_preimage_range_multi_aff(map,
-				    isl_multi_aff_copy(node->decompress));
-	}
+	map = compress(map, node, node);
 	delta = isl_map_deltas(map);
 	if (treat)
 		delta = drop_coalescing_constraints(delta, node);
@@ -1705,12 +1898,7 @@ static __isl_give isl_basic_set *inter_coefficients(
 	}
 
 	key = isl_map_copy(map);
-	if (edge->src->compressed)
-		map = isl_map_preimage_domain_multi_aff(map,
-				    isl_multi_aff_copy(edge->src->decompress));
-	if (edge->dst->compressed)
-		map = isl_map_preimage_range_multi_aff(map,
-				    isl_multi_aff_copy(edge->dst->decompress));
+	map = compress(map, edge->src, edge->dst);
 	set = isl_map_wrap(isl_map_remove_divs(map));
 	coef = isl_set_coefficients(set);
 	graph->inter_hmap = isl_map_to_basic_set_set(graph->inter_hmap, key,
@@ -1728,9 +1916,9 @@ static __isl_give isl_basic_set *inter_coefficients(
  *
  * Return the position of S.
  */
-static int coef_var_offset(__isl_keep isl_basic_set *coef)
+static isl_size coef_var_offset(__isl_keep isl_basic_set *coef)
 {
-	int offset;
+	isl_size offset;
 	isl_space *space;
 
 	space = isl_space_unwrap(isl_basic_set_get_space(coef));
@@ -1815,13 +2003,13 @@ static __isl_give isl_dim_map *intra_dim_map(isl_ctx *ctx,
 	int offset, int s)
 {
 	int pos;
-	unsigned total;
+	isl_size total;
 	isl_dim_map *dim_map;
 
-	if (!node || !graph->lp)
+	total = isl_basic_set_dim(graph->lp, isl_dim_all);
+	if (!node || total < 0)
 		return NULL;
 
-	total = isl_basic_set_total_dim(graph->lp);
 	pos = node_var_coef_pos(node, 0);
 	dim_map = isl_dim_map_alloc(ctx, total);
 	isl_dim_map_range(dim_map, pos, -2, offset, 1, node->nvar, -s);
@@ -1855,13 +2043,13 @@ static __isl_give isl_dim_map *inter_dim_map(isl_ctx *ctx,
 	struct isl_sched_node *dst, int offset, int s)
 {
 	int pos;
-	unsigned total;
+	isl_size total;
 	isl_dim_map *dim_map;
 
-	if (!src || !dst || !graph->lp)
+	total = isl_basic_set_dim(graph->lp, isl_dim_all);
+	if (!src || !dst || total < 0)
 		return NULL;
 
-	total = isl_basic_set_total_dim(graph->lp);
 	dim_map = isl_dim_map_alloc(ctx, total);
 
 	pos = node_cst_coef_offset(dst);
@@ -1919,7 +2107,7 @@ static __isl_give isl_basic_set *add_constraints_dim_map(
 static isl_stat add_intra_validity_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_edge *edge)
 {
-	int offset;
+	isl_size offset;
 	isl_map *map = isl_map_copy(edge->map);
 	isl_ctx *ctx = isl_map_get_ctx(map);
 	isl_dim_map *dim_map;
@@ -1929,7 +2117,8 @@ static isl_stat add_intra_validity_constraints(struct isl_sched_graph *graph,
 	coef = intra_coefficients(graph, node, map, 0);
 
 	offset = coef_var_offset(coef);
-
+	if (offset < 0)
+		coef = isl_basic_set_free(coef);
 	if (!coef)
 		return isl_stat_error;
 
@@ -1955,7 +2144,7 @@ static isl_stat add_intra_validity_constraints(struct isl_sched_graph *graph,
 static isl_stat add_inter_validity_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_edge *edge)
 {
-	int offset;
+	isl_size offset;
 	isl_map *map;
 	isl_ctx *ctx;
 	isl_dim_map *dim_map;
@@ -1971,7 +2160,8 @@ static isl_stat add_inter_validity_constraints(struct isl_sched_graph *graph,
 	coef = inter_coefficients(graph, edge, map);
 
 	offset = coef_var_offset(coef);
-
+	if (offset < 0)
+		coef = isl_basic_set_free(coef);
 	if (!coef)
 		return isl_stat_error;
 
@@ -2031,8 +2221,8 @@ static isl_stat add_inter_validity_constraints(struct isl_sched_graph *graph,
 static isl_stat add_intra_proximity_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_edge *edge, int s, int local)
 {
-	int offset;
-	unsigned nparam;
+	isl_size offset;
+	isl_size nparam;
 	isl_map *map = isl_map_copy(edge->map);
 	isl_ctx *ctx = isl_map_get_ctx(map);
 	isl_dim_map *dim_map;
@@ -2040,13 +2230,14 @@ static isl_stat add_intra_proximity_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_node *node = edge->src;
 
 	coef = intra_coefficients(graph, node, map, !local);
+	nparam = isl_space_dim(node->space, isl_dim_param);
 
 	offset = coef_var_offset(coef);
-
+	if (nparam < 0 || offset < 0)
+		coef = isl_basic_set_free(coef);
 	if (!coef)
 		return isl_stat_error;
 
-	nparam = isl_space_dim(node->space, isl_dim_param);
 	dim_map = intra_dim_map(ctx, graph, node, offset, -s);
 
 	if (!local) {
@@ -2109,8 +2300,8 @@ static isl_stat add_intra_proximity_constraints(struct isl_sched_graph *graph,
 static isl_stat add_inter_proximity_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_edge *edge, int s, int local)
 {
-	int offset;
-	unsigned nparam;
+	isl_size offset;
+	isl_size nparam;
 	isl_map *map = isl_map_copy(edge->map);
 	isl_ctx *ctx = isl_map_get_ctx(map);
 	isl_dim_map *dim_map;
@@ -2119,13 +2310,14 @@ static isl_stat add_inter_proximity_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_node *dst = edge->dst;
 
 	coef = inter_coefficients(graph, edge, map);
+	nparam = isl_space_dim(src->space, isl_dim_param);
 
 	offset = coef_var_offset(coef);
-
+	if (nparam < 0 || offset < 0)
+		coef = isl_basic_set_free(coef);
 	if (!coef)
 		return isl_stat_error;
 
-	nparam = isl_space_dim(src->space, isl_dim_param);
 	dim_map = inter_dim_map(ctx, graph, src, dst, offset, -s);
 
 	if (!local) {
@@ -2248,6 +2440,18 @@ static __isl_give isl_mat *normalize_independent(__isl_take isl_mat *indep)
 	return indep;
 }
 
+/* Extract the linear part of the current schedule for node "node".
+ */
+static __isl_give isl_mat *extract_linear_schedule(struct isl_sched_node *node)
+{
+	isl_size n_row = isl_mat_rows(node->sched);
+
+	if (n_row < 0)
+		return NULL;
+	return isl_mat_sub_alloc(node->sched, 0, n_row,
+			      1 + node->nparam, node->nvar);
+}
+
 /* Compute a basis for the rows in the linear part of the schedule
  * and extend this basis to a full basis.  The remaining rows
  * can then be used to force linear independence from the rows
@@ -2279,10 +2483,8 @@ static __isl_give isl_mat *normalize_independent(__isl_take isl_mat *indep)
 static int node_update_vmap(struct isl_sched_node *node)
 {
 	isl_mat *H, *U, *Q;
-	int n_row = isl_mat_rows(node->sched);
 
-	H = isl_mat_sub_alloc(node->sched, 0, n_row,
-			      1 + node->nparam, node->nvar);
+	H = extract_linear_schedule(node);
 
 	H = isl_mat_left_hermite(H, 0, &U, &Q);
 	isl_mat_free(node->indep);
@@ -2473,13 +2675,15 @@ static isl_stat add_bound_constant_constraints(isl_ctx *ctx,
 {
 	int i, k;
 	int max;
-	int total;
+	isl_size total;
 
 	max = isl_options_get_schedule_max_constant_term(ctx);
 	if (max == -1)
 		return isl_stat_ok;
 
 	total = isl_basic_set_dim(graph->lp, isl_dim_set);
+	if (total < 0)
+		return isl_stat_error;
 
 	for (i = 0; i < graph->n; ++i) {
 		struct isl_sched_node *node = &graph->node[i];
@@ -2552,10 +2756,12 @@ static isl_stat node_add_coefficient_constraints(isl_ctx *ctx,
 	struct isl_sched_graph *graph, struct isl_sched_node *node, int max)
 {
 	int i, j, k;
-	int total;
+	isl_size total;
 	isl_vec *ineq;
 
 	total = isl_basic_set_dim(graph->lp, isl_dim_set);
+	if (total < 0)
+		return isl_stat_error;
 
 	for (j = 0; j < node->nparam; ++j) {
 		int dim;
@@ -2643,9 +2849,11 @@ static isl_stat add_sum_constraint(struct isl_sched_graph *graph,
 	int sum_pos, int first, int n)
 {
 	int i, k;
-	int total;
+	isl_size total;
 
 	total = isl_basic_set_dim(graph->lp, isl_dim_set);
+	if (total < 0)
+		return isl_stat_error;
 
 	k = isl_basic_set_alloc_equality(graph->lp);
 	if (k < 0)
@@ -2665,9 +2873,11 @@ static isl_stat add_param_sum_constraint(struct isl_sched_graph *graph,
 	int sum_pos)
 {
 	int i, j, k;
-	int total;
+	isl_size total;
 
 	total = isl_basic_set_dim(graph->lp, isl_dim_set);
+	if (total < 0)
+		return isl_stat_error;
 
 	k = isl_basic_set_alloc_equality(graph->lp);
 	if (k < 0)
@@ -2691,9 +2901,11 @@ static isl_stat add_var_sum_constraint(struct isl_sched_graph *graph,
 	int sum_pos)
 {
 	int i, j, k;
-	int total;
+	isl_size total;
 
 	total = isl_basic_set_dim(graph->lp, isl_dim_set);
+	if (total < 0)
+		return isl_stat_error;
 
 	k = isl_basic_set_alloc_equality(graph->lp);
 	if (k < 0)
@@ -2745,7 +2957,7 @@ static isl_stat setup_lp(isl_ctx *ctx, struct isl_sched_graph *graph,
 	int use_coincidence)
 {
 	int i;
-	unsigned nparam;
+	isl_size nparam;
 	unsigned total;
 	isl_space *space;
 	int parametric;
@@ -2754,6 +2966,8 @@ static isl_stat setup_lp(isl_ctx *ctx, struct isl_sched_graph *graph,
 
 	parametric = ctx->opt->schedule_parametric;
 	nparam = isl_space_dim(graph->node[0].space, isl_dim_param);
+	if (nparam < 0)
+		return isl_stat_error;
 	param_pos = 4;
 	total = param_pos + 2 * nparam;
 	for (i = 0; i < graph->n; ++i) {
@@ -2856,14 +3070,15 @@ static __isl_give isl_mat *construct_trivial(__isl_keep isl_mat *indep)
 {
 	isl_ctx *ctx;
 	isl_mat *mat;
-	int i, j, n, n_var;
+	int i, j;
+	isl_size n, n_var;
 
-	if (!indep)
+	n = isl_mat_rows(indep);
+	n_var = isl_mat_cols(indep);
+	if (n < 0 || n_var < 0)
 		return NULL;
 
 	ctx = isl_mat_get_ctx(indep);
-	n = isl_mat_rows(indep);
-	n_var = isl_mat_cols(indep);
 	mat = isl_mat_alloc(ctx, n, 2 * n_var);
 	if (!mat)
 		return NULL;
@@ -2969,11 +3184,11 @@ static int update_schedule(struct isl_sched_graph *graph,
 	for (i = 0; i < graph->n; ++i) {
 		struct isl_sched_node *node = &graph->node[i];
 		int pos;
-		int row = isl_mat_rows(node->sched);
+		isl_size row = isl_mat_rows(node->sched);
 
 		isl_vec_free(csol);
 		csol = extract_var_coef(node, sol);
-		if (!csol)
+		if (row < 0 || !csol)
 			goto error;
 
 		isl_map_free(node->sched_map);
@@ -3056,13 +3271,15 @@ static __isl_give isl_multi_aff *node_extract_partial_schedule_multi_aff(
 	isl_local_space *ls;
 	isl_aff *aff;
 	isl_multi_aff *ma;
-	int nrow;
+	isl_size nrow;
 
 	if (!node)
 		return NULL;
 	nrow = isl_mat_rows(node->sched);
+	if (nrow < 0)
+		return NULL;
 	if (node->compressed)
-		space = isl_multi_aff_get_domain_space(node->decompress);
+		space = isl_pw_multi_aff_get_domain_space(node->decompress);
 	else
 		space = isl_space_copy(node->space);
 	ls = isl_local_space_from_space(isl_space_copy(space));
@@ -3091,9 +3308,11 @@ static __isl_give isl_multi_aff *node_extract_partial_schedule_multi_aff(
 static __isl_give isl_multi_aff *node_extract_schedule_multi_aff(
 	struct isl_sched_node *node)
 {
-	int nrow;
+	isl_size nrow;
 
 	nrow = isl_mat_rows(node->sched);
+	if (nrow < 0)
+		return NULL;
 	return node_extract_partial_schedule_multi_aff(node, 0, nrow);
 }
 
@@ -3189,7 +3408,8 @@ static isl_stat update_edge(isl_ctx *ctx, struct isl_sched_graph *graph,
 	if (empty < 0)
 		goto error;
 	if (empty) {
-		graph_remove_edge(graph, edge);
+		if (graph_remove_edge(graph, edge) < 0)
+			goto error;
 	} else if (is_multi_edge_type(edge)) {
 		if (graph_edge_tables_add(ctx, graph, edge) < 0)
 			goto error;
@@ -3475,7 +3695,7 @@ static isl_stat copy_nodes(struct isl_sched_graph *dst,
 		dst->node[j].compress =
 			isl_multi_aff_copy(src->node[i].compress);
 		dst->node[j].decompress =
-			isl_multi_aff_copy(src->node[i].decompress);
+			isl_pw_multi_aff_copy(src->node[i].decompress);
 		dst->node[j].nvar = src->node[i].nvar;
 		dst->node[j].nparam = src->node[i].nparam;
 		dst->node[j].sched = isl_mat_copy(src->node[i].sched);
@@ -3862,15 +4082,17 @@ static __isl_give isl_schedule_node *compute_next_band(
 static isl_stat add_intra_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_node *node, __isl_take isl_basic_set *coef, int pos)
 {
-	int offset;
+	isl_size offset;
 	isl_ctx *ctx;
 	isl_dim_map *dim_map;
 
+	offset = coef_var_offset(coef);
+	if (offset < 0)
+		coef = isl_basic_set_free(coef);
 	if (!coef)
 		return isl_stat_error;
 
 	ctx = isl_basic_set_get_ctx(coef);
-	offset = coef_var_offset(coef);
 	dim_map = intra_dim_map(ctx, graph, node, offset, 1);
 	isl_dim_map_range(dim_map, 3 + pos, 0, 0, 0, 1, -1);
 	graph->lp = add_constraints_dim_map(graph->lp, coef, dim_map);
@@ -3906,15 +4128,17 @@ static isl_stat add_inter_constraints(struct isl_sched_graph *graph,
 	struct isl_sched_node *src, struct isl_sched_node *dst,
 	__isl_take isl_basic_set *coef, int pos)
 {
-	int offset;
+	isl_size offset;
 	isl_ctx *ctx;
 	isl_dim_map *dim_map;
 
+	offset = coef_var_offset(coef);
+	if (offset < 0)
+		coef = isl_basic_set_free(coef);
 	if (!coef)
 		return isl_stat_error;
 
 	ctx = isl_basic_set_get_ctx(coef);
-	offset = coef_var_offset(coef);
 	dim_map = inter_dim_map(ctx, graph, src, dst, offset, 1);
 	if (pos >= 0)
 		isl_dim_map_range(dim_map, 3 + pos, 0, 0, 0, 1, -1);
@@ -4257,6 +4481,7 @@ static __isl_give isl_schedule_node *split_scaled(
 	int row;
 	isl_ctx *ctx;
 	isl_int gcd, gcd_i;
+	isl_size n_row;
 
 	if (!node)
 		return NULL;
@@ -4266,23 +4491,30 @@ static __isl_give isl_schedule_node *split_scaled(
 		return compute_next_band(node, graph, 0);
 	if (graph->n <= 1)
 		return compute_next_band(node, graph, 0);
+	n_row = isl_mat_rows(graph->node[0].sched);
+	if (n_row < 0)
+		return isl_schedule_node_free(node);
 
 	isl_int_init(gcd);
 	isl_int_init(gcd_i);
 
 	isl_int_set_si(gcd, 0);
 
-	row = isl_mat_rows(graph->node[0].sched) - 1;
+	row = n_row - 1;
 
 	for (i = 0; i < graph->n; ++i) {
 		struct isl_sched_node *node = &graph->node[i];
-		int cols = isl_mat_cols(node->sched);
+		isl_size cols = isl_mat_cols(node->sched);
 
+		if (cols < 0)
+			break;
 		isl_seq_gcd(node->sched->row[row] + 1, cols - 1, &gcd_i);
 		isl_int_gcd(gcd, gcd, gcd_i);
 	}
 
 	isl_int_clear(gcd_i);
+	if (i < graph->n)
+		goto error;
 
 	if (isl_int_cmp_si(gcd, 1) <= 0) {
 		isl_int_clear(gcd);
@@ -4620,12 +4852,7 @@ static __isl_give isl_union_map *add_intra(__isl_take isl_union_map *umap,
 		return umap;
 
 	map = isl_map_copy(edge->map);
-	if (node->compressed) {
-		map = isl_map_preimage_domain_multi_aff(map,
-				    isl_multi_aff_copy(node->decompress));
-		map = isl_map_preimage_range_multi_aff(map,
-				    isl_multi_aff_copy(node->decompress));
-	}
+	map = compress(map, node, node);
 	umap = isl_union_map_add_map(umap, map);
 	return umap;
 }
@@ -4644,12 +4871,7 @@ static __isl_give isl_union_map *add_inter(__isl_take isl_union_map *umap,
 		return umap;
 
 	map = isl_map_copy(edge->map);
-	if (edge->src->compressed)
-		map = isl_map_preimage_domain_multi_aff(map,
-				    isl_multi_aff_copy(edge->src->decompress));
-	if (edge->dst->compressed)
-		map = isl_map_preimage_range_multi_aff(map,
-				    isl_multi_aff_copy(edge->dst->decompress));
+	map = compress(map, edge->src, edge->dst);
 	umap = isl_union_map_add_map(umap, map);
 	return umap;
 }
@@ -4737,13 +4959,10 @@ static isl_stat add_non_trivial_lineality(__isl_take isl_basic_set *lineality,
 	isl_multi_aff *ma;
 	isl_multi_pw_aff *mpa;
 	isl_map *map;
-	int n;
+	isl_size n;
 
-	if (!lineality)
-		return isl_stat_error;
-	if (isl_basic_set_dim(lineality, isl_dim_div) != 0)
-		isl_die(isl_basic_set_get_ctx(lineality), isl_error_internal,
-			"local variables not allowed", goto error);
+	if (isl_basic_set_check_no_locals(lineality) < 0)
+		goto error;
 
 	space = isl_basic_set_get_space(lineality);
 	if (!data->any_non_trivial) {
@@ -4757,6 +4976,8 @@ static isl_stat add_non_trivial_lineality(__isl_take isl_basic_set *lineality,
 
 	eq = isl_basic_set_extract_equalities(lineality);
 	n = isl_mat_rows(eq);
+	if (n < 0)
+		space = isl_space_free(space);
 	eq = isl_mat_insert_zero_rows(eq, 0, 1);
 	eq = isl_mat_set_element_si(eq, 0, 0, 1);
 	space = isl_space_from_domain(space);
@@ -4785,18 +5006,22 @@ static isl_stat add_lineality(__isl_take isl_set *set, void *user)
 {
 	struct isl_exploit_lineality_data *data = user;
 	isl_basic_set *hull;
-	int dim, n_eq;
+	isl_size dim;
+	int n_eq;
 
 	set = isl_set_remove_divs(set);
 	hull = isl_set_unshifted_simple_hull(set);
 	dim = isl_basic_set_dim(hull, isl_dim_set);
 	n_eq = isl_basic_set_n_equality(hull);
-	if (!hull)
-		return isl_stat_error;
+	if (dim < 0)
+		goto error;
 	if (dim != n_eq)
 		return add_non_trivial_lineality(hull, data);
 	isl_basic_set_free(hull);
 	return isl_stat_ok;
+error:
+	isl_basic_set_free(hull);
+	return isl_stat_error;
 }
 
 /* Check if the 
diff erence set on intra-node schedule constraints "intra"
@@ -4914,17 +5139,6 @@ static __isl_give isl_union_map *collect_validity(struct isl_sched_graph *graph,
 	return umap;
 }
 
-/* Project out all parameters from "uset" and return the result.
- */
-static __isl_give isl_union_set *union_set_drop_parameters(
-	__isl_take isl_union_set *uset)
-{
-	unsigned nparam;
-
-	nparam = isl_union_set_dim(uset, isl_dim_param);
-	return isl_union_set_project_out(uset, isl_dim_param, 0, nparam);
-}
-
 /* For each dependence relation on a (conditional) validity edge
  * from a node to itself,
  * construct the set of coefficients of valid constraints for elements
@@ -4971,7 +5185,7 @@ static __isl_give isl_basic_set_list *collect_intra_validity(isl_ctx *ctx,
 
 	intra = collect_validity(graph, &add_intra, coincidence);
 	delta = isl_union_map_deltas(intra);
-	delta = union_set_drop_parameters(delta);
+	delta = isl_union_set_project_out_all_params(delta);
 	delta = isl_union_set_remove_divs(delta);
 	if (isl_options_get_schedule_treat_coalescing(ctx))
 		delta = union_drop_coalescing_constraints(ctx, graph, delta);
@@ -5085,7 +5299,7 @@ static __isl_give isl_vec *compute_carrying_sol_coef(isl_ctx *ctx,
 static __isl_give isl_vec *compute_carrying_sol(isl_ctx *ctx,
 	struct isl_sched_graph *graph, int fallback, int coincidence)
 {
-	int n_intra, n_inter;
+	isl_size n_intra, n_inter;
 	int n_edge;
 	struct isl_carry carry = { 0 };
 	isl_vec *sol;
@@ -5094,10 +5308,10 @@ static __isl_give isl_vec *compute_carrying_sol(isl_ctx *ctx,
 						&carry.lineality);
 	carry.inter = collect_inter_validity(graph, coincidence,
 						&carry.lineality);
-	if (!carry.intra || !carry.inter)
-		goto error;
 	n_intra = isl_basic_set_list_n_basic_set(carry.intra);
 	n_inter = isl_basic_set_list_n_basic_set(carry.inter);
+	if (n_intra < 0 || n_inter < 0)
+		goto error;
 
 	if (fallback && n_intra > 0 &&
 	    isl_options_get_schedule_carry_self_first(ctx)) {
@@ -5389,10 +5603,12 @@ static int has_any_coincidence(struct isl_sched_graph *graph)
 static __isl_give isl_map *final_row(struct isl_sched_node *node)
 {
 	isl_multi_aff *ma;
-	int row;
+	isl_size n_row;
 
-	row = isl_mat_rows(node->sched) - 1;
-	ma = node_extract_partial_schedule_multi_aff(node, row, 1);
+	n_row = isl_mat_rows(node->sched);
+	if (n_row < 0)
+		return NULL;
+	ma = node_extract_partial_schedule_multi_aff(node, n_row - 1, 1);
 	return isl_map_from_multi_aff(ma);
 }
 
@@ -6406,7 +6622,7 @@ static isl_bool ok_to_merge_coincident(struct isl_clustering *c,
 
 	n_coincident = get_n_coincident(merge_graph);
 
-	return n_coincident >= max_coincident;
+	return isl_bool_ok(n_coincident >= max_coincident);
 }
 
 /* Return the transformation on "node" expressed by the current (and only)
@@ -6490,13 +6706,13 @@ static isl_bool distance_is_bounded(__isl_keep isl_set *set, int pos)
  */
 static isl_bool has_single_value(__isl_keep isl_set *set, int pos)
 {
-	int n;
+	isl_size n;
 	isl_bool single;
 
-	if (!set)
+	n = isl_set_dim(set, isl_dim_set);
+	if (n < 0)
 		return isl_bool_error;
 	set = isl_set_copy(set);
-	n = isl_set_dim(set, isl_dim_set);
 	set = isl_set_project_out(set, isl_dim_set, pos + 1, n - (pos + 1));
 	set = isl_set_project_out(set, isl_dim_set, 0, pos);
 	single = isl_set_is_singleton(set);
@@ -6557,7 +6773,8 @@ static isl_bool has_bounded_distances(isl_ctx *ctx, struct isl_sched_edge *edge,
 	struct isl_sched_graph *graph, struct isl_clustering *c,
 	struct isl_sched_graph *merge_graph)
 {
-	int i, n, n_slack;
+	int i, n_slack;
+	isl_size n;
 	isl_bool bounded;
 	isl_map *map, *t;
 	isl_set *dist;
@@ -6571,6 +6788,8 @@ static isl_bool has_bounded_distances(isl_ctx *ctx, struct isl_sched_edge *edge,
 
 	bounded = isl_bool_true;
 	n = isl_set_dim(dist, isl_dim_set);
+	if (n < 0)
+		goto error;
 	n_slack = n - edge->weight;
 	if (edge->weight < 0)
 		n_slack -= graph->max_weight + 1;
@@ -6701,12 +6920,15 @@ static __isl_give isl_mat *node_transformation(isl_ctx *ctx,
 {
 	int i, j;
 	isl_mat *t;
-	int n_row, n_col, n_param, n_var;
+	isl_size n_row, n_col;
+	int n_param, n_var;
 
 	n_param = node->nparam;
 	n_var = node->nvar;
 	n_row = isl_mat_rows(t_node->sched);
 	n_col = isl_mat_cols(node->sched);
+	if (n_row < 0 || n_col < 0)
+		return NULL;
 	t = isl_mat_alloc(ctx, n_row, n_col);
 	if (!t)
 		return NULL;
@@ -6736,13 +6958,15 @@ static isl_stat transform(isl_ctx *ctx, struct isl_sched_graph *graph,
 	struct isl_sched_node *t_node)
 {
 	int i, j;
-	int n_new;
+	isl_size n_new;
 	int start, n;
 
 	start = graph->band_start;
 	n = graph->n_total_row - start;
 
 	n_new = isl_mat_rows(t_node->sched);
+	if (n_new < 0)
+		return isl_stat_error;
 	for (i = 0; i < graph->n; ++i) {
 		struct isl_sched_node *node = &graph->node[i];
 		isl_mat *t;
@@ -7094,7 +7318,7 @@ static isl_stat compute_weights(struct isl_sched_graph *graph,
 		struct isl_sched_node *dst = edge->dst;
 		isl_basic_map *hull;
 		isl_bool prox;
-		int n_in, n_out;
+		isl_size n_in, n_out;
 
 		prox = is_non_empty_proximity(edge);
 		if (prox < 0)
@@ -7120,6 +7344,8 @@ static isl_stat compute_weights(struct isl_sched_graph *graph,
 		hull = isl_basic_map_remove_divs(hull);
 		n_in = isl_basic_map_dim(hull, isl_dim_in);
 		n_out = isl_basic_map_dim(hull, isl_dim_out);
+		if (n_in < 0 || n_out < 0)
+			hull = isl_basic_map_free(hull);
 		hull = isl_basic_map_drop_constraints_not_involving_dims(hull,
 							isl_dim_in, 0, n_in);
 		hull = isl_basic_map_drop_constraints_not_involving_dims(hull,
@@ -7379,16 +7605,18 @@ __isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
 	isl_schedule *sched;
 	isl_schedule_node *node;
 	isl_union_set *domain;
+	isl_size n;
 
 	sc = isl_schedule_constraints_align_params(sc);
 
 	domain = isl_schedule_constraints_get_domain(sc);
-	if (isl_union_set_n_set(domain) == 0) {
+	n = isl_union_set_n_set(domain);
+	if (n == 0) {
 		isl_schedule_constraints_free(sc);
 		return isl_schedule_from_domain(domain);
 	}
 
-	if (graph_init(&graph, sc) < 0)
+	if (n < 0 || graph_init(&graph, sc) < 0)
 		domain = isl_union_set_free(domain);
 
 	node = isl_schedule_node_from_domain(domain);

diff  --git a/polly/lib/External/isl/isl_set_list.c b/polly/lib/External/isl/isl_set_list.c
index 333441387277..2a6749aa13c5 100644
--- a/polly/lib/External/isl/isl_set_list.c
+++ b/polly/lib/External/isl/isl_set_list.c
@@ -16,17 +16,17 @@
 
 #include <isl_list_templ.h>
 
-#undef BASE
-#define BASE basic_set
+#undef EL_BASE
+#define EL_BASE basic_set
 
 #include <isl_list_templ.c>
 
-#undef BASE
-#define BASE set
+#undef EL_BASE
+#define EL_BASE set
 
 #include <isl_list_templ.c>
 
-#undef BASE
-#define BASE union_set
+#undef EL_BASE
+#define EL_BASE union_set
 
 #include <isl_list_templ.c>

diff  --git a/polly/lib/External/isl/isl_set_to_ast_graft_list.c b/polly/lib/External/isl/isl_set_to_ast_graft_list.c
new file mode 100644
index 000000000000..86206d0e4ef5
--- /dev/null
+++ b/polly/lib/External/isl/isl_set_to_ast_graft_list.c
@@ -0,0 +1,17 @@
+#include <isl/ctx.h>
+#include <isl/set_type.h>
+#include "isl_ast_graft_private.h"
+#include "isl_set_to_ast_graft_list.h"
+
+#define isl_ast_graft_list_is_identical(a, b)	isl_bool_ok(a == b)
+
+#define ISL_KEY			isl_set
+#define ISL_VAL			isl_ast_graft_list
+#define ISL_HMAP_SUFFIX		set_to_ast_graft_list
+#define ISL_HMAP		isl_set_to_ast_graft_list
+#define ISL_KEY_IS_EQUAL	isl_set_plain_is_equal
+#define ISL_VAL_IS_EQUAL	isl_ast_graft_list_is_identical
+#define ISL_KEY_PRINT		isl_printer_print_set
+#define ISL_VAL_PRINT		isl_printer_print_ast_graft_list
+
+#include <isl/hmap_templ.c>

diff  --git a/polly/lib/External/isl/isl_set_to_ast_graft_list.h b/polly/lib/External/isl/isl_set_to_ast_graft_list.h
new file mode 100644
index 000000000000..862afaab2c45
--- /dev/null
+++ b/polly/lib/External/isl/isl_set_to_ast_graft_list.h
@@ -0,0 +1,18 @@
+#ifndef ISL_SET_TO_GRAFT_LIST_H
+#define ISL_SET_TO_GRAFT_LIST_H
+
+#include <isl/set_type.h>
+#include "isl_ast_graft_private.h"
+#include "isl_maybe_ast_graft_list.h"
+
+#define ISL_KEY			isl_set
+#define ISL_VAL			isl_ast_graft_list
+#define ISL_HMAP_SUFFIX		set_to_ast_graft_list
+#define ISL_HMAP		isl_set_to_ast_graft_list
+#include <isl/hmap.h>
+#undef ISL_KEY
+#undef ISL_VAL
+#undef ISL_HMAP_SUFFIX
+#undef ISL_HMAP
+
+#endif

diff  --git a/polly/lib/External/isl/isl_space.c b/polly/lib/External/isl/isl_space.c
index 3a6c2bd0d834..0d35ff6e19fd 100644
--- a/polly/lib/External/isl/isl_space.c
+++ b/polly/lib/External/isl/isl_space.c
@@ -2,6 +2,7 @@
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  * Copyright 2010      INRIA Saclay
  * Copyright 2013-2014 Ecole Normale Superieure
+ * Copyright 2018-2019 Cerebras Systems
  *
  * Use of this software is governed by the MIT license
  *
@@ -10,6 +11,7 @@
  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
  */
 
 #include <stdlib.h>
@@ -18,37 +20,37 @@
 #include <isl_id_private.h>
 #include <isl_reordering.h>
 
-isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim)
+isl_ctx *isl_space_get_ctx(__isl_keep isl_space *space)
 {
-	return dim ? dim->ctx : NULL;
+	return space ? space->ctx : NULL;
 }
 
 __isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
 			unsigned nparam, unsigned n_in, unsigned n_out)
 {
-	isl_space *dim;
+	isl_space *space;
 
-	dim = isl_alloc_type(ctx, struct isl_space);
-	if (!dim)
+	space = isl_alloc_type(ctx, struct isl_space);
+	if (!space)
 		return NULL;
 
-	dim->ctx = ctx;
+	space->ctx = ctx;
 	isl_ctx_ref(ctx);
-	dim->ref = 1;
-	dim->nparam = nparam;
-	dim->n_in = n_in;
-	dim->n_out = n_out;
+	space->ref = 1;
+	space->nparam = nparam;
+	space->n_in = n_in;
+	space->n_out = n_out;
 
-	dim->tuple_id[0] = NULL;
-	dim->tuple_id[1] = NULL;
+	space->tuple_id[0] = NULL;
+	space->tuple_id[1] = NULL;
 
-	dim->nested[0] = NULL;
-	dim->nested[1] = NULL;
+	space->nested[0] = NULL;
+	space->nested[1] = NULL;
 
-	dim->n_id = 0;
-	dim->ids = NULL;
+	space->n_id = 0;
+	space->ids = NULL;
 
-	return dim;
+	return space;
 }
 
 /* Mark the space as being that of a set, by setting the domain tuple
@@ -76,14 +78,63 @@ isl_bool isl_space_is_set(__isl_keep isl_space *space)
 	return isl_bool_true;
 }
 
+/* Check that "space" is a set space.
+ */
+isl_stat isl_space_check_is_set(__isl_keep isl_space *space)
+{
+	isl_bool is_set;
+
+	is_set = isl_space_is_set(space);
+	if (is_set < 0)
+		return isl_stat_error;
+	if (!is_set)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"space is not a set", return isl_stat_error);
+	return isl_stat_ok;
+}
+
 /* Is the given space that of a map?
  */
 isl_bool isl_space_is_map(__isl_keep isl_space *space)
 {
+	int r;
+
 	if (!space)
 		return isl_bool_error;
-	return space->tuple_id[0] != &isl_id_none &&
-		space->tuple_id[1] != &isl_id_none;
+	r = space->tuple_id[0] != &isl_id_none &&
+	    space->tuple_id[1] != &isl_id_none;
+	return isl_bool_ok(r);
+}
+
+/* Check that "space" is the space of a map.
+ */
+static isl_stat isl_space_check_is_map(__isl_keep isl_space *space)
+{
+	isl_bool is_space;
+
+	is_space = isl_space_is_map(space);
+	if (is_space < 0)
+		return isl_stat_error;
+	if (!is_space)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"expecting map space", return isl_stat_error);
+	return isl_stat_ok;
+}
+
+/* Check that "space" is the space of a map
+ * where the range is a wrapped map space.
+ */
+isl_stat isl_space_check_range_is_wrapping(__isl_keep isl_space *space)
+{
+	isl_bool wrapping;
+
+	wrapping = isl_space_range_is_wrapping(space);
+	if (wrapping < 0)
+		return isl_stat_error;
+	if (!wrapping)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"range not a product", return isl_stat_error);
+	return isl_stat_ok;
 }
 
 __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
@@ -133,132 +184,166 @@ __isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam)
 	return space;
 }
 
-static unsigned global_pos(__isl_keep isl_space *dim,
+/* Create a space for a parameter domain, without any parameters.
+ */
+__isl_give isl_space *isl_space_unit(isl_ctx *ctx)
+{
+	return isl_space_params_alloc(ctx, 0);
+}
+
+static isl_size global_pos(__isl_keep isl_space *space,
 				 enum isl_dim_type type, unsigned pos)
 {
-	struct isl_ctx *ctx = dim->ctx;
+	if (isl_space_check_range(space, type, pos, 1) < 0)
+		return isl_size_error;
 
 	switch (type) {
 	case isl_dim_param:
-		isl_assert(ctx, pos < dim->nparam,
-			    return isl_space_dim(dim, isl_dim_all));
 		return pos;
 	case isl_dim_in:
-		isl_assert(ctx, pos < dim->n_in,
-			    return isl_space_dim(dim, isl_dim_all));
-		return pos + dim->nparam;
+		return pos + space->nparam;
 	case isl_dim_out:
-		isl_assert(ctx, pos < dim->n_out,
-			    return isl_space_dim(dim, isl_dim_all));
-		return pos + dim->nparam + dim->n_in;
+		return pos + space->nparam + space->n_in;
 	default:
-		isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all));
+		isl_assert(isl_space_get_ctx(space), 0, return isl_size_error);
 	}
-	return isl_space_dim(dim, isl_dim_all);
+	return isl_size_error;
 }
 
 /* Extend length of ids array to the total number of dimensions.
  */
-static __isl_give isl_space *extend_ids(__isl_take isl_space *dim)
+static __isl_give isl_space *extend_ids(__isl_take isl_space *space)
 {
 	isl_id **ids;
 	int i;
+	isl_size dim;
 
-	if (isl_space_dim(dim, isl_dim_all) <= dim->n_id)
-		return dim;
+	dim = isl_space_dim(space, isl_dim_all);
+	if (dim < 0)
+		return isl_space_free(space);
+	if (dim <= space->n_id)
+		return space;
 
-	if (!dim->ids) {
-		dim->ids = isl_calloc_array(dim->ctx,
-				isl_id *, isl_space_dim(dim, isl_dim_all));
-		if (!dim->ids)
+	if (!space->ids) {
+		space->ids = isl_calloc_array(space->ctx, isl_id *, dim);
+		if (!space->ids)
 			goto error;
 	} else {
-		ids = isl_realloc_array(dim->ctx, dim->ids,
-				isl_id *, isl_space_dim(dim, isl_dim_all));
+		ids = isl_realloc_array(space->ctx, space->ids, isl_id *, dim);
 		if (!ids)
 			goto error;
-		dim->ids = ids;
-		for (i = dim->n_id; i < isl_space_dim(dim, isl_dim_all); ++i)
-			dim->ids[i] = NULL;
+		space->ids = ids;
+		for (i = space->n_id; i < dim; ++i)
+			space->ids[i] = NULL;
 	}
 
-	dim->n_id = isl_space_dim(dim, isl_dim_all);
+	space->n_id = dim;
 
-	return dim;
+	return space;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
-static __isl_give isl_space *set_id(__isl_take isl_space *dim,
+static __isl_give isl_space *set_id(__isl_take isl_space *space,
 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
 {
-	dim = isl_space_cow(dim);
+	isl_size gpos;
 
-	if (!dim)
-		goto error;
+	space = isl_space_cow(space);
 
-	pos = global_pos(dim, type, pos);
-	if (pos == isl_space_dim(dim, isl_dim_all))
+	gpos = global_pos(space, type, pos);
+	if (gpos < 0)
 		goto error;
 
-	if (pos >= dim->n_id) {
+	if (gpos >= space->n_id) {
 		if (!id)
-			return dim;
-		dim = extend_ids(dim);
-		if (!dim)
+			return space;
+		space = extend_ids(space);
+		if (!space)
 			goto error;
 	}
 
-	dim->ids[pos] = id;
+	space->ids[gpos] = id;
 
-	return dim;
+	return space;
 error:
 	isl_id_free(id);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
-static __isl_keep isl_id *get_id(__isl_keep isl_space *dim,
+static __isl_keep isl_id *get_id(__isl_keep isl_space *space,
 				 enum isl_dim_type type, unsigned pos)
 {
-	if (!dim)
-		return NULL;
+	isl_size gpos;
 
-	pos = global_pos(dim, type, pos);
-	if (pos == isl_space_dim(dim, isl_dim_all))
+	gpos = global_pos(space, type, pos);
+	if (gpos < 0)
 		return NULL;
-	if (pos >= dim->n_id)
+	if (gpos >= space->n_id)
 		return NULL;
-	return dim->ids[pos];
+	return space->ids[gpos];
 }
 
-static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type)
+/* Return the nested space at the given position.
+ */
+static __isl_keep isl_space *isl_space_peek_nested(__isl_keep isl_space *space,
+	int pos)
+{
+	if (!space)
+		return NULL;
+	if (!space->nested[pos])
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"no nested space", return NULL);
+	return space->nested[pos];
+}
+
+static unsigned offset(__isl_keep isl_space *space, enum isl_dim_type type)
 {
 	switch (type) {
 	case isl_dim_param:	return 0;
-	case isl_dim_in:	return dim->nparam;
-	case isl_dim_out:	return dim->nparam + dim->n_in;
+	case isl_dim_in:	return space->nparam;
+	case isl_dim_out:	return space->nparam + space->n_in;
 	default:		return 0;
 	}
 }
 
-static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
+static unsigned n(__isl_keep isl_space *space, enum isl_dim_type type)
 {
 	switch (type) {
-	case isl_dim_param:	return dim->nparam;
-	case isl_dim_in:	return dim->n_in;
-	case isl_dim_out:	return dim->n_out;
-	case isl_dim_all:	return dim->nparam + dim->n_in + dim->n_out;
+	case isl_dim_param:	return space->nparam;
+	case isl_dim_in:	return space->n_in;
+	case isl_dim_out:	return space->n_out;
+	case isl_dim_all:
+		return space->nparam + space->n_in + space->n_out;
 	default:		return 0;
 	}
 }
 
-unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type)
+isl_size isl_space_dim(__isl_keep isl_space *space, enum isl_dim_type type)
 {
-	if (!dim)
-		return 0;
-	return n(dim, type);
+	if (!space)
+		return isl_size_error;
+	return n(space, type);
+}
+
+/* Return the dimensionality of tuple "inner" within the wrapped relation
+ * inside tuple "outer".
+ */
+isl_size isl_space_wrapped_dim(__isl_keep isl_space *space,
+	enum isl_dim_type outer, enum isl_dim_type inner)
+{
+	int pos;
+
+	if (!space)
+		return isl_size_error;
+	if (outer != isl_dim_in && outer != isl_dim_out)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"only input, output and set tuples "
+			"can have nested relations", return isl_size_error);
+	pos = outer - isl_dim_in;
+	return isl_space_dim(isl_space_peek_nested(space, pos), inner);
 }
 
 unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type)
@@ -289,53 +374,56 @@ static __isl_give isl_space *copy_ids(__isl_take isl_space *dst,
 	return dst;
 }
 
-__isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
+__isl_take isl_space *isl_space_dup(__isl_keep isl_space *space)
 {
 	isl_space *dup;
-	if (!dim)
+	if (!space)
 		return NULL;
-	dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
+	dup = isl_space_alloc(space->ctx,
+				space->nparam, space->n_in, space->n_out);
 	if (!dup)
 		return NULL;
-	if (dim->tuple_id[0] &&
-	    !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
+	if (space->tuple_id[0] &&
+	    !(dup->tuple_id[0] = isl_id_copy(space->tuple_id[0])))
 		goto error;
-	if (dim->tuple_id[1] &&
-	    !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1])))
+	if (space->tuple_id[1] &&
+	    !(dup->tuple_id[1] = isl_id_copy(space->tuple_id[1])))
 		goto error;
-	if (dim->nested[0] && !(dup->nested[0] = isl_space_copy(dim->nested[0])))
+	if (space->nested[0] &&
+	    !(dup->nested[0] = isl_space_copy(space->nested[0])))
 		goto error;
-	if (dim->nested[1] && !(dup->nested[1] = isl_space_copy(dim->nested[1])))
+	if (space->nested[1] &&
+	    !(dup->nested[1] = isl_space_copy(space->nested[1])))
 		goto error;
-	if (!dim->ids)
+	if (!space->ids)
 		return dup;
-	dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
-	dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
-	dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
+	dup = copy_ids(dup, isl_dim_param, 0, space, isl_dim_param);
+	dup = copy_ids(dup, isl_dim_in, 0, space, isl_dim_in);
+	dup = copy_ids(dup, isl_dim_out, 0, space, isl_dim_out);
 	return dup;
 error:
 	isl_space_free(dup);
 	return NULL;
 }
 
-__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_cow(__isl_take isl_space *space)
 {
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	if (dim->ref == 1)
-		return dim;
-	dim->ref--;
-	return isl_space_dup(dim);
+	if (space->ref == 1)
+		return space;
+	space->ref--;
+	return isl_space_dup(space);
 }
 
-__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
+__isl_give isl_space *isl_space_copy(__isl_keep isl_space *space)
 {
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	dim->ref++;
-	return dim;
+	space->ref++;
+	return space;
 }
 
 __isl_null isl_space *isl_space_free(__isl_take isl_space *space)
@@ -382,6 +470,67 @@ static int name_ok(isl_ctx *ctx, const char *s)
 	return 1;
 }
 
+/* Return a copy of the nested space at the given position.
+ */
+static __isl_keep isl_space *isl_space_get_nested(__isl_keep isl_space *space,
+	int pos)
+{
+	return isl_space_copy(isl_space_peek_nested(space, pos));
+}
+
+/* Return the nested space at the given position.
+ * This may be either a copy or the nested space itself
+ * if there is only one reference to "space".
+ * This allows the nested space to be modified inplace
+ * if both "space" and the nested space have only a single reference.
+ * The caller is not allowed to modify "space" between this call and
+ * a subsequent call to isl_space_restore_nested.
+ * The only exception is that isl_space_free can be called instead.
+ */
+static __isl_give isl_space *isl_space_take_nested(__isl_keep isl_space *space,
+	int pos)
+{
+	isl_space *nested;
+
+	if (!space)
+		return NULL;
+	if (space->ref != 1)
+		return isl_space_get_nested(space, pos);
+	nested = space->nested[pos];
+	space->nested[pos] = NULL;
+	return nested;
+}
+
+/* Replace the nested space at the given position by "nested",
+ * where this nested space of "space" may be missing
+ * due to a preceding call to isl_space_take_nested.
+ * However, in this case, "space" only has a single reference and
+ * then the call to isl_space_cow has no effect.
+ */
+static __isl_give isl_space *isl_space_restore_nested(
+	__isl_take isl_space *space, int pos, __isl_take isl_space *nested)
+{
+	if (!space || !nested)
+		goto error;
+
+	if (space->nested[pos] == nested) {
+		isl_space_free(nested);
+		return space;
+	}
+
+	space = isl_space_cow(space);
+	if (!space)
+		goto error;
+	isl_space_free(space->nested[pos]);
+	space->nested[pos] = nested;
+
+	return space;
+error:
+	isl_space_free(space);
+	isl_space_free(nested);
+	return NULL;
+}
+
 /* Is it possible for the given dimension type to have a tuple id?
  */
 static int space_can_have_id(__isl_keep isl_space *space,
@@ -405,68 +554,68 @@ static int space_can_have_id(__isl_keep isl_space *space,
 
 /* Does the tuple have an id?
  */
-isl_bool isl_space_has_tuple_id(__isl_keep isl_space *dim,
+isl_bool isl_space_has_tuple_id(__isl_keep isl_space *space,
 	enum isl_dim_type type)
 {
-	if (!space_can_have_id(dim, type))
+	if (!space_can_have_id(space, type))
 		return isl_bool_error;
-	return dim->tuple_id[type - isl_dim_in] != NULL;
+	return isl_bool_ok(space->tuple_id[type - isl_dim_in] != NULL);
 }
 
-__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
+__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *space,
 	enum isl_dim_type type)
 {
 	int has_id;
 
-	if (!dim)
+	if (!space)
 		return NULL;
-	has_id = isl_space_has_tuple_id(dim, type);
+	has_id = isl_space_has_tuple_id(space, type);
 	if (has_id < 0)
 		return NULL;
 	if (!has_id)
-		isl_die(dim->ctx, isl_error_invalid,
+		isl_die(space->ctx, isl_error_invalid,
 			"tuple has no id", return NULL);
-	return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
+	return isl_id_copy(space->tuple_id[type - isl_dim_in]);
 }
 
-__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *space,
 	enum isl_dim_type type, __isl_take isl_id *id)
 {
-	dim = isl_space_cow(dim);
-	if (!dim || !id)
+	space = isl_space_cow(space);
+	if (!space || !id)
 		goto error;
 	if (type != isl_dim_in && type != isl_dim_out)
-		isl_die(dim->ctx, isl_error_invalid,
+		isl_die(space->ctx, isl_error_invalid,
 			"only input, output and set tuples can have names",
 			goto error);
 
-	isl_id_free(dim->tuple_id[type - isl_dim_in]);
-	dim->tuple_id[type - isl_dim_in] = id;
+	isl_id_free(space->tuple_id[type - isl_dim_in]);
+	space->tuple_id[type - isl_dim_in] = id;
 
-	return dim;
+	return space;
 error:
 	isl_id_free(id);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
-__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *space,
 	enum isl_dim_type type)
 {
-	dim = isl_space_cow(dim);
-	if (!dim)
+	space = isl_space_cow(space);
+	if (!space)
 		return NULL;
 	if (type != isl_dim_in && type != isl_dim_out)
-		isl_die(dim->ctx, isl_error_invalid,
+		isl_die(space->ctx, isl_error_invalid,
 			"only input, output and set tuples can have names",
 			goto error);
 
-	isl_id_free(dim->tuple_id[type - isl_dim_in]);
-	dim->tuple_id[type - isl_dim_in] = NULL;
+	isl_id_free(space->tuple_id[type - isl_dim_in]);
+	space->tuple_id[type - isl_dim_in] = NULL;
 
-	return dim;
+	return space;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -537,43 +686,43 @@ __isl_give isl_space *isl_space_reset_dim_id(__isl_take isl_space *space,
 	return NULL;
 }
 
-isl_bool isl_space_has_dim_id(__isl_keep isl_space *dim,
+isl_bool isl_space_has_dim_id(__isl_keep isl_space *space,
 	enum isl_dim_type type, unsigned pos)
 {
-	if (!dim)
+	if (!space)
 		return isl_bool_error;
-	return get_id(dim, type, pos) != NULL;
+	return isl_bool_ok(get_id(space, type, pos) != NULL);
 }
 
-__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim,
+__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *space,
 	enum isl_dim_type type, unsigned pos)
 {
-	if (!dim)
+	if (!space)
 		return NULL;
-	if (!get_id(dim, type, pos))
-		isl_die(dim->ctx, isl_error_invalid,
+	if (!get_id(space, type, pos))
+		isl_die(space->ctx, isl_error_invalid,
 			"dim has no id", return NULL);
-	return isl_id_copy(get_id(dim, type, pos));
+	return isl_id_copy(get_id(space, type, pos));
 }
 
-__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *space,
 	enum isl_dim_type type, const char *s)
 {
 	isl_id *id;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 
 	if (!s)
-		return isl_space_reset_tuple_id(dim, type);
+		return isl_space_reset_tuple_id(space, type);
 
-	if (!name_ok(dim->ctx, s))
+	if (!name_ok(space->ctx, s))
 		goto error;
 
-	id = isl_id_alloc(dim->ctx, s, NULL);
-	return isl_space_set_tuple_id(dim, type, id);
+	id = isl_id_alloc(space->ctx, s, NULL);
+	return isl_space_set_tuple_id(space, type, id);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -587,37 +736,37 @@ isl_bool isl_space_has_tuple_name(__isl_keep isl_space *space,
 	if (!space_can_have_id(space, type))
 		return isl_bool_error;
 	id = space->tuple_id[type - isl_dim_in];
-	return id && id->name;
+	return isl_bool_ok(id && id->name);
 }
 
-__isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
+__isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *space,
 	 enum isl_dim_type type)
 {
 	isl_id *id;
-	if (!dim)
+	if (!space)
 		return NULL;
 	if (type != isl_dim_in && type != isl_dim_out)
 		return NULL;
-	id = dim->tuple_id[type - isl_dim_in];
+	id = space->tuple_id[type - isl_dim_in];
 	return id ? id->name : NULL;
 }
 
-__isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *space,
 				 enum isl_dim_type type, unsigned pos,
 				 const char *s)
 {
 	isl_id *id;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 	if (!s)
-		return isl_space_reset_dim_id(dim, type, pos);
-	if (!name_ok(dim->ctx, s))
+		return isl_space_reset_dim_id(space, type, pos);
+	if (!name_ok(space->ctx, s))
 		goto error;
-	id = isl_id_alloc(dim->ctx, s, NULL);
-	return isl_space_set_dim_id(dim, type, pos, id);
+	id = isl_id_alloc(space->ctx, s, NULL);
+	return isl_space_set_dim_id(space, type, pos, id);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -631,30 +780,30 @@ isl_bool isl_space_has_dim_name(__isl_keep isl_space *space,
 	if (!space)
 		return isl_bool_error;
 	id = get_id(space, type, pos);
-	return id && id->name;
+	return isl_bool_ok(id && id->name);
 }
 
-__isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim,
+__isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *space,
 				 enum isl_dim_type type, unsigned pos)
 {
-	isl_id *id = get_id(dim, type, pos);
+	isl_id *id = get_id(space, type, pos);
 	return id ? id->name : NULL;
 }
 
-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_id(__isl_keep isl_space *space,
+	enum isl_dim_type type, __isl_keep isl_id *id)
 {
 	int i;
 	int offset;
-	int n;
+	isl_size n;
 
-	if (!dim || !id)
+	n = isl_space_dim(space, type);
+	if (n < 0 || !id)
 		return -1;
 
-	offset = isl_space_offset(dim, type);
-	n = isl_space_dim(dim, type);
-	for (i = 0; i < n && offset + i < dim->n_id; ++i)
-		if (dim->ids[offset + i] == id)
+	offset = isl_space_offset(space, type);
+	for (i = 0; i < n && offset + i < space->n_id; ++i)
+		if (space->ids[offset + i] == id)
 			return i;
 
 	return -1;
@@ -665,13 +814,13 @@ int isl_space_find_dim_by_name(__isl_keep isl_space *space,
 {
 	int i;
 	int offset;
-	int n;
+	isl_size n;
 
-	if (!space || !name)
+	n = isl_space_dim(space, type);
+	if (n < 0 || !name)
 		return -1;
 
 	offset = isl_space_offset(space, type);
-	n = isl_space_dim(space, type);
 	for (i = 0; i < n && offset + i < space->n_id; ++i) {
 		isl_id *id = get_id(space, type, i);
 		if (id && id->name && !strcmp(id->name, name))
@@ -727,14 +876,15 @@ __isl_give isl_space *isl_space_reset_user(__isl_take isl_space *space)
 	}
 
 	for (i = 0; i < 2; ++i) {
+		isl_space *nested;
+
 		if (!space->nested[i])
 			continue;
-		space = isl_space_cow(space);
+		nested = isl_space_take_nested(space, i);
+		nested = isl_space_reset_user(nested);
+		space = isl_space_restore_nested(space, i, nested);
 		if (!space)
 			return NULL;
-		space->nested[i] = isl_space_reset_user(space->nested[i]);
-		if (!space->nested[i])
-			return isl_space_free(space);
 	}
 
 	return space;
@@ -779,6 +929,24 @@ isl_bool isl_space_has_equal_tuples(__isl_keep isl_space *space1,
 					space2, isl_dim_out);
 }
 
+/* Check that the two spaces are the same,
+ * apart from positions and names of parameters.
+ */
+isl_stat isl_space_check_equal_tuples(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2)
+{
+	isl_bool is_equal;
+
+	is_equal = isl_space_has_equal_tuples(space1, space2);
+	if (is_equal < 0)
+		return isl_stat_error;
+	if (!is_equal)
+		isl_die(isl_space_get_ctx(space1), isl_error_invalid,
+			"incompatible spaces", return isl_stat_error);
+
+	return isl_stat_ok;
+}
+
 /* Check if the tuple of type "type1" of "space1" is the same as
  * the tuple of type "type2" of "space2".
  *
@@ -825,12 +993,17 @@ static isl_bool match(__isl_keep isl_space *space1, enum isl_dim_type type1,
 	__isl_keep isl_space *space2, enum isl_dim_type type2)
 {
 	int i;
+	isl_bool equal;
+
+	if (!space1 || !space2)
+		return isl_bool_error;
 
 	if (space1 == space2 && type1 == type2)
 		return isl_bool_true;
 
-	if (!isl_space_tuple_is_equal(space1, type1, space2, type2))
-		return isl_bool_false;
+	equal = isl_space_tuple_is_equal(space1, type1, space2, type2);
+	if (equal < 0 || !equal)
+		return equal;
 
 	if (!space1->ids && !space2->ids)
 		return isl_bool_true;
@@ -847,9 +1020,6 @@ static isl_bool match(__isl_keep isl_space *space1, enum isl_dim_type type1,
 isl_bool isl_space_has_equal_params(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2)
 {
-	if (!space1 || !space2)
-		return isl_bool_error;
-
 	return match(space1, isl_dim_param, space2, isl_dim_param);
 }
 
@@ -861,9 +1031,6 @@ isl_bool isl_space_has_equal_ids(__isl_keep isl_space *space1,
 {
 	isl_bool equal;
 
-	if (!space1 || !space2)
-		return isl_bool_error;
-
 	equal = match(space1, isl_dim_in, space2, isl_dim_in);
 	if (equal < 0 || !equal)
 		return equal;
@@ -873,9 +1040,6 @@ isl_bool isl_space_has_equal_ids(__isl_keep isl_space *space1,
 isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
 	__isl_keep isl_space *space2, enum isl_dim_type type2)
 {
-	if (!space1 || !space2)
-		return isl_bool_error;
-
 	return match(space1, type1, space2, type2);
 }
 
@@ -982,7 +1146,7 @@ __isl_give isl_space *isl_space_add_dims(__isl_take isl_space *space,
 __isl_give isl_space *isl_space_add_param_id(__isl_take isl_space *space,
 	__isl_take isl_id *id)
 {
-	int pos;
+	isl_size pos;
 
 	if (!space || !id)
 		goto error;
@@ -993,6 +1157,8 @@ __isl_give isl_space *isl_space_add_param_id(__isl_take isl_space *space,
 	}
 
 	pos = isl_space_dim(space, isl_dim_param);
+	if (pos < 0)
+		goto error;
 	space = isl_space_add_dims(space, isl_dim_param, 1);
 	space = isl_space_set_dim_id(space, isl_dim_param, pos, id);
 
@@ -1015,6 +1181,10 @@ static int valid_dim_type(enum isl_dim_type type)
 	}
 }
 
+#undef TYPE
+#define TYPE	isl_space
+#include "check_type_range_templ.c"
+
 /* Insert "n" dimensions of type "type" at position "pos".
  * If we are inserting parameters, then they are also inserted in
  * any nested spaces.
@@ -1024,7 +1194,6 @@ __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *space,
 {
 	isl_ctx *ctx;
 	isl_id **ids = NULL;
-	unsigned total;
 
 	if (!space)
 		return NULL;
@@ -1037,12 +1206,8 @@ __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *space,
 			"cannot insert dimensions of specified type",
 			goto error);
 
-	total = isl_space_dim(space, isl_dim_all);
-	if (total + n < total)
-		isl_die(ctx, isl_error_invalid,
-			"overflow in total number of dimensions",
-			return isl_space_free(space));
-	isl_assert(ctx, pos <= isl_space_dim(space, type), goto error);
+	if (isl_space_check_range(space, type, pos, 0) < 0)
+		return isl_space_free(space);
 
 	space = isl_space_cow(space);
 	if (!space)
@@ -1114,8 +1279,8 @@ __isl_give isl_space *isl_space_move_dims(__isl_take isl_space *space,
 	if (n == 0)
 		return space;
 
-	isl_assert(space->ctx, src_pos + n <= isl_space_dim(space, src_type),
-		goto error);
+	if (isl_space_check_range(space, src_type, src_pos, n) < 0)
+		return isl_space_free(space);
 
 	if (dst_type == src_type && dst_pos == src_pos)
 		return space;
@@ -1182,12 +1347,15 @@ __isl_give isl_space *isl_space_move_dims(__isl_take isl_space *space,
 		return space;
 
 	for (i = 0; i < 2; ++i) {
+		isl_space *nested;
+
 		if (!space->nested[i])
 			continue;
-		space->nested[i] = isl_space_replace_params(space->nested[i],
-							     space);
-		if (!space->nested[i])
-			goto error;
+		nested = isl_space_take_nested(space, i);
+		nested = isl_space_replace_params(nested, space);
+		space = isl_space_restore_nested(space, i, nested);
+		if (!space)
+			return NULL;
 	}
 
 	return space;
@@ -1216,7 +1384,7 @@ isl_stat isl_space_check_equal_params(__isl_keep isl_space *space1,
 __isl_give isl_space *isl_space_join(__isl_take isl_space *left,
 	__isl_take isl_space *right)
 {
-	isl_space *dim;
+	isl_space *space;
 
 	if (isl_space_check_equal_params(left, right) < 0)
 		goto error;
@@ -1225,31 +1393,32 @@ __isl_give isl_space *isl_space_join(__isl_take isl_space *left,
 		isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
 		goto error);
 
-	dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
-	if (!dim)
+	space = isl_space_alloc(left->ctx,
+				left->nparam, left->n_in, right->n_out);
+	if (!space)
 		goto error;
 
-	dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
-	dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
-	dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
+	space = copy_ids(space, isl_dim_param, 0, left, isl_dim_param);
+	space = copy_ids(space, isl_dim_in, 0, left, isl_dim_in);
+	space = copy_ids(space, isl_dim_out, 0, right, isl_dim_out);
 
-	if (dim && left->tuple_id[0] &&
-	    !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
+	if (space && left->tuple_id[0] &&
+	    !(space->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
 		goto error;
-	if (dim && right->tuple_id[1] &&
-	    !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
+	if (space && right->tuple_id[1] &&
+	    !(space->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
 		goto error;
-	if (dim && left->nested[0] &&
-	    !(dim->nested[0] = isl_space_copy(left->nested[0])))
+	if (space && left->nested[0] &&
+	    !(space->nested[0] = isl_space_copy(left->nested[0])))
 		goto error;
-	if (dim && right->nested[1] &&
-	    !(dim->nested[1] = isl_space_copy(right->nested[1])))
+	if (space && right->nested[1] &&
+	    !(space->nested[1] = isl_space_copy(right->nested[1])))
 		goto error;
 
 	isl_space_free(left);
 	isl_space_free(right);
 
-	return dim;
+	return space;
 error:
 	isl_space_free(left);
 	isl_space_free(right);
@@ -1468,11 +1637,8 @@ static __isl_give isl_space *range_factor_domain(__isl_take isl_space *space)
 __isl_give isl_space *isl_space_range_factor_domain(
 	__isl_take isl_space *space)
 {
-	if (!space)
-		return NULL;
-	if (!isl_space_range_is_wrapping(space))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"range not a product", return isl_space_free(space));
+	if (isl_space_check_range_is_wrapping(space) < 0)
+		return isl_space_free(space);
 
 	return range_factor_domain(space);
 }
@@ -1546,11 +1712,8 @@ static __isl_give isl_space *range_factor_range(__isl_take isl_space *space)
 __isl_give isl_space *isl_space_range_factor_range(
 	__isl_take isl_space *space)
 {
-	if (!space)
-		return NULL;
-	if (!isl_space_range_is_wrapping(space))
-		isl_die(isl_space_get_ctx(space), isl_error_invalid,
-			"range not a product", return isl_space_free(space));
+	if (isl_space_check_range_is_wrapping(space) < 0)
+		return isl_space_free(space);
 
 	return range_factor_range(space);
 }
@@ -1652,117 +1815,149 @@ static __isl_give isl_space *set_ids(__isl_take isl_space *dim,
 	return dim;
 }
 
-__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_reverse(__isl_take isl_space *space)
 {
 	unsigned t;
+	isl_bool equal;
 	isl_space *nested;
 	isl_id **ids = NULL;
 	isl_id *id;
 
-	if (!dim)
-		return NULL;
-	if (match(dim, isl_dim_in, dim, isl_dim_out))
-		return dim;
+	equal = match(space, isl_dim_in, space, isl_dim_out);
+	if (equal < 0)
+		return isl_space_free(space);
+	if (equal)
+		return space;
 
-	dim = isl_space_cow(dim);
-	if (!dim)
+	space = isl_space_cow(space);
+	if (!space)
 		return NULL;
 
-	id = dim->tuple_id[0];
-	dim->tuple_id[0] = dim->tuple_id[1];
-	dim->tuple_id[1] = id;
+	id = space->tuple_id[0];
+	space->tuple_id[0] = space->tuple_id[1];
+	space->tuple_id[1] = id;
 
-	nested = dim->nested[0];
-	dim->nested[0] = dim->nested[1];
-	dim->nested[1] = nested;
+	nested = space->nested[0];
+	space->nested[0] = space->nested[1];
+	space->nested[1] = nested;
 
-	if (dim->ids) {
-		int n_id = dim->n_in + dim->n_out;
-		ids = isl_alloc_array(dim->ctx, isl_id *, n_id);
+	if (space->ids) {
+		int n_id = space->n_in + space->n_out;
+		ids = isl_alloc_array(space->ctx, isl_id *, n_id);
 		if (n_id && !ids)
 			goto error;
-		get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
-		get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
+		get_ids(space, isl_dim_in, 0, space->n_in, ids);
+		get_ids(space, isl_dim_out, 0, space->n_out, ids + space->n_in);
 	}
 
-	t = dim->n_in;
-	dim->n_in = dim->n_out;
-	dim->n_out = t;
+	t = space->n_in;
+	space->n_in = space->n_out;
+	space->n_out = t;
 
-	if (dim->ids) {
-		dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
-		dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
+	if (space->ids) {
+		space = set_ids(space, isl_dim_out, 0, space->n_out, ids);
+		space = set_ids(space, isl_dim_in, 0, space->n_in,
+				ids + space->n_out);
 		free(ids);
 	}
 
-	return dim;
+	return space;
 error:
 	free(ids);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
-__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
+/* Given a space A -> (B -> C), return the corresponding space
+ * A -> (C -> B).
+ *
+ * If the range tuple is named, then the name is only preserved
+ * if B and C are equal tuples, in which case the output
+ * of this function is identical to the input.
+ */
+__isl_give isl_space *isl_space_range_reverse(__isl_take isl_space *space)
+{
+	isl_space *nested;
+	isl_bool equal;
+
+	if (isl_space_check_range_is_wrapping(space) < 0)
+		return isl_space_free(space);
+
+	nested = isl_space_peek_nested(space, 1);
+	equal = isl_space_tuple_is_equal(nested, isl_dim_in,
+					nested, isl_dim_out);
+	if (equal < 0)
+		return isl_space_free(space);
+
+	nested = isl_space_take_nested(space, 1);
+	nested = isl_space_reverse(nested);
+	space = isl_space_restore_nested(space, 1, nested);
+	if (!equal)
+		space = isl_space_reset_tuple_id(space, isl_dim_out);
+
+	return space;
+}
+
+__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *space,
 	enum isl_dim_type type, unsigned first, unsigned num)
 {
 	int i;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 
 	if (num == 0)
-		return isl_space_reset(dim, type);
+		return isl_space_reset(space, type);
 
 	if (!valid_dim_type(type))
-		isl_die(dim->ctx, isl_error_invalid,
+		isl_die(space->ctx, isl_error_invalid,
 			"cannot drop dimensions of specified type", goto error);
 
-	if (first + num > n(dim, type) || first + num < first)
-		isl_die(isl_space_get_ctx(dim), isl_error_invalid,
-			"index out of bounds", return isl_space_free(dim));
-	dim = isl_space_cow(dim);
-	if (!dim)
+	if (isl_space_check_range(space, type, first, num) < 0)
+		return isl_space_free(space);
+	space = isl_space_cow(space);
+	if (!space)
 		goto error;
-	if (dim->ids) {
-		dim = extend_ids(dim);
-		if (!dim)
+	if (space->ids) {
+		space = extend_ids(space);
+		if (!space)
 			goto error;
 		for (i = 0; i < num; ++i)
-			isl_id_free(get_id(dim, type, first + i));
-		for (i = first+num; i < n(dim, type); ++i)
-			set_id(dim, type, i - num, get_id(dim, type, i));
+			isl_id_free(get_id(space, type, first + i));
+		for (i = first+num; i < n(space, type); ++i)
+			set_id(space, type, i - num, get_id(space, type, i));
 		switch (type) {
 		case isl_dim_param:
-			get_ids(dim, isl_dim_in, 0, dim->n_in,
-				dim->ids + offset(dim, isl_dim_in) - num);
+			get_ids(space, isl_dim_in, 0, space->n_in,
+				space->ids + offset(space, isl_dim_in) - num);
 		case isl_dim_in:
-			get_ids(dim, isl_dim_out, 0, dim->n_out,
-				dim->ids + offset(dim, isl_dim_out) - num);
+			get_ids(space, isl_dim_out, 0, space->n_out,
+				space->ids + offset(space, isl_dim_out) - num);
 		default:
 			;
 		}
-		dim->n_id -= num;
+		space->n_id -= num;
 	}
 	switch (type) {
-	case isl_dim_param:	dim->nparam -= num; break;
-	case isl_dim_in:	dim->n_in -= num; break;
-	case isl_dim_out:	dim->n_out -= num; break;
+	case isl_dim_param:	space->nparam -= num; break;
+	case isl_dim_in:	space->n_in -= num; break;
+	case isl_dim_out:	space->n_out -= num; break;
 	default:		;
 	}
-	dim = isl_space_reset(dim, type);
+	space = isl_space_reset(space, type);
 	if (type == isl_dim_param) {
-		if (dim && dim->nested[0] &&
-		    !(dim->nested[0] = isl_space_drop_dims(dim->nested[0],
+		if (space && space->nested[0] &&
+		    !(space->nested[0] = isl_space_drop_dims(space->nested[0],
 						    isl_dim_param, first, num)))
 			goto error;
-		if (dim && dim->nested[1] &&
-		    !(dim->nested[1] = isl_space_drop_dims(dim->nested[1],
+		if (space && space->nested[1] &&
+		    !(space->nested[1] = isl_space_drop_dims(space->nested[1],
 						    isl_dim_param, first, num)))
 			goto error;
 	}
-	return dim;
+	return space;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -1782,6 +1977,18 @@ __isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
 	return isl_space_drop_dims(dim, isl_dim_out, first, n);
 }
 
+/* Remove all parameters from "space".
+ */
+__isl_give isl_space *isl_space_drop_all_params(__isl_take isl_space *space)
+{
+	isl_size nparam;
+
+	nparam = isl_space_dim(space, isl_dim_param);
+	if (nparam < 0)
+		return isl_space_free(space);
+	return isl_space_drop_dims(space, isl_dim_param, 0, nparam);
+}
+
 __isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
 {
 	if (!space)
@@ -1792,18 +1999,18 @@ __isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
 	return space;
 }
 
-__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *space)
 {
-	if (!dim)
+	if (!space)
 		return NULL;
-	if (!isl_space_is_set(dim))
-		isl_die(isl_space_get_ctx(dim), isl_error_invalid,
+	if (!isl_space_is_set(space))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
 			"not a set space", goto error);
-	dim = isl_space_reverse(dim);
-	dim = isl_space_reset(dim, isl_dim_out);
-	return dim;
+	space = isl_space_reverse(space);
+	space = isl_space_reset(space, isl_dim_out);
+	return space;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -1816,16 +2023,16 @@ __isl_give isl_space *isl_space_range(__isl_take isl_space *space)
 	return space;
 }
 
-__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_from_range(__isl_take isl_space *space)
 {
-	if (!dim)
+	if (!space)
 		return NULL;
-	if (!isl_space_is_set(dim))
-		isl_die(isl_space_get_ctx(dim), isl_error_invalid,
+	if (!isl_space_is_set(space))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
 			"not a set space", goto error);
-	return isl_space_reset(dim, isl_dim_in);
+	return isl_space_reset(space, isl_dim_in);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -1857,12 +2064,16 @@ __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_size n_in, n_out;
+
 	if (isl_space_is_params(space))
 		return space;
-	space = isl_space_drop_dims(space,
-			    isl_dim_in, 0, isl_space_dim(space, isl_dim_in));
-	space = isl_space_drop_dims(space,
-			    isl_dim_out, 0, isl_space_dim(space, isl_dim_out));
+	n_in = isl_space_dim(space, isl_dim_in);
+	n_out = isl_space_dim(space, isl_dim_out);
+	if (n_in < 0 || n_out < 0)
+		return isl_space_free(space);
+	space = isl_space_drop_dims(space, isl_dim_in, 0, n_in);
+	space = isl_space_drop_dims(space, isl_dim_out, 0, n_out);
 	space = mark_as_params(space);
 	return space;
 }
@@ -1880,30 +2091,273 @@ __isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
 	return NULL;
 }
 
-__isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
+/* Add an unnamed tuple of dimension "dim" to "space".
+ * This requires "space" to be a parameter or set space.
+ *
+ * In particular, if "space" is a parameter space, then return
+ * a set space with the given dimension.
+ * If "space" is a set space, then return a map space
+ * with "space" as domain and a range of the given dimension.
+ */
+__isl_give isl_space *isl_space_add_unnamed_tuple_ui(
+	__isl_take isl_space *space, unsigned dim)
+{
+	isl_bool is_params, is_set;
+
+	is_params = isl_space_is_params(space);
+	is_set = isl_space_is_set(space);
+	if (is_params < 0 || is_set < 0)
+		return isl_space_free(space);
+	if (!is_params && !is_set)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"cannot add tuple to map space",
+			return isl_space_free(space));
+	if (is_params)
+		space = isl_space_set_from_params(space);
+	else
+		space = isl_space_from_domain(space);
+	space = isl_space_add_dims(space, isl_dim_out, dim);
+	return space;
+}
+
+/* Add a tuple of dimension "dim" and with tuple identifier "tuple_id"
+ * to "space".
+ * This requires "space" to be a parameter or set space.
+ */
+__isl_give isl_space *isl_space_add_named_tuple_id_ui(
+	__isl_take isl_space *space, __isl_take isl_id *tuple_id, unsigned dim)
+{
+	space = isl_space_add_unnamed_tuple_ui(space, dim);
+	space = isl_space_set_tuple_id(space, isl_dim_out, tuple_id);
+	return space;
+}
+
+/* Check that the identifiers in "tuple" do not appear as parameters
+ * in "space".
+ */
+static isl_stat check_fresh_params(__isl_keep isl_space *space,
+	__isl_keep isl_multi_id *tuple)
+{
+	int i;
+	isl_size n;
+
+	n = isl_multi_id_size(tuple);
+	if (n < 0)
+		return isl_stat_error;
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+		int pos;
+
+		id = isl_multi_id_get_at(tuple, i);
+		if (!id)
+			return isl_stat_error;
+		pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
+		isl_id_free(id);
+		if (pos >= 0)
+			isl_die(isl_space_get_ctx(space), isl_error_invalid,
+				"parameters not unique", return isl_stat_error);
+	}
+
+	return isl_stat_ok;
+}
+
+/* Add the identifiers in "tuple" as parameters of "space"
+ * that are known to be fresh.
+ */
+static __isl_give isl_space *add_bind_params(__isl_take isl_space *space,
+	__isl_keep isl_multi_id *tuple)
+{
+	int i;
+	isl_size first, n;
+
+	first = isl_space_dim(space, isl_dim_param);
+	n = isl_multi_id_size(tuple);
+	if (first < 0 || n < 0)
+		return isl_space_free(space);
+	space = isl_space_add_dims(space, isl_dim_param, n);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+
+		id = isl_multi_id_get_at(tuple, i);
+		space = isl_space_set_dim_id(space,
+						isl_dim_param, first + i, id);
+	}
+
+	return space;
+}
+
+/* Internal function that removes the set tuple of "space",
+ * which is assumed to correspond to the range space of "tuple", and
+ * adds the identifiers in "tuple" as fresh parameters.
+ * In other words, the set dimensions of "space" are reinterpreted
+ * as parameters, but stay in the same global positions.
+ */
+__isl_give isl_space *isl_space_bind_set(__isl_take isl_space *space,
+	__isl_keep isl_multi_id *tuple)
+{
+	isl_space *tuple_space;
+
+	if (isl_space_check_is_set(space) < 0)
+		return isl_space_free(space);
+	tuple_space = isl_multi_id_peek_space(tuple);
+	if (isl_space_check_equal_tuples(tuple_space, space) < 0)
+		return isl_space_free(space);
+	if (check_fresh_params(space, tuple) < 0)
+		return isl_space_free(space);
+	space = isl_space_params(space);
+	space = add_bind_params(space, tuple);
+	return space;
+}
+
+/* Internal function that removes the domain tuple of the map space "space",
+ * which is assumed to correspond to the range space of "tuple", and
+ * adds the identifiers in "tuple" as fresh parameters.
+ * In other words, the domain dimensions of "space" are reinterpreted
+ * as parameters, but stay in the same global positions.
+ */
+__isl_give isl_space *isl_space_bind_map_domain(__isl_take isl_space *space,
+	__isl_keep isl_multi_id *tuple)
+{
+	isl_space *tuple_space;
+
+	if (isl_space_check_is_map(space) < 0)
+		return isl_space_free(space);
+	tuple_space = isl_multi_id_peek_space(tuple);
+	if (isl_space_check_domain_tuples(tuple_space, space) < 0)
+		return isl_space_free(space);
+	if (check_fresh_params(space, tuple) < 0)
+		return isl_space_free(space);
+	space = isl_space_range(space);
+	space = add_bind_params(space, tuple);
+	return space;
+}
+
+/* Internal function that, given a space of the form [A -> B] -> C and
+ * a tuple of identifiers in A, returns a space B -> C with
+ * the identifiers in "tuple" added as fresh parameters.
+ * In other words, the domain dimensions of the wrapped relation
+ * in the domain of "space" are reinterpreted
+ * as parameters, but stay in the same global positions.
+ */
+__isl_give isl_space *isl_space_bind_domain_wrapped_domain(
+	__isl_take isl_space *space, __isl_keep isl_multi_id *tuple)
+{
+	isl_space *tuple_space;
+
+	if (isl_space_check_is_map(space) < 0)
+		return isl_space_free(space);
+	tuple_space = isl_multi_id_peek_space(tuple);
+	if (isl_space_check_domain_wrapped_domain_tuples(tuple_space,
+							space) < 0)
+		  return isl_space_free(space);
+	if (check_fresh_params(space, tuple) < 0)
+		return isl_space_free(space);
+	space = isl_space_domain_factor_range(space);
+	space = add_bind_params(space, tuple);
+	return space;
+}
+
+/* Insert a domain tuple in "space" corresponding to the set space "domain".
+ * In particular, if "space" is a parameter space, then the result
+ * is the set space "domain" combined with the parameters of "space".
+ * If "space" is a set space, then the result
+ * is a map space with "domain" as domain and the original space as range.
+ */
+static __isl_give isl_space *isl_space_insert_domain(
+	__isl_take isl_space *space, __isl_take isl_space *domain)
+{
+	isl_bool is_params;
+
+	domain = isl_space_replace_params(domain, space);
+
+	is_params = isl_space_is_params(space);
+	if (is_params < 0) {
+		isl_space_free(domain);
+		space = isl_space_free(space);
+	} else if (is_params) {
+		isl_space_free(space);
+		space = domain;
+	} else {
+		space = isl_space_map_from_domain_and_range(domain, space);
+	}
+	return space;
+}
+
+/* Internal function that introduces a domain in "space"
+ * corresponding to the range space of "tuple".
+ * In particular, if "space" is a parameter space, then the result
+ * is a set space.  If "space" is a set space, then the result
+ * is a map space with the original space as range.
+ * Parameters that correspond to the identifiers in "tuple" are removed.
+ *
+ * The parameters are removed in reverse order (under the assumption
+ * that they appear in the same order in "multi") because
+ * it is slightly more efficient to remove parameters at the end.
+ *
+ * For pretty-printing purposes, the identifiers of the set dimensions
+ * of the introduced domain are set to the identifiers in "tuple".
+ */
+__isl_give isl_space *isl_space_unbind_params_insert_domain(
+	__isl_take isl_space *space, __isl_keep isl_multi_id *tuple)
+{
+	int i;
+	isl_size n;
+	isl_space *tuple_space;
+
+	n = isl_multi_id_size(tuple);
+	if (!space || n < 0)
+		return isl_space_free(space);
+	for (i = n - 1; i >= 0; --i) {
+		isl_id *id;
+		int pos;
+
+		id = isl_multi_id_get_id(tuple, i);
+		if (!id)
+			return isl_space_free(space);
+		pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
+		isl_id_free(id);
+		if (pos < 0)
+			continue;
+		space = isl_space_drop_dims(space, isl_dim_param, pos, 1);
+	}
+	tuple_space = isl_multi_id_get_space(tuple);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+
+		id = isl_multi_id_get_id(tuple, i);
+		tuple_space = isl_space_set_dim_id(tuple_space,
+						    isl_dim_set, i, id);
+	}
+	return isl_space_insert_domain(space, tuple_space);
+}
+
+__isl_give isl_space *isl_space_underlying(__isl_take isl_space *space,
 	unsigned n_div)
 {
 	int i;
+	isl_bool is_set;
 
-	if (!dim)
-		return NULL;
-	if (n_div == 0 &&
-	    dim->nparam == 0 && dim->n_in == 0 && dim->n_id == 0)
-		return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out);
-	dim = isl_space_cow(dim);
-	if (!dim)
+	is_set = isl_space_is_set(space);
+	if (is_set < 0)
+		return isl_space_free(space);
+	if (n_div == 0 && is_set &&
+	    space->nparam == 0 && space->n_in == 0 && space->n_id == 0)
+		return isl_space_reset(space, isl_dim_out);
+	space = isl_space_cow(space);
+	if (!space)
 		return NULL;
-	dim->n_out += dim->nparam + dim->n_in + n_div;
-	dim->nparam = 0;
-	dim->n_in = 0;
+	space->n_out += space->nparam + space->n_in + n_div;
+	space->nparam = 0;
+	space->n_in = 0;
 
-	for (i = 0; i < dim->n_id; ++i)
-		isl_id_free(get_id(dim, isl_dim_out, i));
-	dim->n_id = 0;
-	dim = isl_space_reset(dim, isl_dim_in);
-	dim = isl_space_reset(dim, isl_dim_out);
+	for (i = 0; i < space->n_id; ++i)
+		isl_id_free(get_id(space, isl_dim_out, i));
+	space->n_id = 0;
+	space = isl_space_reset(space, isl_dim_in);
+	space = isl_space_reset(space, isl_dim_out);
+	space = mark_as_set(space);
 
-	return dim;
+	return space;
 }
 
 /* Are the two spaces the same, including positions and names of parameters?
@@ -1924,7 +2378,7 @@ isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
 }
 
 /* Do the tuples of "space1" correspond to those of the domain of "space2"?
- * That is, is "space1" eqaul to the domain of "space2", ignoring parameters.
+ * That is, is "space1" equal to the domain of "space2", ignoring parameters.
  *
  * "space2" is allowed to be a set space, in which case "space1"
  * should be a parameter space.
@@ -1941,6 +2395,62 @@ isl_bool isl_space_has_domain_tuples(__isl_keep isl_space *space1,
 					space2, isl_dim_in);
 }
 
+/* Do the tuples of "space1" correspond to those of the range of "space2"?
+ * That is, is "space1" equal to the range of "space2", ignoring parameters.
+ *
+ * "space2" is allowed to be the space of a set,
+ * in which case it should be equal to "space1", ignoring parameters.
+ */
+isl_bool isl_space_has_range_tuples(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2)
+{
+	isl_bool is_set;
+
+	is_set = isl_space_is_set(space1);
+	if (is_set < 0 || !is_set)
+		return is_set;
+	return isl_space_tuple_is_equal(space1, isl_dim_set,
+					space2, isl_dim_out);
+}
+
+/* Check that the tuples of "space1" correspond to those
+ * of the domain of "space2".
+ * That is, check that "space1" is equal to the domain of "space2",
+ * ignoring parameters.
+ */
+isl_stat isl_space_check_domain_tuples(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2)
+{
+	isl_bool is_equal;
+
+	is_equal = isl_space_has_domain_tuples(space1, space2);
+	if (is_equal < 0)
+		return isl_stat_error;
+	if (!is_equal)
+		isl_die(isl_space_get_ctx(space1), isl_error_invalid,
+			"incompatible spaces", return isl_stat_error);
+
+	return isl_stat_ok;
+}
+
+/* Check that the tuples of "space1" correspond to those
+ * of the domain of the wrapped relation in the domain of "space2".
+ * That is, check that "space1" is equal to this domain,
+ * ignoring parameters.
+ */
+isl_stat isl_space_check_domain_wrapped_domain_tuples(
+	__isl_keep isl_space *space1, __isl_keep isl_space *space2)
+{
+	isl_space *domain;
+	isl_stat r;
+
+	domain = isl_space_unwrap(isl_space_domain(isl_space_copy(space2)));
+	r = isl_space_check_domain_tuples(space1, domain);
+	isl_space_free(domain);
+
+	return r;
+}
+
 /* Is space1 equal to the domain of space2?
  *
  * In the internal version we also allow space2 to be the space of a set,
@@ -1983,13 +2493,10 @@ isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
 
 	if (!space1 || !space2)
 		return isl_bool_error;
-	if (!isl_space_is_set(space1))
-		return isl_bool_false;
 	equal_params = isl_space_has_equal_params(space1, space2);
 	if (equal_params < 0 || !equal_params)
 		return equal_params;
-	return isl_space_tuple_is_equal(space1, isl_dim_set,
-					space2, isl_dim_out);
+	return isl_space_has_range_tuples(space1, space2);
 }
 
 /* Is space1 equal to the range of space2?
@@ -2120,15 +2627,17 @@ uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space)
 	return hash;
 }
 
-isl_bool isl_space_is_wrapping(__isl_keep isl_space *dim)
+/* Is "space" the space of a set wrapping a map space?
+ */
+isl_bool isl_space_is_wrapping(__isl_keep isl_space *space)
 {
-	if (!dim)
+	if (!space)
 		return isl_bool_error;
 
-	if (!isl_space_is_set(dim))
+	if (!isl_space_is_set(space))
 		return isl_bool_false;
 
-	return dim->nested[1] != NULL;
+	return isl_bool_ok(space->nested[1] != NULL);
 }
 
 /* Is "space" the space of a map where the domain is a wrapped map space?
@@ -2141,7 +2650,7 @@ isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space)
 	if (isl_space_is_set(space))
 		return isl_bool_false;
 
-	return space->nested[0] != NULL;
+	return isl_bool_ok(space->nested[0] != NULL);
 }
 
 /* Is "space" the space of a map where the range is a wrapped map space?
@@ -2154,7 +2663,7 @@ isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space)
 	if (isl_space_is_set(space))
 		return isl_bool_false;
 
-	return space->nested[1] != NULL;
+	return isl_bool_ok(space->nested[1] != NULL);
 }
 
 /* Is "space" a product of two spaces?
@@ -2177,48 +2686,48 @@ isl_bool isl_space_is_product(__isl_keep isl_space *space)
 	return isl_space_range_is_wrapping(space);
 }
 
-__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_wrap(__isl_take isl_space *space)
 {
 	isl_space *wrap;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	wrap = isl_space_set_alloc(dim->ctx,
-				    dim->nparam, dim->n_in + dim->n_out);
+	wrap = isl_space_set_alloc(space->ctx,
+				    space->nparam, space->n_in + space->n_out);
 
-	wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
-	wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
-	wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
+	wrap = copy_ids(wrap, isl_dim_param, 0, space, isl_dim_param);
+	wrap = copy_ids(wrap, isl_dim_set, 0, space, isl_dim_in);
+	wrap = copy_ids(wrap, isl_dim_set, space->n_in, space, isl_dim_out);
 
 	if (!wrap)
 		goto error;
 
-	wrap->nested[1] = dim;
+	wrap->nested[1] = space;
 
 	return wrap;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
-__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *space)
 {
 	isl_space *unwrap;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	if (!isl_space_is_wrapping(dim))
-		isl_die(dim->ctx, isl_error_invalid, "not a wrapping space",
+	if (!isl_space_is_wrapping(space))
+		isl_die(space->ctx, isl_error_invalid, "not a wrapping space",
 			goto error);
 
-	unwrap = isl_space_copy(dim->nested[1]);
-	isl_space_free(dim);
+	unwrap = isl_space_copy(space->nested[1]);
+	isl_space_free(space);
 
 	return unwrap;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -2239,12 +2748,16 @@ isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
 isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
 {
 	isl_bool nested;
+	isl_size n_in;
 
 	if (!space)
 		return isl_bool_error;
 	if (isl_space_is_set(space))
 		return isl_bool_true;
-	if (isl_space_dim(space, isl_dim_in) != 0)
+	n_in = isl_space_dim(space, isl_dim_in);
+	if (n_in < 0)
+		return isl_bool_error;
+	if (n_in != 0)
 		return isl_bool_false;
 	nested = isl_space_is_named_or_nested(space, isl_dim_in);
 	if (nested < 0 || nested)
@@ -2252,37 +2765,37 @@ isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
 	return isl_bool_true;
 }
 
-__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_reset(__isl_take isl_space *space,
 	enum isl_dim_type type)
 {
-	if (!isl_space_is_named_or_nested(dim, type))
-		return dim;
+	if (!isl_space_is_named_or_nested(space, type))
+		return space;
 
-	dim = isl_space_cow(dim);
-	if (!dim)
+	space = isl_space_cow(space);
+	if (!space)
 		return NULL;
 
-	isl_id_free(dim->tuple_id[type - isl_dim_in]);
-	dim->tuple_id[type - isl_dim_in] = NULL;
-	isl_space_free(dim->nested[type - isl_dim_in]);
-	dim->nested[type - isl_dim_in] = NULL;
+	isl_id_free(space->tuple_id[type - isl_dim_in]);
+	space->tuple_id[type - isl_dim_in] = NULL;
+	isl_space_free(space->nested[type - isl_dim_in]);
+	space->nested[type - isl_dim_in] = NULL;
 
-	return dim;
+	return space;
 }
 
-__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_flatten(__isl_take isl_space *space)
 {
-	if (!dim)
+	if (!space)
 		return NULL;
-	if (!dim->nested[0] && !dim->nested[1])
-		return dim;
+	if (!space->nested[0] && !space->nested[1])
+		return space;
 
-	if (dim->nested[0])
-		dim = isl_space_reset(dim, isl_dim_in);
-	if (dim && dim->nested[1])
-		dim = isl_space_reset(dim, isl_dim_out);
+	if (space->nested[0])
+		space = isl_space_reset(space, isl_dim_in);
+	if (space && space->nested[1])
+		space = isl_space_reset(space, isl_dim_out);
 
-	return dim;
+	return space;
 }
 
 __isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *space)
@@ -2310,6 +2823,7 @@ __isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *space)
 __isl_give isl_space *isl_space_replace_params(__isl_take isl_space *dst,
 	__isl_keep isl_space *src)
 {
+	isl_size dst_dim, src_dim;
 	isl_bool equal_params;
 	enum isl_dim_type type = isl_dim_param;
 
@@ -2321,22 +2835,27 @@ __isl_give isl_space *isl_space_replace_params(__isl_take isl_space *dst,
 
 	dst = isl_space_cow(dst);
 
-	if (!dst || !src)
+	dst_dim = isl_space_dim(dst, type);
+	src_dim = isl_space_dim(src, type);
+	if (dst_dim < 0 || src_dim < 0)
 		goto error;
 
-	dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type));
-	dst = isl_space_add_dims(dst, type, isl_space_dim(src, type));
+	dst = isl_space_drop_dims(dst, type, 0, dst_dim);
+	dst = isl_space_add_dims(dst, type, src_dim);
 	dst = copy_ids(dst, type, 0, src, type);
 
 	if (dst) {
 		int i;
 		for (i = 0; i <= 1; ++i) {
+			isl_space *nested;
+
 			if (!dst->nested[i])
 				continue;
-			dst->nested[i] = isl_space_replace_params(
-							dst->nested[i], src);
-			if (!dst->nested[i])
-				goto error;
+			nested = isl_space_take_nested(dst, i);
+			nested = isl_space_replace_params(nested, src);
+			dst = isl_space_restore_nested(dst, i, nested);
+			if (!dst)
+				return NULL;
 		}
 	}
 
@@ -2346,28 +2865,70 @@ __isl_give isl_space *isl_space_replace_params(__isl_take isl_space *dst,
 	return NULL;
 }
 
-/* Given a dimension specification "dim" of a set, create a dimension
- * specification for the lift of the set.  In particular, the result
- * is of the form [dim -> local[..]], with n_local variables in the
+/* Given two tuples ("dst_type" in "dst" and "src_type" in "src")
+ * of the same size, check if any of the dimensions in the "dst" tuple
+ * have no identifier, while the corresponding dimensions in "src"
+ * does have an identifier,
+ * If so, copy the identifier over to "dst".
+ */
+__isl_give isl_space *isl_space_copy_ids_if_unset(__isl_take isl_space *dst,
+	enum isl_dim_type dst_type, __isl_keep isl_space *src,
+	enum isl_dim_type src_type)
+{
+	int i;
+	isl_size n;
+
+	n = isl_space_dim(dst, dst_type);
+	if (n < 0)
+		return isl_space_free(dst);
+	for (i = 0; i < n; ++i) {
+		isl_bool set;
+		isl_id *id;
+
+		set = isl_space_has_dim_id(dst, dst_type, i);
+		if (set < 0)
+			return isl_space_free(dst);
+		if (set)
+			continue;
+
+		set = isl_space_has_dim_id(src, src_type, i);
+		if (set < 0)
+			return isl_space_free(dst);
+		if (!set)
+			continue;
+
+		id = isl_space_get_dim_id(src, src_type, i);
+		dst = isl_space_set_dim_id(dst, dst_type, i, id);
+	}
+
+	return dst;
+}
+
+/* Given a space "space" of a set, create a space
+ * for the lift of the set.  In particular, the result
+ * is of the form lifted[space -> local[..]], with n_local variables in the
  * range of the wrapped map.
  */
-__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local)
+__isl_give isl_space *isl_space_lift(__isl_take isl_space *space,
+	unsigned n_local)
 {
-	isl_space *local_dim;
+	isl_space *local_space;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 
-	local_dim = isl_space_dup(dim);
-	local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out);
-	local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local);
-	local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local");
-	dim = isl_space_join(isl_space_from_domain(dim),
-			    isl_space_from_range(local_dim));
-	dim = isl_space_wrap(dim);
-	dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted");
+	local_space = isl_space_dup(space);
+	local_space = isl_space_drop_dims(local_space, isl_dim_set, 0,
+					space->n_out);
+	local_space = isl_space_add_dims(local_space, isl_dim_set, n_local);
+	local_space = isl_space_set_tuple_name(local_space,
+						isl_dim_set, "local");
+	space = isl_space_join(isl_space_from_domain(space),
+			    isl_space_from_range(local_space));
+	space = isl_space_wrap(space);
+	space = isl_space_set_tuple_name(space, isl_dim_set, "lifted");
 
-	return dim;
+	return space;
 }
 
 isl_bool isl_space_can_zip(__isl_keep isl_space *space)
@@ -2382,19 +2943,19 @@ isl_bool isl_space_can_zip(__isl_keep isl_space *space)
 	return isl_space_is_product(space);
 }
 
-__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
+__isl_give isl_space *isl_space_zip(__isl_take isl_space *space)
 {
 	isl_space *dom, *ran;
 	isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
 
-	if (!isl_space_can_zip(dim))
-		isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
+	if (!isl_space_can_zip(space))
+		isl_die(space->ctx, isl_error_invalid, "space cannot be zipped",
 			goto error);
 
-	if (!dim)
+	if (!space)
 		return NULL;
-	dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim)));
-	ran = isl_space_unwrap(isl_space_range(dim));
+	dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
+	ran = isl_space_unwrap(isl_space_range(space));
 	dom_dom = isl_space_domain(isl_space_copy(dom));
 	dom_ran = isl_space_range(dom);
 	ran_dom = isl_space_domain(isl_space_copy(ran));
@@ -2406,19 +2967,16 @@ __isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
 	return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
 			    isl_space_from_range(isl_space_wrap(ran)));
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
 /* Can we apply isl_space_curry to "space"?
- * That is, does it have a nested relation in its domain?
+ * That is, does is it have a map space with a nested relation in its domain?
  */
 isl_bool isl_space_can_curry(__isl_keep isl_space *space)
 {
-	if (!space)
-		return isl_bool_error;
-
-	return !!space->nested[0];
+	return isl_space_domain_is_wrapping(space);
 }
 
 /* Given a space (A -> B) -> C, return the corresponding space
@@ -2470,6 +3028,8 @@ isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
  */
 __isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
 {
+	isl_space *nested;
+
 	if (!space)
 		return NULL;
 
@@ -2478,25 +3038,19 @@ __isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
 			"space range cannot be curried",
 			return isl_space_free(space));
 
-	space = isl_space_cow(space);
-	if (!space)
-		return NULL;
-	space->nested[1] = isl_space_curry(space->nested[1]);
-	if (!space->nested[1])
-		return isl_space_free(space);
+	nested = isl_space_take_nested(space, 1);
+	nested = isl_space_curry(nested);
+	space = isl_space_restore_nested(space, 1, nested);
 
 	return space;
 }
 
 /* Can we apply isl_space_uncurry to "space"?
- * That is, does it have a nested relation in its range?
+ * That is, does it have a map space with a nested relation in its range?
  */
 isl_bool isl_space_can_uncurry(__isl_keep isl_space *space)
 {
-	if (!space)
-		return isl_bool_error;
-
-	return !!space->nested[1];
+	return isl_space_range_is_wrapping(space);
 }
 
 /* Given a space A -> (B -> C), return the corresponding space
@@ -2589,12 +3143,16 @@ __isl_give isl_space *isl_space_align_params(__isl_take isl_space *space1,
 __isl_give isl_space *isl_space_extend_domain_with_range(
 	__isl_take isl_space *space, __isl_take isl_space *model)
 {
+	isl_size n_out;
+
 	if (!model)
 		goto error;
 
 	space = isl_space_from_domain(space);
-	space = isl_space_add_dims(space, isl_dim_out,
-				    isl_space_dim(model, isl_dim_out));
+	n_out = isl_space_dim(model, isl_dim_out);
+	if (n_out < 0)
+		goto error;
+	space = isl_space_add_dims(space, isl_dim_out, n_out);
 	if (isl_space_has_tuple_id(model, isl_dim_out))
 		space = isl_space_set_tuple_id(space, isl_dim_out,
 				isl_space_get_tuple_id(model, isl_dim_out));
@@ -2602,10 +3160,12 @@ __isl_give isl_space *isl_space_extend_domain_with_range(
 		goto error;
 	if (model->nested[1]) {
 		isl_space *nested = isl_space_copy(model->nested[1]);
-		int n_nested, n_space;
+		isl_size n_nested, n_space;
 		nested = isl_space_align_params(nested, isl_space_copy(space));
 		n_nested = isl_space_dim(nested, isl_dim_param);
 		n_space = isl_space_dim(space, isl_dim_param);
+		if (n_nested < 0 || n_space < 0)
+			goto error;
 		if (n_nested > n_space)
 			nested = isl_space_drop_dims(nested, isl_dim_param,
 						n_space, n_nested - n_space);
@@ -2629,11 +3189,15 @@ static int isl_space_cmp_type(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2, enum isl_dim_type type)
 {
 	int cmp;
+	isl_size dim1, dim2;
 	isl_space *nested1, *nested2;
 
-	if (isl_space_dim(space1, type) != isl_space_dim(space2, type))
-		return isl_space_dim(space1, type) -
-			isl_space_dim(space2, type);
+	dim1 = isl_space_dim(space1, type);
+	dim2 = isl_space_dim(space2, type);
+	if (dim1 < 0 || dim2 < 0)
+		return 0;
+	if (dim1 != dim2)
+		return dim1 - dim2;
 
 	cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
 	if (cmp != 0)

diff  --git a/polly/lib/External/isl/isl_space_private.h b/polly/lib/External/isl/isl_space_private.h
index 141d8357069d..d66bdc2edc82 100644
--- a/polly/lib/External/isl/isl_space_private.h
+++ b/polly/lib/External/isl/isl_space_private.h
@@ -22,9 +22,9 @@ struct isl_space {
 	isl_id **ids;
 };
 
-__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_cow(__isl_take isl_space *space);
 
-__isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_underlying(__isl_take isl_space *space,
 	unsigned n_div);
 
 uint32_t isl_space_get_tuple_hash(__isl_keep isl_space *space);
@@ -33,13 +33,24 @@ uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space);
 
 isl_bool isl_space_has_domain_tuples(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2);
+isl_bool isl_space_has_range_tuples(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2);
+isl_stat isl_space_check_domain_tuples(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2);
 isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2);
 isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2);
+isl_stat isl_space_check_domain_wrapped_domain_tuples(
+	__isl_keep isl_space *space1, __isl_keep isl_space *space2);
 
+isl_size isl_space_wrapped_dim(__isl_keep isl_space *space,
+	enum isl_dim_type outer, enum isl_dim_type inner);
 unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type);
 
+isl_stat isl_space_check_range(__isl_keep isl_space *space,
+	enum isl_dim_type type, unsigned first, unsigned n);
+isl_stat isl_space_check_is_set(__isl_keep isl_space *space);
 isl_bool isl_space_may_be_set(__isl_keep isl_space *space);
 isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
 	enum isl_dim_type type);
@@ -49,17 +60,33 @@ isl_bool isl_space_has_named_params(__isl_keep isl_space *space);
 isl_stat isl_space_check_named_params(__isl_keep isl_space *space);
 isl_stat isl_space_check_equal_params(__isl_keep isl_space *space1,
 	__isl_keep isl_space *space2);
-__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
+isl_stat isl_space_check_equal_tuples(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2);
+__isl_give isl_space *isl_space_reset(__isl_take isl_space *space,
 	enum isl_dim_type type);
-__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_flatten(__isl_take isl_space *space);
+
+isl_stat isl_space_check_range_is_wrapping(__isl_keep isl_space *space);
 
 __isl_give isl_space *isl_space_replace_params(__isl_take isl_space *dst,
 	__isl_keep isl_space *src);
+__isl_give isl_space *isl_space_copy_ids_if_unset(__isl_take isl_space *dst,
+	enum isl_dim_type dst_type, __isl_keep isl_space *src,
+	enum isl_dim_type src_type);
 
-__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local);
+__isl_give isl_space *isl_space_lift(__isl_take isl_space *space,
+	unsigned n_local);
 
 __isl_give isl_space *isl_space_extend_domain_with_range(
 	__isl_take isl_space *domain, __isl_take isl_space *model);
+__isl_give isl_space *isl_space_bind_set(__isl_take isl_space *space,
+	__isl_keep isl_multi_id *tuple);
+__isl_give isl_space *isl_space_bind_map_domain(__isl_take isl_space *space,
+	__isl_keep isl_multi_id *tuple);
+__isl_give isl_space *isl_space_bind_domain_wrapped_domain(
+	__isl_take isl_space *space, __isl_keep isl_multi_id *tuple);
+__isl_give isl_space *isl_space_unbind_params_insert_domain(
+	__isl_take isl_space *space, __isl_keep isl_multi_id *tuple);
 
 int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2);
 

diff  --git a/polly/lib/External/isl/isl_srcdir.c.in b/polly/lib/External/isl/isl_srcdir.c.in
index 38e30c5e0933..7f39904074b5 100644
--- a/polly/lib/External/isl/isl_srcdir.c.in
+++ b/polly/lib/External/isl/isl_srcdir.c.in
@@ -1 +1 @@
-static const char *srcdir = "@srcdir@";
+static const char *srcdir = "@OS_SRCDIR@";

diff  --git a/polly/lib/External/isl/isl_stream.c b/polly/lib/External/isl/isl_stream.c
index beb06a64539d..5f2732b31d77 100644
--- a/polly/lib/External/isl/isl_stream.c
+++ b/polly/lib/External/isl/isl_stream.c
@@ -20,11 +20,11 @@ struct isl_keyword {
 	enum isl_token_type	type;
 };
 
-static int same_name(const void *entry, const void *val)
+static isl_bool same_name(const void *entry, const void *val)
 {
 	const struct isl_keyword *keyword = (const struct isl_keyword *)entry;
 
-	return !strcmp(keyword->name, val);
+	return isl_bool_ok(!strcmp(keyword->name, val));
 }
 
 enum isl_token_type isl_stream_register_keyword(__isl_keep isl_stream *s,
@@ -345,7 +345,9 @@ static enum isl_token_type check_keywords(__isl_keep isl_stream *s)
 	name_hash = isl_hash_string(isl_hash_init(), s->buffer);
 	entry = isl_hash_table_find(s->ctx, s->keywords, name_hash, same_name,
 					s->buffer, 0);
-	if (entry) {
+	if (!entry)
+		return ISL_TOKEN_ERROR;
+	if (entry != isl_hash_table_entry_none) {
 		keyword = entry->data;
 		return keyword->type;
 	}
@@ -617,13 +619,19 @@ static struct isl_token *next_token(__isl_keep isl_stream *s, int same_line)
 		tok = isl_token_new(s->ctx, line, col, old_line != line);
 		if (!tok)
 			return NULL;
-		if ((c = isl_stream_getc(s)) != '\\' && c != -1) {
-			tok->type = (enum isl_token_type) '/';
-			isl_stream_ungetc(s, c);
-		} else {
+		if ((c = isl_stream_getc(s)) == '\\') {
 			tok->u.s = strdup("/\\");
 			tok->type = ISL_TOKEN_AND;
+			return tok;
+		} else if (c == '/') {
+			tok->u.s = strdup("//");
+			tok->type = ISL_TOKEN_INT_DIV;
+			return tok;
+		} else {
+			tok->type = (enum isl_token_type) '/';
 		}
+		if (c != -1)
+			isl_stream_ungetc(s, c);
 		return tok;
 	}
 	if (c == '\\') {

diff  --git a/polly/lib/External/isl/isl_stride.c b/polly/lib/External/isl/isl_stride.c
index 8f91cfe23e23..2d1c027062d7 100644
--- a/polly/lib/External/isl/isl_stride.c
+++ b/polly/lib/External/isl/isl_stride.c
@@ -227,7 +227,8 @@ static isl_stat set_stride(struct isl_detect_stride_data *data,
 static isl_stat detect_stride(__isl_take isl_constraint *c, void *user)
 {
 	struct isl_detect_stride_data *data = user;
-	int i, n_div;
+	int i;
+	isl_size n_div;
 	isl_ctx *ctx;
 	isl_stat r = isl_stat_ok;
 	isl_val *v, *stride, *m;
@@ -242,9 +243,11 @@ static isl_stat detect_stride(__isl_take isl_constraint *c, void *user)
 		return isl_stat_ok;
 	}
 
+	n_div = isl_constraint_dim(c, isl_dim_div);
+	if (n_div < 0)
+		goto error;
 	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);
@@ -371,12 +374,15 @@ __isl_give isl_stride_info *isl_map_get_range_stride_info(
 {
 	isl_stride_info *si;
 	isl_set *set;
+	isl_size n_in;
 
+	n_in = isl_map_dim(map, isl_dim_in);
+	if (n_in < 0)
+		return NULL;
 	map = isl_map_copy(map);
 	map = isl_map_project_onto(map, isl_dim_out, pos, 1);
-	pos = isl_map_dim(map, isl_dim_in);
 	set = isl_map_wrap(map);
-	si = isl_set_get_stride_info(set, pos);
+	si = isl_set_get_stride_info(set, n_in);
 	isl_set_free(set);
 	if (!si)
 		return NULL;

diff  --git a/polly/lib/External/isl/isl_tab.c b/polly/lib/External/isl/isl_tab.c
index 0fb9e34e2068..1cb016a0ecc5 100644
--- a/polly/lib/External/isl/isl_tab.c
+++ b/polly/lib/External/isl/isl_tab.c
@@ -2116,7 +2116,7 @@ static int add_zero_row(struct isl_tab *tab)
  * one more element in the constraint array are available in the tableau.
  * If tab->bmap is set, then two rows are needed instead of one.
  */
-int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
+isl_stat isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
 {
 	struct isl_tab_undo *snap = NULL;
 	struct isl_tab_var *var;
@@ -2126,8 +2126,8 @@ int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
 	isl_int cst;
 
 	if (!tab)
-		return -1;
-	isl_assert(tab->mat->ctx, !tab->M, return -1);
+		return isl_stat_error;
+	isl_assert(tab->mat->ctx, !tab->M, return isl_stat_error);
 
 	if (tab->need_undo)
 		snap = isl_tab_snap(tab);
@@ -2143,7 +2143,7 @@ int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
 		isl_int_clear(cst);
 	}
 	if (r < 0)
-		return -1;
+		return isl_stat_error;
 
 	var = &tab->con[r];
 	row = var->index;
@@ -2156,16 +2156,16 @@ int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
 	if (tab->bmap) {
 		tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
 		if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
-			return -1;
+			return isl_stat_error;
 		isl_seq_neg(eq, eq, 1 + tab->n_var);
 		tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
 		isl_seq_neg(eq, eq, 1 + tab->n_var);
 		if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
-			return -1;
+			return isl_stat_error;
 		if (!tab->bmap)
-			return -1;
+			return isl_stat_error;
 		if (add_zero_row(tab) < 0)
-			return -1;
+			return isl_stat_error;
 	}
 
 	sgn = isl_int_sgn(tab->mat->row[row][1]);
@@ -2180,22 +2180,22 @@ int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
 	if (sgn < 0) {
 		sgn = sign_of_max(tab, var);
 		if (sgn < -1)
-			return -1;
+			return isl_stat_error;
 		if (sgn < 0) {
 			if (isl_tab_mark_empty(tab) < 0)
-				return -1;
-			return 0;
+				return isl_stat_error;
+			return isl_stat_ok;
 		}
 	}
 
 	var->is_nonneg = 1;
 	if (to_col(tab, var) < 0)
-		return -1;
+		return isl_stat_error;
 	var->is_nonneg = 0;
 	if (isl_tab_kill_col(tab, var->index) < 0)
-		return -1;
+		return isl_stat_error;
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Construct and return an inequality that expresses an upper bound
@@ -2208,16 +2208,17 @@ int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
  *
  *	m d <= e
  */
-static struct isl_vec *ineq_for_div(struct isl_basic_map *bmap, unsigned div)
+static __isl_give isl_vec *ineq_for_div(__isl_keep isl_basic_map *bmap,
+	unsigned div)
 {
-	unsigned total;
+	isl_size total;
 	unsigned div_pos;
 	struct isl_vec *ineq;
 
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return NULL;
 
-	total = isl_basic_map_total_dim(bmap);
 	div_pos = 1 + total - bmap->n_div + div;
 
 	ineq = isl_vec_alloc(bmap->ctx, 1 + total);
@@ -2247,11 +2248,13 @@ static struct isl_vec *ineq_for_div(struct isl_basic_map *bmap, unsigned div)
 static isl_stat add_div_constraints(struct isl_tab *tab, unsigned div,
 	isl_stat (*add_ineq)(void *user, isl_int *), void *user)
 {
-	unsigned total;
+	isl_size total;
 	unsigned div_pos;
 	struct isl_vec *ineq;
 
-	total = isl_basic_map_total_dim(tab->bmap);
+	total = isl_basic_map_dim(tab->bmap, isl_dim_all);
+	if (total < 0)
+		return isl_stat_error;
 	div_pos = 1 + total - tab->bmap->n_div + div;
 
 	ineq = ineq_for_div(tab->bmap, div);
@@ -2331,7 +2334,8 @@ int isl_tab_insert_div(struct isl_tab *tab, int pos, __isl_keep isl_vec *div,
 {
 	int r;
 	int nonneg;
-	int n_div, o_div;
+	isl_size n_div;
+	int o_div;
 
 	if (!tab || !div)
 		return -1;
@@ -2340,8 +2344,9 @@ int isl_tab_insert_div(struct isl_tab *tab, int pos, __isl_keep isl_vec *div,
 		isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
 			"unexpected size", return -1);
 
-	isl_assert(tab->mat->ctx, tab->bmap, return -1);
 	n_div = isl_basic_map_dim(tab->bmap, isl_dim_div);
+	if (n_div < 0)
+		return -1;
 	o_div = tab->n_var - n_div;
 	if (pos < o_div || pos > tab->n_var)
 		isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
@@ -2392,12 +2397,12 @@ __isl_give struct isl_tab *isl_tab_from_basic_map(
 {
 	int i;
 	struct isl_tab *tab;
+	isl_size total;
 
-	if (!bmap)
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
 		return NULL;
-	tab = isl_tab_alloc(bmap->ctx,
-			    isl_basic_map_total_dim(bmap) + bmap->n_ineq + 1,
-			    isl_basic_map_total_dim(bmap), 0);
+	tab = isl_tab_alloc(bmap->ctx, total + bmap->n_ineq + 1, total, 0);
 	if (!tab)
 		return NULL;
 	tab->preserve = track;
@@ -2441,14 +2446,16 @@ struct isl_tab *isl_tab_from_recession_cone(__isl_keep isl_basic_set *bset,
 	isl_int cst;
 	int i;
 	struct isl_tab *tab;
-	unsigned offset = 0;
+	isl_size offset = 0;
+	isl_size total;
 
-	if (!bset)
-		return NULL;
+	total = isl_basic_set_dim(bset, isl_dim_all);
 	if (parametric)
 		offset = isl_basic_set_dim(bset, isl_dim_param);
+	if (total < 0 || offset < 0)
+		return NULL;
 	tab = isl_tab_alloc(bset->ctx, bset->n_eq + bset->n_ineq,
-				isl_basic_set_total_dim(bset) - offset, 0);
+				total - offset, 0);
 	if (!tab)
 		return NULL;
 	tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL);
@@ -2750,6 +2757,18 @@ static isl_stat cut_to_hyperplane(struct isl_tab *tab, struct isl_tab_var *var)
 	return isl_stat_ok;
 }
 
+/* Check that "con" is a valid constraint position for "tab".
+ */
+static isl_stat isl_tab_check_con(struct isl_tab *tab, int con)
+{
+	if (!tab)
+		return isl_stat_error;
+	if (con < 0 || con >= tab->n_con)
+		isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
+			"position out of bounds", return isl_stat_error);
+	return isl_stat_ok;
+}
+
 /* Given a tableau "tab" and an inequality constraint "con" of the tableau,
  * relax the inequality by one.  That is, the inequality r >= 0 is replaced
  * by r' = r + 1 >= 0.
@@ -3037,6 +3056,30 @@ static int update_con_after_move(struct isl_tab *tab, int i, int old)
 	return 0;
 }
 
+/* Interchange constraints "con1" and "con2" in "tab".
+ * In particular, interchange the contents of these entries in tab->con.
+ * Since tab->col_var and tab->row_var point back into this array,
+ * they need to be updated accordingly.
+ */
+isl_stat isl_tab_swap_constraints(struct isl_tab *tab, int con1, int con2)
+{
+	struct isl_tab_var var;
+
+	if (isl_tab_check_con(tab, con1) < 0 ||
+	    isl_tab_check_con(tab, con2) < 0)
+		return isl_stat_error;
+
+	var = tab->con[con1];
+	tab->con[con1] = tab->con[con2];
+	if (update_con_after_move(tab, con1, con2) < 0)
+		return isl_stat_error;
+	tab->con[con2] = var;
+	if (update_con_after_move(tab, con2, con1) < 0)
+		return isl_stat_error;
+
+	return isl_stat_ok;
+}
+
 /* Rotate the "n" constraints starting at "first" to the right,
  * putting the last constraint in the position of the first constraint.
  */
@@ -3062,6 +3105,77 @@ static int rotate_constraints(struct isl_tab *tab, int first, int n)
 	return 0;
 }
 
+/* Drop the "n" entries starting at position "first" in tab->con, moving all
+ * subsequent entries down.
+ * Since some of the entries of tab->row_var and tab->col_var contain
+ * indices into this array, they have to be updated accordingly.
+ */
+static isl_stat con_drop_entries(struct isl_tab *tab,
+	unsigned first, unsigned n)
+{
+	int i;
+
+	if (first + n > tab->n_con || first + n < first)
+		isl_die(isl_tab_get_ctx(tab), isl_error_internal,
+			"invalid range", return isl_stat_error);
+
+	tab->n_con -= n;
+
+	for (i = first; i < tab->n_con; ++i) {
+		tab->con[i] = tab->con[i + n];
+		if (update_con_after_move(tab, i, i + n) < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* isl_basic_map_gauss5 callback that gets called when
+ * two (equality) constraints "a" and "b" get interchanged
+ * in the basic map.  Perform the same interchange in "tab".
+ */
+static isl_stat swap_eq(unsigned a, unsigned b, void *user)
+{
+	struct isl_tab *tab = user;
+
+	return isl_tab_swap_constraints(tab, a, b);
+}
+
+/* isl_basic_map_gauss5 callback that gets called when
+ * the final "n" equality constraints get removed.
+ * As a special case, if "n" is equal to the total number
+ * of equality constraints, then this means the basic map
+ * turned out to be empty.
+ * Drop the same number of equality constraints from "tab" or
+ * mark it empty in the special case.
+ */
+static isl_stat drop_eq(unsigned n, void *user)
+{
+	struct isl_tab *tab = user;
+
+	if (tab->n_eq == n)
+		return isl_tab_mark_empty(tab);
+
+	tab->n_eq -= n;
+	return con_drop_entries(tab, tab->n_eq, n);
+}
+
+/* If "bmap" has more than a single reference, then call
+ * isl_basic_map_gauss on it, updating "tab" accordingly.
+ */
+static __isl_give isl_basic_map *gauss_if_shared(__isl_take isl_basic_map *bmap,
+	struct isl_tab *tab)
+{
+	isl_bool single;
+
+	single = isl_basic_map_has_single_reference(bmap);
+	if (single < 0)
+		return isl_basic_map_free(bmap);
+	if (single)
+		return bmap;
+	return isl_basic_map_gauss5(bmap, NULL, &swap_eq, &drop_eq, tab);
+}
+
 /* Make the equalities that are implicit in "bmap" but that have been
  * detected in the corresponding "tab" explicit in "bmap" and update
  * "tab" to reflect the new order of the constraints.
@@ -3088,20 +3202,25 @@ static int rotate_constraints(struct isl_tab *tab, int first, int n)
  * If "tab" contains any constraints that are not in "bmap" then they
  * appear after those in "bmap" and they should be left untouched.
  *
- * Note that this function leaves "bmap" in a temporary state
- * as it does not call isl_basic_map_gauss.  Calling this function
- * is the responsibility of the caller.
+ * Note that this function only calls isl_basic_map_gauss
+ * (in case some equality constraints got detected)
+ * if "bmap" has more than one reference.
+ * If it only has a single reference, then it is left in a temporary state,
+ * because the caller may require this state.
+ * Calling isl_basic_map_gauss is then the responsibility of the caller.
  */
 __isl_give isl_basic_map *isl_tab_make_equalities_explicit(struct isl_tab *tab,
 	__isl_take isl_basic_map *bmap)
 {
 	int i;
+	unsigned n_eq;
 
 	if (!tab || !bmap)
 		return isl_basic_map_free(bmap);
 	if (tab->empty)
 		return bmap;
 
+	n_eq = tab->n_eq;
 	for (i = bmap->n_ineq - 1; i >= 0; --i) {
 		if (!isl_tab_is_equality(tab, bmap->n_eq + i))
 			continue;
@@ -3114,6 +3233,9 @@ __isl_give isl_basic_map *isl_tab_make_equalities_explicit(struct isl_tab *tab,
 		tab->n_eq++;
 	}
 
+	if (n_eq != tab->n_eq)
+		bmap = gauss_if_shared(bmap, tab);
+
 	return bmap;
 }
 
@@ -3313,11 +3435,8 @@ enum isl_lp_result isl_tab_min(struct isl_tab *tab,
  */
 int isl_tab_is_redundant(struct isl_tab *tab, int con)
 {
-	if (!tab)
+	if (isl_tab_check_con(tab, con) < 0)
 		return -1;
-	if (con < 0 || con >= tab->n_con)
-		isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
-			"position out of bounds", return -1);
 	if (tab->con[con].is_zero)
 		return 0;
 	if (tab->con[con].is_redundant)
@@ -3579,7 +3698,7 @@ isl_bool isl_tab_need_undo(struct isl_tab *tab)
 	if (!tab)
 		return isl_bool_error;
 
-	return tab->need_undo;
+	return isl_bool_ok(tab->need_undo);
 }
 
 /* Remove all tracking of undo information from "tab", invalidating
@@ -3759,8 +3878,12 @@ isl_stat isl_tab_restore_redundant(struct isl_tab *tab)
 static isl_stat drop_bmap_div(struct isl_tab *tab, int pos)
 {
 	int off;
+	isl_size n_div;
 
-	off = tab->n_var - isl_basic_map_dim(tab->bmap, isl_dim_div);
+	n_div = isl_basic_map_dim(tab->bmap, isl_dim_div);
+	if (n_div < 0)
+		return isl_stat_error;
+	off = tab->n_var - n_div;
 	if (isl_basic_map_drop_div(tab->bmap, pos - off) < 0)
 		return isl_stat_error;
 	if (tab->samples) {
@@ -3870,9 +3993,11 @@ static isl_stat perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
 	case isl_tab_undo_unrestrict:
 		return perform_undo_var(tab, undo);
 	case isl_tab_undo_bmap_eq:
-		return isl_basic_map_free_equality(tab->bmap, 1);
+		tab->bmap = isl_basic_map_free_equality(tab->bmap, 1);
+		return tab->bmap ? isl_stat_ok : isl_stat_error;
 	case isl_tab_undo_bmap_ineq:
-		return isl_basic_map_free_inequality(tab->bmap, 1);
+		tab->bmap = isl_basic_map_free_inequality(tab->bmap, 1);
+		return tab->bmap ? isl_stat_ok : isl_stat_error;
 	case isl_tab_undo_bmap_div:
 		return drop_bmap_div(tab, undo->u.var_index);
 	case isl_tab_undo_saved_basis:
@@ -3896,12 +4021,12 @@ static isl_stat perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
 /* Return the tableau to the state it was in when the snapshot "snap"
  * was taken.
  */
-int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap)
+isl_stat isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap)
 {
 	struct isl_tab_undo *undo, *next;
 
 	if (!tab)
-		return -1;
+		return isl_stat_error;
 
 	tab->in_undo = 1;
 	for (undo = tab->top; undo && undo != &tab->bottom; undo = next) {
@@ -3912,15 +4037,15 @@ int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap)
 			tab->top = undo;
 			free_undo(tab);
 			tab->in_undo = 0;
-			return -1;
+			return isl_stat_error;
 		}
 		free_undo_record(undo);
 	}
 	tab->in_undo = 0;
 	tab->top = undo;
 	if (!undo)
-		return -1;
-	return 0;
+		return isl_stat_error;
+	return isl_stat_ok;
 }
 
 /* The given row "row" represents an inequality violated by all

diff  --git a/polly/lib/External/isl/isl_tab.h b/polly/lib/External/isl/isl_tab.h
index f3a4dfbe9f18..8b15cb04fa24 100644
--- a/polly/lib/External/isl/isl_tab.h
+++ b/polly/lib/External/isl/isl_tab.h
@@ -208,7 +208,7 @@ enum isl_lp_result isl_tab_min(struct isl_tab *tab,
 	unsigned flags) WARN_UNUSED;
 
 isl_stat isl_tab_add_ineq(struct isl_tab *tab, isl_int *ineq) WARN_UNUSED;
-int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED;
+isl_stat isl_tab_add_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED;
 int isl_tab_add_valid_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED;
 
 int isl_tab_freeze_constraint(struct isl_tab *tab, int con) WARN_UNUSED;
@@ -237,7 +237,7 @@ enum isl_ineq_type {
 enum isl_ineq_type isl_tab_ineq_type(struct isl_tab *tab, isl_int *ineq);
 
 struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab);
-int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap) WARN_UNUSED;
+isl_stat isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap) WARN_UNUSED;
 isl_bool isl_tab_need_undo(struct isl_tab *tab);
 void isl_tab_clear_undo(struct isl_tab *tab);
 
@@ -334,4 +334,6 @@ int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div);
 
 int isl_tab_shift_var(struct isl_tab *tab, int pos, isl_int shift) WARN_UNUSED;
 
+isl_stat isl_tab_swap_constraints(struct isl_tab *tab, int con1, int con2);
+
 #endif

diff  --git a/polly/lib/External/isl/isl_tab_lexopt_templ.c b/polly/lib/External/isl/isl_tab_lexopt_templ.c
index 751e7bf8051c..45eba10631c5 100644
--- a/polly/lib/External/isl/isl_tab_lexopt_templ.c
+++ b/polly/lib/External/isl/isl_tab_lexopt_templ.c
@@ -52,6 +52,7 @@ static TYPE *SF(basic_map_partial_lexopt_symm,SUFFIX)(
 {
 	int i, n, k;
 	int *list = NULL;
+	isl_size bmap_in, bmap_param, bmap_all;
 	unsigned n_in, n_out, n_div;
 	isl_ctx *ctx;
 	isl_vec *var = NULL;
@@ -61,9 +62,13 @@ static TYPE *SF(basic_map_partial_lexopt_symm,SUFFIX)(
 	map_space = isl_basic_map_get_space(bmap);
 	set_space = empty ? isl_basic_set_get_space(dom) : NULL;
 
-	n_in = isl_basic_map_dim(bmap, isl_dim_param) +
-	       isl_basic_map_dim(bmap, isl_dim_in);
-	n_out = isl_basic_map_dim(bmap, isl_dim_all) - n_in;
+	bmap_in = isl_basic_map_dim(bmap, isl_dim_in);
+	bmap_param = isl_basic_map_dim(bmap, isl_dim_param);
+	bmap_all = isl_basic_map_dim(bmap, isl_dim_all);
+	if (bmap_in < 0 || bmap_param < 0 || bmap_all < 0)
+		goto error;
+	n_in = bmap_param + bmap_in;
+	n_out = bmap_all - n_in;
 
 	ctx = isl_basic_map_get_ctx(bmap);
 	list = isl_alloc_array(ctx, int, bmap->n_ineq);

diff  --git a/polly/lib/External/isl/isl_tab_pip.c b/polly/lib/External/isl/isl_tab_pip.c
index e305cfd93327..980acb98b7aa 100644
--- a/polly/lib/External/isl/isl_tab_pip.c
+++ b/polly/lib/External/isl/isl_tab_pip.c
@@ -184,7 +184,7 @@ struct isl_sol {
 	int rational;
 	int level;
 	int max;
-	int n_out;
+	isl_size n_out;
 	isl_space *space;
 	struct isl_context *context;
 	struct isl_partial_sol *partial;
@@ -250,12 +250,13 @@ static isl_stat check_final_columns_are_zero(__isl_keep isl_mat *M,
 	unsigned first)
 {
 	int i;
-	unsigned rows, cols, n;
+	isl_size rows, cols;
+	unsigned n;
 
-	if (!M)
-		return isl_stat_error;
 	rows = isl_mat_rows(M);
 	cols = isl_mat_cols(M);
+	if (rows < 0 || cols < 0)
+		return isl_stat_error;
 	n = cols - first;
 	for (i = 0; i < rows; ++i)
 		if (isl_seq_first_non_zero(M->row[i] + first, n) != -1)
@@ -274,13 +275,14 @@ static __isl_give isl_multi_aff *set_from_affine_matrix(
 	__isl_take isl_multi_aff *ma, __isl_take isl_local_space *ls,
 	__isl_take isl_mat *M)
 {
-	int i, dim;
+	int i;
+	isl_size dim;
 	isl_aff *aff;
 
-	if (!ma || !ls || !M)
+	dim = isl_local_space_dim(ls, isl_dim_all);
+	if (!ma || dim < 0 || !M)
 		goto error;
 
-	dim = isl_local_space_dim(ls, isl_dim_all);
 	if (check_final_columns_are_zero(M, 1 + dim) < 0)
 		goto error;
 	for (i = 1; i < M->n_row; ++i) {
@@ -328,9 +330,12 @@ static void sol_push_sol_mat(struct isl_sol *sol,
 {
 	isl_local_space *ls;
 	isl_multi_aff *ma;
-	int n_div, n_known;
+	isl_size n_div;
+	int n_known;
 
 	n_div = isl_basic_set_dim(dom, isl_dim_div);
+	if (n_div < 0)
+		goto error;
 	n_known = n_div - sol->context->n_unknown;
 
 	ma = isl_multi_aff_alloc(isl_space_copy(sol->space));
@@ -342,6 +347,11 @@ static void sol_push_sol_mat(struct isl_sol *sol,
 	if (!ma)
 		dom = isl_basic_set_free(dom);
 	sol_push_sol(sol, dom, ma);
+	return;
+error:
+	isl_basic_set_free(dom);
+	isl_mat_free(M);
+	sol_push_sol(sol, NULL, NULL);
 }
 
 /* Pop one partial solution from the partial solution stack and
@@ -999,14 +1009,14 @@ static struct isl_vec *get_row_split_div(struct isl_tab *tab, int row)
 static __isl_give isl_vec *ineq_for_div(__isl_keep isl_basic_set *bset,
 	unsigned div)
 {
-	unsigned total;
+	isl_size total;
 	unsigned div_pos;
 	struct isl_vec *ineq;
 
-	if (!bset)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		return NULL;
 
-	total = isl_basic_set_total_dim(bset);
 	div_pos = 1 + total - bset->n_div + div;
 
 	ineq = isl_vec_alloc(bset->ctx, 1 + total);
@@ -2063,7 +2073,7 @@ static isl_bool context_tab_insert_div(struct isl_tab *tab, int pos,
 	if (!tab->samples)
 		return isl_bool_error;
 
-	return nonneg;
+	return isl_bool_ok(nonneg);
 }
 
 /* Add a div specified by "div" to both the main tableau and
@@ -2112,19 +2122,26 @@ static int add_div(struct isl_tab *tab, struct isl_context *context,
 	return -1;
 }
 
+/* Return the position of the integer division that is equal to div/denom
+ * if there is one.  Otherwise, return a position beyond the integer divisions.
+ */
 static int find_div(struct isl_tab *tab, isl_int *div, isl_int denom)
 {
 	int i;
-	unsigned total = isl_basic_map_total_dim(tab->bmap);
+	isl_size total = isl_basic_map_dim(tab->bmap, isl_dim_all);
+	isl_size n_div;
 
-	for (i = 0; i < tab->bmap->n_div; ++i) {
+	n_div = isl_basic_map_dim(tab->bmap, isl_dim_div);
+	if (total < 0 || n_div < 0)
+		return -1;
+	for (i = 0; i < n_div; ++i) {
 		if (isl_int_ne(tab->bmap->div[i][0], denom))
 			continue;
 		if (!isl_seq_eq(tab->bmap->div[i] + 1, div, 1 + total))
 			continue;
 		return i;
 	}
-	return -1;
+	return n_div;
 }
 
 /* Return the index of a div that corresponds to "div".
@@ -2135,12 +2152,16 @@ static int get_div(struct isl_tab *tab, struct isl_context *context,
 {
 	int d;
 	struct isl_tab *context_tab = context->op->peek_tab(context);
+	unsigned n_div;
 
 	if (!context_tab)
 		return -1;
 
+	n_div = isl_basic_map_dim(context_tab->bmap, isl_dim_div);
 	d = find_div(context_tab, div->el + 1, div->el[0]);
-	if (d != -1)
+	if (d < 0)
+		return -1;
+	if (d < n_div)
 		return d;
 
 	return add_div(tab, context, div);
@@ -2283,15 +2304,23 @@ static __isl_give struct isl_tab *tab_for_lexmin(__isl_keep isl_basic_map *bmap,
 	struct isl_tab *tab;
 	unsigned n_var;
 	unsigned o_var;
+	isl_size total;
 
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return NULL;
 	tab = isl_tab_alloc(bmap->ctx, 2 * bmap->n_eq + bmap->n_ineq + 1,
-			    isl_basic_map_total_dim(bmap), M);
+			    total, M);
 	if (!tab)
 		return NULL;
 
 	tab->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
 	if (dom) {
-		tab->n_param = isl_basic_set_total_dim(dom) - dom->n_div;
+		isl_size dom_total;
+		dom_total = isl_basic_set_dim(dom, isl_dim_all);
+		if (dom_total < 0)
+			goto error;
+		tab->n_param = dom_total - dom->n_div;
 		tab->n_div = dom->n_div;
 		tab->row_sign = isl_calloc_array(bmap->ctx,
 					enum isl_tab_row_sign, tab->mat->n_row);
@@ -2890,8 +2919,10 @@ static void gbr_init_shifted(struct isl_context_gbr *cgbr)
 	int i, j;
 	struct isl_vec *cst;
 	struct isl_basic_set *bset = isl_tab_peek_bset(cgbr->tab);
-	unsigned dim = isl_basic_set_total_dim(bset);
+	isl_size dim = isl_basic_set_dim(bset, isl_dim_all);
 
+	if (dim < 0)
+		return;
 	cst = isl_vec_alloc(cgbr->tab->mat->ctx, bset->n_ineq);
 	if (!cst)
 		return;
@@ -3131,8 +3162,10 @@ static void add_gbr_ineq(struct isl_context_gbr *cgbr, isl_int *ineq)
 
 	if (cgbr->shifted && !cgbr->shifted->empty && use_shifted(cgbr)) {
 		int i;
-		unsigned dim;
-		dim = isl_basic_map_total_dim(cgbr->tab->bmap);
+		isl_size dim;
+		dim = isl_basic_map_dim(cgbr->tab->bmap, isl_dim_all);
+		if (dim < 0)
+			goto error;
 
 		if (isl_tab_extend_cons(cgbr->shifted, 1) < 0)
 			goto error;
@@ -3402,9 +3435,12 @@ static isl_bool context_gbr_insert_div(struct isl_context *context, int pos,
 {
 	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
 	if (cgbr->cone) {
-		int r, n_div, o_div;
+		int r, o_div;
+		isl_size n_div;
 
 		n_div = isl_basic_map_dim(cgbr->cone->bmap, isl_dim_div);
+		if (n_div < 0)
+			return isl_bool_error;
 		o_div = cgbr->cone->n_var - n_div;
 
 		if (isl_tab_extend_cons(cgbr->cone, 3) < 0)
@@ -3611,6 +3647,7 @@ static struct isl_context *isl_context_alloc(__isl_keep isl_basic_set *dom)
 {
 	struct isl_context *context;
 	int first;
+	isl_size n_div;
 
 	if (!dom)
 		return NULL;
@@ -3624,9 +3661,10 @@ static struct isl_context *isl_context_alloc(__isl_keep isl_basic_set *dom)
 		return NULL;
 
 	first = isl_basic_set_first_unknown_div(dom);
-	if (first < 0)
+	n_div = isl_basic_set_dim(dom, isl_dim_div);
+	if (first < 0 || n_div < 0)
 		return context->op->free(context);
-	context->n_unknown = isl_basic_set_dim(dom, isl_dim_div) - first;
+	context->n_unknown = n_div - first;
 
 	return context;
 }
@@ -3649,7 +3687,7 @@ static isl_stat sol_init(struct isl_sol *sol, __isl_keep isl_basic_map *bmap,
 	sol->space = isl_basic_map_get_space(bmap);
 
 	sol->context = isl_context_alloc(dom);
-	if (!sol->space || !sol->context)
+	if (sol->n_out < 0 || !sol->space || !sol->context)
 		return isl_stat_error;
 
 	return isl_stat_ok;
@@ -4273,30 +4311,37 @@ static void find_solutions_main(struct isl_sol *sol, struct isl_tab *tab)
 
 /* Check if integer division "div" of "dom" also occurs in "bmap".
  * If so, return its position within the divs.
- * If not, return -1.
+ * Otherwise, return a position beyond the integer divisions.
  */
-static int find_context_div(struct isl_basic_map *bmap,
-	struct isl_basic_set *dom, unsigned div)
+static int find_context_div(__isl_keep isl_basic_map *bmap,
+	__isl_keep isl_basic_set *dom, unsigned div)
 {
 	int i;
-	unsigned b_dim = isl_space_dim(bmap->dim, isl_dim_all);
-	unsigned d_dim = isl_space_dim(dom->dim, isl_dim_all);
+	isl_size b_v_div, d_v_div;
+	isl_size n_div;
 
-	if (isl_int_is_zero(dom->div[div][0]))
-		return -1;
-	if (isl_seq_first_non_zero(dom->div[div] + 2 + d_dim, dom->n_div) != -1)
+	b_v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
+	d_v_div = isl_basic_set_var_offset(dom, isl_dim_div);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (b_v_div < 0 || d_v_div < 0 || n_div < 0)
 		return -1;
 
-	for (i = 0; i < bmap->n_div; ++i) {
+	if (isl_int_is_zero(dom->div[div][0]))
+		return n_div;
+	if (isl_seq_first_non_zero(dom->div[div] + 2 + d_v_div,
+				    dom->n_div) != -1)
+		return n_div;
+
+	for (i = 0; i < n_div; ++i) {
 		if (isl_int_is_zero(bmap->div[i][0]))
 			continue;
-		if (isl_seq_first_non_zero(bmap->div[i] + 2 + d_dim,
-					   (b_dim - d_dim) + bmap->n_div) != -1)
+		if (isl_seq_first_non_zero(bmap->div[i] + 2 + d_v_div,
+					   (b_v_div - d_v_div) + n_div) != -1)
 			continue;
-		if (isl_seq_eq(bmap->div[i], dom->div[div], 2 + d_dim))
+		if (isl_seq_eq(bmap->div[i], dom->div[div], 2 + d_v_div))
 			return i;
 	}
-	return -1;
+	return n_div;
 }
 
 /* The correspondence between the variables in the main tableau,
@@ -4319,27 +4364,38 @@ static __isl_give isl_basic_map *align_context_divs(
 	int i;
 	int common = 0;
 	int other;
+	unsigned bmap_n_div;
+
+	bmap_n_div = isl_basic_map_dim(bmap, isl_dim_div);
+
+	for (i = 0; i < dom->n_div; ++i) {
+		int pos;
 
-	for (i = 0; i < dom->n_div; ++i)
-		if (find_context_div(bmap, dom, i) != -1)
+		pos = find_context_div(bmap, dom, i);
+		if (pos < 0)
+			return isl_basic_map_free(bmap);
+		if (pos < bmap_n_div)
 			common++;
-	other = bmap->n_div - common;
+	}
+	other = bmap_n_div - common;
 	if (dom->n_div - common > 0) {
-		bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
-				dom->n_div - common, 0, 0);
+		bmap = isl_basic_map_extend(bmap, dom->n_div - common, 0, 0);
 		if (!bmap)
 			return NULL;
 	}
 	for (i = 0; i < dom->n_div; ++i) {
 		int pos = find_context_div(bmap, dom, i);
-		if (pos < 0) {
+		if (pos < 0)
+			bmap = isl_basic_map_free(bmap);
+		if (pos >= bmap_n_div) {
 			pos = isl_basic_map_alloc_div(bmap);
 			if (pos < 0)
 				goto error;
 			isl_int_set_si(bmap->div[pos][0], 0);
+			bmap_n_div++;
 		}
 		if (pos != other + i)
-			isl_basic_map_swap_div(bmap, pos, other + i);
+			bmap = isl_basic_map_swap_div(bmap, pos, other + i);
 	}
 	return bmap;
 error:
@@ -4509,12 +4565,14 @@ struct isl_constraint_equal_info {
 /* Check whether the coefficients of the output variables
  * of the constraint in "entry" are equal to info->val.
  */
-static int constraint_equal(const void *entry, const void *val)
+static isl_bool constraint_equal(const void *entry, const void *val)
 {
 	isl_int **row = (isl_int **)entry;
 	const struct isl_constraint_equal_info *info = val;
+	int eq;
 
-	return isl_seq_eq((*row) + 1 + info->n_in, info->val, info->n_out);
+	eq = isl_seq_eq((*row) + 1 + info->n_in, info->val, info->n_out);
+	return isl_bool_ok(eq);
 }
 
 /* Check whether "bmap" has a pair of constraints that have
@@ -4536,21 +4594,23 @@ static isl_bool parallel_constraints(__isl_keep isl_basic_map *bmap,
 	struct isl_hash_table *table = NULL;
 	struct isl_hash_table_entry *entry;
 	struct isl_constraint_equal_info info;
-	unsigned n_out;
-	unsigned n_div;
+	isl_size nparam, n_in, n_out, n_div;
 
 	ctx = isl_basic_map_get_ctx(bmap);
 	table = isl_hash_table_alloc(ctx, bmap->n_ineq);
 	if (!table)
 		goto error;
 
-	info.n_in = isl_basic_map_dim(bmap, isl_dim_param) +
-		    isl_basic_map_dim(bmap, isl_dim_in);
+	nparam = isl_basic_map_dim(bmap, isl_dim_param);
+	n_in = isl_basic_map_dim(bmap, isl_dim_in);
+	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (nparam < 0 || n_in < 0 || n_out < 0 || n_div < 0)
+		goto error;
+	info.n_in = nparam + n_in;
 	occurrences = count_occurrences(bmap, info.n_in);
 	if (info.n_in && !occurrences)
 		goto error;
-	n_out = isl_basic_map_dim(bmap, isl_dim_out);
-	n_div = isl_basic_map_dim(bmap, isl_dim_div);
 	info.n_out = n_out + n_div;
 	for (i = 0; i < bmap->n_ineq; ++i) {
 		uint32_t hash;
@@ -4581,7 +4641,7 @@ static isl_bool parallel_constraints(__isl_keep isl_basic_map *bmap,
 	isl_hash_table_free(ctx, table);
 	free(occurrences);
 
-	return i < bmap->n_ineq;
+	return isl_bool_ok(i < bmap->n_ineq);
 error:
 	isl_hash_table_free(ctx, table);
 	free(occurrences);
@@ -4638,21 +4698,21 @@ static __isl_give isl_basic_set *select_minimum(__isl_take isl_basic_set *bset,
  *	b_i <= b_j	for j > i
  *	b_i <  b_j	for j < i
  */
-static __isl_give isl_set *set_minimum(__isl_take isl_space *dim,
+static __isl_give isl_set *set_minimum(__isl_take isl_space *space,
 	__isl_take isl_mat *var)
 {
 	int i, k;
 	isl_basic_set *bset = NULL;
 	isl_set *set = NULL;
 
-	if (!dim || !var)
+	if (!space || !var)
 		goto error;
 
-	set = isl_set_alloc_space(isl_space_copy(dim),
+	set = isl_set_alloc_space(isl_space_copy(space),
 				var->n_row, ISL_SET_DISJOINT);
 
 	for (i = 0; i < var->n_row; ++i) {
-		bset = isl_basic_set_alloc_space(isl_space_copy(dim), 0,
+		bset = isl_basic_set_alloc_space(isl_space_copy(space), 0,
 					       1, var->n_row - 1);
 		k = isl_basic_set_alloc_equality(bset);
 		if (k < 0)
@@ -4663,13 +4723,13 @@ static __isl_give isl_set *set_minimum(__isl_take isl_space *dim,
 		set = isl_set_add_basic_set(set, bset);
 	}
 
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_mat_free(var);
 	return set;
 error:
 	isl_basic_set_free(bset);
 	isl_set_free(set);
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_mat_free(var);
 	return NULL;
 }
@@ -4687,11 +4747,13 @@ static isl_bool need_split_basic_map(__isl_keep isl_basic_map *bmap,
 	__isl_keep isl_mat *cst)
 {
 	int i, j;
-	unsigned total;
+	isl_size total;
 	unsigned pos;
 
 	pos = cst->n_col - 1;
 	total = isl_basic_map_dim(bmap, isl_dim_all);
+	if (total < 0)
+		return isl_bool_error;
 
 	for (i = 0; i < bmap->n_div; ++i)
 		if (!isl_int_is_zero(bmap->div[i][2 + pos]))
@@ -4753,7 +4815,7 @@ static isl_bool need_split_set(__isl_keep isl_set *set, __isl_keep isl_mat *cst)
 	return isl_bool_false;
 }
 
-/* Given a set of which the last set variable is the minimum
+/* Given a map of which the last input variable is the minimum
  * of the bounds in "cst", split each basic set in the set
  * in pieces where one of the bounds is (strictly) smaller than the others.
  * This subdivision is given in "min_expr".
@@ -4766,71 +4828,21 @@ static isl_bool need_split_set(__isl_keep isl_set *set, __isl_keep isl_mat *cst)
  * to obtain l <= a and l <= b, without having to split on whether
  * m is equal to a or b.
  */
-static __isl_give isl_set *split(__isl_take isl_set *empty,
-	__isl_take isl_set *min_expr, __isl_take isl_mat *cst)
-{
-	int n_in;
-	int i;
-	isl_space *dim;
-	isl_set *res;
-
-	if (!empty || !min_expr || !cst)
-		goto error;
-
-	n_in = isl_set_dim(empty, isl_dim_set);
-	dim = isl_set_get_space(empty);
-	dim = isl_space_drop_dims(dim, isl_dim_set, n_in - 1, 1);
-	res = isl_set_empty(dim);
-
-	for (i = 0; i < empty->n; ++i) {
-		isl_bool split;
-		isl_set *set;
-
-		set = isl_set_from_basic_set(isl_basic_set_copy(empty->p[i]));
-		split = need_split_basic_set(empty->p[i], cst);
-		if (split < 0)
-			set = isl_set_free(set);
-		else if (split)
-			set = isl_set_intersect(set, isl_set_copy(min_expr));
-		set = isl_set_remove_dims(set, isl_dim_set, n_in - 1, 1);
-
-		res = isl_set_union_disjoint(res, set);
-	}
-
-	isl_set_free(empty);
-	isl_set_free(min_expr);
-	isl_mat_free(cst);
-	return res;
-error:
-	isl_set_free(empty);
-	isl_set_free(min_expr);
-	isl_mat_free(cst);
-	return NULL;
-}
-
-/* Given a map of which the last input variable is the minimum
- * of the bounds in "cst", split each basic set in the set
- * in pieces where one of the bounds is (strictly) smaller than the others.
- * This subdivision is given in "min_expr".
- * The variable is subsequently projected out.
- *
- * The implementation is essentially the same as that of "split".
- */
 static __isl_give isl_map *split_domain(__isl_take isl_map *opt,
 	__isl_take isl_set *min_expr, __isl_take isl_mat *cst)
 {
-	int n_in;
+	isl_size n_in;
 	int i;
-	isl_space *dim;
+	isl_space *space;
 	isl_map *res;
 
-	if (!opt || !min_expr || !cst)
+	n_in = isl_map_dim(opt, isl_dim_in);
+	if (n_in < 0 || !min_expr || !cst)
 		goto error;
 
-	n_in = isl_map_dim(opt, isl_dim_in);
-	dim = isl_map_get_space(opt);
-	dim = isl_space_drop_dims(dim, isl_dim_in, n_in - 1, 1);
-	res = isl_map_empty(dim);
+	space = isl_map_get_space(opt);
+	space = isl_space_drop_dims(space, isl_dim_in, n_in - 1, 1);
+	res = isl_map_empty(space);
 
 	for (i = 0; i < opt->n; ++i) {
 		isl_map *map;
@@ -4859,6 +4871,24 @@ static __isl_give isl_map *split_domain(__isl_take isl_map *opt,
 	return NULL;
 }
 
+/* Given a set of which the last set variable is the minimum
+ * of the bounds in "cst", split each basic set in the set
+ * in pieces where one of the bounds is (strictly) smaller than the others.
+ * This subdivision is given in "min_expr".
+ * The variable is subsequently projected out.
+ */
+static __isl_give isl_set *split(__isl_take isl_set *empty,
+	__isl_take isl_set *min_expr, __isl_take isl_mat *cst)
+{
+	isl_map *map;
+
+	map = isl_map_from_domain(empty);
+	map = split_domain(map, min_expr, cst);
+	empty = isl_map_domain(map);
+
+	return empty;
+}
+
 static __isl_give isl_map *basic_map_partial_lexopt(
 	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
 	__isl_give isl_set **empty, int max);
@@ -4921,11 +4951,13 @@ static __isl_give isl_map *basic_map_partial_lexopt_symm_core(
 static __isl_give isl_basic_set *extract_domain(__isl_keep isl_basic_map *bmap,
 	unsigned flags)
 {
-	int n_div;
-	int n_out;
+	isl_size n_div;
+	isl_size n_out;
 
 	n_div = isl_basic_map_dim(bmap, isl_dim_div);
 	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	if (n_div < 0 || n_out < 0)
+		return NULL;
 	bmap = isl_basic_map_copy(bmap);
 	if (ISL_FL_ISSET(flags, ISL_OPT_QE)) {
 		bmap = isl_basic_map_drop_constraints_involving_dims(bmap,
@@ -4979,18 +5011,20 @@ static __isl_give isl_vec *extract_sample_sequence(struct isl_tab *tab,
 static isl_bool region_is_trivial(struct isl_tab *tab, int pos,
 	__isl_keep isl_mat *trivial)
 {
-	int n, len;
+	isl_size n, len;
 	isl_vec *v;
 	isl_bool is_trivial;
 
-	if (!trivial)
+	n = isl_mat_rows(trivial);
+	if (n < 0)
 		return isl_bool_error;
 
-	n = isl_mat_rows(trivial);
 	if (n == 0)
 		return isl_bool_false;
 
 	len = isl_mat_cols(trivial);
+	if (len < 0)
+		return isl_bool_error;
 	v = extract_sample_sequence(tab, pos, len);
 	v = isl_mat_vec_product(isl_mat_copy(trivial), v);
 	is_trivial = isl_vec_is_zero(v);
@@ -5123,12 +5157,14 @@ static int force_better_solution(struct isl_tab *tab,
 static isl_stat fix_zero(struct isl_tab *tab, struct isl_trivial_region *region,
 	int dir, struct isl_lexmin_data *data)
 {
-	int len;
+	isl_size len;
 
 	data->v = isl_vec_clr(data->v);
 	if (!data->v)
 		return isl_stat_error;
 	len = isl_mat_cols(region->trivial);
+	if (len < 0)
+		return isl_stat_error;
 	isl_seq_cpy(data->v->el + 1 + region->pos, region->trivial->row[dir],
 		    len);
 	if (add_lexmin_eq(tab, data->v->el) < 0)
@@ -5149,13 +5185,15 @@ static struct isl_tab *pos_neg(struct isl_tab *tab,
 	struct isl_trivial_region *region,
 	int side, struct isl_lexmin_data *data)
 {
-	int len;
+	isl_size len;
 
 	data->v = isl_vec_clr(data->v);
 	if (!data->v)
 		goto error;
 	isl_int_set_si(data->v->el[0], -1);
 	len = isl_mat_cols(region->trivial);
+	if (len < 0)
+		goto error;
 	if (side % 2 == 0)
 		isl_seq_cpy(data->v->el + 1 + region->pos,
 			    region->trivial->row[side / 2], len);
@@ -5232,14 +5270,20 @@ static void update_outer_levels(struct isl_lexmin_data *data, int level)
 /* Initialize "local" to refer to region "region" and
  * to initiate processing at this level.
  */
-static void init_local_region(struct isl_local_region *local, int region,
+static isl_stat init_local_region(struct isl_local_region *local, int region,
 	struct isl_lexmin_data *data)
 {
-	local->n = isl_mat_rows(data->region[region].trivial);
+	isl_size n = isl_mat_rows(data->region[region].trivial);
+
+	if (n < 0)
+		return isl_stat_error;
+	local->n = n;
 	local->region = region;
 	local->side = 0;
 	local->update = 0;
 	local->n_zero = 0;
+
+	return isl_stat_ok;
 }
 
 /* What to do next after entering a level of the backtracking procedure.
@@ -5322,7 +5366,8 @@ static enum isl_next enter_level(int level, int init,
 			isl_die(isl_vec_get_ctx(data->v), isl_error_internal,
 				"nesting level too deep",
 				return isl_next_error);
-		init_local_region(local, r, data);
+		if (init_local_region(local, r, data) < 0)
+			return isl_next_error;
 		if (isl_tab_extend_cons(data->tab,
 				    2 * local->n + 2 * data->n_op) < 0)
 			return isl_next_error;
@@ -5757,18 +5802,27 @@ static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_base_pw_multi_aff(
  * In particular, check if the last input variable appears in any
  * of the expressions in "maff".
  */
-static int need_substitution(__isl_keep isl_multi_aff *maff)
+static isl_bool need_substitution(__isl_keep isl_multi_aff *maff)
 {
 	int i;
+	isl_size n_in;
 	unsigned pos;
 
-	pos = isl_multi_aff_dim(maff, isl_dim_in) - 1;
+	n_in = isl_multi_aff_dim(maff, isl_dim_in);
+	if (n_in < 0)
+		return isl_bool_error;
+	pos = n_in - 1;
 
-	for (i = 0; i < maff->n; ++i)
-		if (isl_aff_involves_dims(maff->u.p[i], isl_dim_in, pos, 1))
-			return 1;
+	for (i = 0; i < maff->n; ++i) {
+		isl_bool involves;
 
-	return 0;
+		involves = isl_aff_involves_dims(maff->u.p[i],
+						isl_dim_in, pos, 1);
+		if (involves < 0 || involves)
+			return involves;
+	}
+
+	return isl_bool_false;
 }
 
 /* Given a set of upper bounds on the last "input" variable m,
@@ -5853,7 +5907,7 @@ static __isl_give isl_pw_multi_aff *split_domain_pma(
 	__isl_take isl_pw_multi_aff *opt, __isl_take isl_pw_aff *min_expr_pa,
 	__isl_take isl_set *min_expr, __isl_take isl_mat *cst)
 {
-	int n_in;
+	isl_size n_in;
 	int i;
 	isl_space *space;
 	isl_pw_multi_aff *res;
@@ -5862,19 +5916,25 @@ static __isl_give isl_pw_multi_aff *split_domain_pma(
 		goto error;
 
 	n_in = isl_pw_multi_aff_dim(opt, isl_dim_in);
+	if (n_in < 0)
+		goto error;
 	space = isl_pw_multi_aff_get_space(opt);
 	space = isl_space_drop_dims(space, isl_dim_in, n_in - 1, 1);
 	res = isl_pw_multi_aff_empty(space);
 
 	for (i = 0; i < opt->n; ++i) {
+		isl_bool subs;
 		isl_pw_multi_aff *pma;
 
 		pma = isl_pw_multi_aff_alloc(isl_set_copy(opt->p[i].set),
 					 isl_multi_aff_copy(opt->p[i].maff));
-		if (need_substitution(opt->p[i].maff))
+		subs = need_substitution(opt->p[i].maff);
+		if (subs < 0) {
+			pma = isl_pw_multi_aff_free(pma);
+		} else if (subs) {
 			pma = isl_pw_multi_aff_substitute(pma,
 					isl_dim_in, n_in - 1, min_expr_pa);
-		else {
+		} else {
 			isl_bool split;
 			split = need_split_set(opt->p[i].set, cst);
 			if (split < 0)

diff  --git a/polly/lib/External/isl/isl_test.c b/polly/lib/External/isl/isl_test.c
index d08870d579b0..a1b45ad4306d 100644
--- a/polly/lib/External/isl/isl_test.c
+++ b/polly/lib/External/isl/isl_test.c
@@ -120,36 +120,10 @@ static int test_parse_multi_val(isl_ctx *ctx, const char *str)
 	return mv ? 0 : -1;
 }
 
-/* Check that printing "mpa" and parsing the output results
- * in the same expression.
- */
-static isl_stat check_reparse_mpa(isl_ctx *ctx,
-	__isl_take isl_multi_pw_aff *mpa)
-{
-	char *str;
-	isl_bool equal;
-	isl_multi_pw_aff *mpa2;
-
-	str = isl_multi_pw_aff_to_str(mpa);
-	mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
-	free(str);
-	equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
-	isl_multi_pw_aff_free(mpa);
-	isl_multi_pw_aff_free(mpa2);
-	if (equal < 0)
-		return isl_stat_error;
-	if (!equal)
-		isl_die(ctx, isl_error_unknown,
-			"parsed function not equal to original",
-			return isl_stat_error);
-
-	return isl_stat_ok;
-}
-
 /* String descriptions of multi piecewise affine expressions
  * that are used for testing printing and parsing.
  */
-const char *parse_multi_mpa_tests[] = {
+static const char *reparse_multi_pw_aff_tests[] = {
 	"{ A[x, y] -> [] : x + y >= 0 }",
 	"{ A[x, y] -> B[] : x + y >= 0 }",
 	"{ A[x, y] -> [x] : x + y >= 0 }",
@@ -163,24 +137,74 @@ const char *parse_multi_mpa_tests[] = {
 	"[N, M] -> { [(N : N >= 0), (M : M >= 0)] : N + M >= 0 }",
 };
 
+#undef BASE
+#define BASE multi_pw_aff
+
+#include "check_reparse_templ.c"
+#include "check_reparse_test_templ.c"
+
+/* String descriptions of piecewise multi affine expressions
+ * that are used for testing printing and parsing.
+ */
+static const char *reparse_pw_multi_aff_tests[] = {
+	"{ [x] -> [x] }",
+	"{ [x] -> [x % 4] }",
+	"{ [x] -> [x % 4] : x mod 3 = 1 }",
+	"{ [x, x] -> [x % 4] }",
+	"{ [x, x + 1] -> [x % 4] : x mod 3 = 1 }",
+	"{ [x, x mod 2] -> [x % 4] }",
+};
+
+#undef BASE
+#define BASE pw_multi_aff
+
+#include "check_reparse_templ.c"
+#include "check_reparse_test_templ.c"
+
+/* Test parsing of piecewise multi affine expressions by printing
+ * the expressions and checking that parsing the output results
+ * in the same expression.
+ * Do this for an expression converted from a map with an output
+ * dimension name that is equal to an automatically generated name, and
+ * a set of expressions parsed from strings.
+ */
+static isl_stat test_parse_pma(isl_ctx *ctx)
+{
+	isl_map *map;
+	isl_pw_multi_aff *pma;
+
+	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
+	pma = isl_pw_multi_aff_from_map(map);
+	if (check_reparse_pw_multi_aff(ctx, pma) < 0)
+		return isl_stat_error;
+
+	if (check_reparse_pw_multi_aff_tests(ctx) < 0)
+		return isl_stat_error;
+
+	return isl_stat_ok;
+}
+
 /* Test parsing of multi piecewise affine expressions by printing
  * the expressions and checking that parsing the output results
  * in the same expression.
- * Do this for a couple of manually constructed expressions and
+ * Do this for a couple of manually constructed expressions,
+ * an expression converted from a map with an output dimension name
+ * that is equal to an automatically generated name, and
  * a set of expressions parsed from strings.
  */
 static int test_parse_mpa(isl_ctx *ctx)
 {
-	int i;
 	isl_space *space;
 	isl_set *dom;
+	isl_map *map;
+	isl_pw_multi_aff *pma;
 	isl_multi_pw_aff *mpa;
 	isl_stat r;
 
 	space = isl_space_set_alloc(ctx, 0, 0);
 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
 	mpa = isl_multi_pw_aff_zero(space);
-	r = check_reparse_mpa(ctx, mpa);
+	r = check_reparse_multi_pw_aff(ctx, mpa);
 	if (r < 0)
 		return -1;
 
@@ -191,53 +215,26 @@ static int test_parse_mpa(isl_ctx *ctx)
 	dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
 	mpa = isl_multi_pw_aff_zero(space);
 	mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
-	r = check_reparse_mpa(ctx, mpa);
+	r = check_reparse_multi_pw_aff(ctx, mpa);
 	if (r < 0)
 		return -1;
 
-	for (i = 0; i < ARRAY_SIZE(parse_multi_mpa_tests); ++i) {
-		const char *str;
+	map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");
+	pma = isl_pw_multi_aff_from_map(map);
+	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
+	if (check_reparse_multi_pw_aff(ctx, mpa) < 0)
+		return -1;
 
-		str = parse_multi_mpa_tests[i];
-		mpa = isl_multi_pw_aff_read_from_str(ctx, str);
-		r = check_reparse_mpa(ctx, mpa);
-		if (r < 0)
-			return -1;
-	}
+	if (check_reparse_multi_pw_aff_tests(ctx) < 0)
+		return -1;
 
 	return 0;
 }
 
-/* Check that printing "mupa" and parsing the output results
- * in the same expression.
- */
-static isl_stat check_reparse_mupa(isl_ctx *ctx,
-	__isl_take isl_multi_union_pw_aff *mupa)
-{
-	char *str;
-	isl_bool equal;
-	isl_multi_union_pw_aff *mupa2;
-
-	str = isl_multi_union_pw_aff_to_str(mupa);
-	mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
-	free(str);
-	equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
-	isl_multi_union_pw_aff_free(mupa);
-	isl_multi_union_pw_aff_free(mupa2);
-	if (equal < 0)
-		return isl_stat_error;
-	if (!equal)
-		isl_die(ctx, isl_error_unknown,
-			"parsed function not equal to original",
-			return isl_stat_error);
-
-	return isl_stat_ok;
-}
-
 /* String descriptions of multi union piecewise affine expressions
  * that are used for testing printing and parsing.
  */
-const char *parse_multi_mupa_tests[] = {
+static const char *reparse_multi_union_pw_aff_tests[] = {
 	"[]",
 	"A[]",
 	"A[B[] -> C[]]",
@@ -252,6 +249,12 @@ const char *parse_multi_mupa_tests[] = {
 		"{ S[x] : x > 0; T[y] : y >= 0 })",
 };
 
+#undef BASE
+#define BASE multi_union_pw_aff
+
+#include "check_reparse_templ.c"
+#include "check_reparse_test_templ.c"
+
 /* Test parsing of multi union piecewise affine expressions by printing
  * the expressions and checking that parsing the output results
  * in the same expression.
@@ -260,7 +263,6 @@ const char *parse_multi_mupa_tests[] = {
  */
 static int test_parse_mupa(isl_ctx *ctx)
 {
-	int i;
 	isl_space *space;
 	isl_multi_union_pw_aff *mupa;
 	isl_set *dom;
@@ -270,7 +272,7 @@ static int test_parse_mupa(isl_ctx *ctx)
 	space = isl_space_set_alloc(ctx, 0, 0);
 	space = isl_space_set_tuple_name(space, isl_dim_set, "A");
 	mupa = isl_multi_union_pw_aff_zero(space);
-	r = check_reparse_mupa(ctx, mupa);
+	r = check_reparse_multi_union_pw_aff(ctx, mupa);
 	if (r < 0)
 		return -1;
 
@@ -285,19 +287,12 @@ static int test_parse_mupa(isl_ctx *ctx)
 	space = isl_space_set_tuple_name(space, isl_dim_set, "B");
 	mupa = isl_multi_union_pw_aff_zero(space);
 	mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);
-	r = check_reparse_mupa(ctx, mupa);
+	r = check_reparse_multi_union_pw_aff(ctx, mupa);
 	if (r < 0)
 		return -1;
 
-	for (i = 0; i < ARRAY_SIZE(parse_multi_mupa_tests); ++i) {
-		const char *str;
-
-		str = parse_multi_mupa_tests[i];
-		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
-		r = check_reparse_mupa(ctx, mupa);
-		if (r < 0)
-			return -1;
-	}
+	if (check_reparse_multi_union_pw_aff_tests(ctx) < 0)
+		return -1;
 
 	return 0;
 }
@@ -387,6 +382,24 @@ struct {
 	  "{ [x] -> [] : 0 <= x <= 15 }" },
 	{ "{ [x] -> [x] : }",
 	  "{ [x] -> [x] }" },
+	{ "{ [x=4:5] -> [x + 1] }",
+	  "{ [x] -> [x + 1] : 4 <= x <= 5 }" },
+	{ "{ [x=4:5] -> [x + 1 : x + 1] }",
+	  "{ [x=4:5] -> [x + 1] }" },
+	{ "{ [x] -> [x - 1 : x + 1] }",
+	  "{ [x] -> [y] : x - 1 <= y <= x + 1 }" },
+	{ "{ [x=4:] -> [x + 1] }",
+	  "{ [x] -> [x + 1] : 4 <= x }" },
+	{ "{ [x=:5] -> [x + 1] }",
+	  "{ [x] -> [x + 1] : x <= 5 }" },
+	{ "{ [x=:] -> [x + 1] }",
+	  "{ [x] -> [x + 1] }" },
+	{ "{ [:] -> [:] }",
+	  "{ [x] -> [y] }" },
+	{ "{ [x, x//4] }",
+	  "{ [x, floor(x/4)] }" },
+	{ "{ [10//4] }",
+	  "{ [2] }" },
 };
 
 int test_parse(struct isl_ctx *ctx)
@@ -403,6 +416,8 @@ int test_parse(struct isl_ctx *ctx)
 		return -1;
 	if (test_parse_multi(ctx) < 0)
 		return -1;
+	if (test_parse_pma(ctx) < 0)
+		return -1;
 
 	str = "{ [i] -> [-i] }";
 	map = isl_map_read_from_str(ctx, str);
@@ -642,6 +657,14 @@ static int test_dim(isl_ctx *ctx)
 	return 0;
 }
 
+#undef BASE
+#define BASE	multi_val
+#include "isl_test_plain_equal_templ.c"
+
+#undef BASE
+#define BASE	multi_aff
+#include "isl_test_plain_equal_templ.c"
+
 /* Check that "val" is equal to the value described by "str".
  * If "str" is "NaN", then check for a NaN value explicitly.
  */
@@ -904,14 +927,14 @@ static const char *elimination_tests[] = {
 static int test_elimination(isl_ctx *ctx)
 {
 	int i;
-	unsigned n;
+	isl_size n;
 	isl_basic_set *bset;
 
 	for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) {
 		bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]);
 		n = isl_basic_set_dim(bset, isl_dim_div);
 		isl_basic_set_free(bset);
-		if (!bset)
+		if (n < 0)
 			return -1;
 		if (n != 0)
 			isl_die(ctx, isl_error_unknown,
@@ -1252,13 +1275,56 @@ void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
 	fclose(input);
 }
 
+/* Pairs of sets and the corresponding expected results of
+ * isl_basic_set_recession_cone.
+ */
+struct {
+	const char *set;
+	const char *cone;
+} recession_cone_tests[] = {
+	{ "{ [i] : 0 <= i <= 10 }", "{ [0] }" },
+	{ "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" },
+	{ "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" },
+	{ "{ [i] : false }", "{ [i] : false }" },
+};
+
+/* Perform some basic isl_basic_set_recession_cone tests.
+ */
+static int test_recession_cone(struct isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) {
+		const char *str;
+		isl_basic_set *bset;
+		isl_basic_set *cone, *expected;
+		isl_bool equal;
+
+		str = recession_cone_tests[i].set;
+		bset = isl_basic_set_read_from_str(ctx, str);
+		str = recession_cone_tests[i].cone;
+		expected = isl_basic_set_read_from_str(ctx, str);
+		cone = isl_basic_set_recession_cone(bset);
+		equal = isl_basic_set_is_equal(cone, expected);
+		isl_basic_set_free(cone);
+		isl_basic_set_free(expected);
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown, "unexpected cone",
+				return -1);
+	}
+
+	return 0;
+}
+
 int test_affine_hull(struct isl_ctx *ctx)
 {
 	const char *str;
 	isl_set *set;
 	isl_basic_set *bset, *bset2;
-	int n;
-	int subset;
+	isl_size n;
+	isl_bool subset;
 
 	test_affine_hull_case(ctx, "affine2");
 	test_affine_hull_case(ctx, "affine");
@@ -1272,6 +1338,8 @@ int test_affine_hull(struct isl_ctx *ctx)
 	bset = isl_set_affine_hull(set);
 	n = isl_basic_set_dim(bset, isl_dim_div);
 	isl_basic_set_free(bset);
+	if (n < 0)
+		return -1;
 	if (n != 0)
 		isl_die(ctx, isl_error_unknown, "not expecting any divs",
 			return -1);
@@ -1418,6 +1486,57 @@ static int test_simple_hull(struct isl_ctx *ctx)
 	return 0;
 }
 
+/* Inputs for isl_set_get_simple_fixed_box_hull tests.
+ * "set" is the input set.
+ * "offset" is the expected box offset.
+ * "size" is the expected box size.
+ */
+static struct {
+	const char *set;
+	const char *offset;
+	const char *size;
+} box_hull_tests[] = {
+	{ "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },
+	{ "[N] -> { S[x, y] : N <= x, y < N + 10 }",
+	  "[N] -> { S[N, N] }", "{ S[10, 10] }" },
+	{ "{ S[x, y] : 0 <= x + y, x - y < 10 }",
+	  "{ S[0, -4] }", "{ S[10, 9] }" },
+};
+
+/* Perform basic isl_set_get_simple_fixed_box_hull tests.
+ */
+static int test_box_hull(struct isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {
+		const char *str;
+		isl_stat r;
+		isl_set *set;
+		isl_multi_aff *offset;
+		isl_multi_val *size;
+		isl_fixed_box *box;
+
+		set = isl_set_read_from_str(ctx, box_hull_tests[i].set);
+		box = isl_set_get_simple_fixed_box_hull(set);
+		offset = isl_fixed_box_get_offset(box);
+		size = isl_fixed_box_get_size(box);
+		str = box_hull_tests[i].offset;
+		r = multi_aff_check_plain_equal(offset, str);
+		str = box_hull_tests[i].size;
+		if (r >= 0)
+			r = multi_val_check_plain_equal(size, str);
+		isl_multi_aff_free(offset);
+		isl_multi_val_free(size);
+		isl_fixed_box_free(box);
+		isl_set_free(set);
+		if (r < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
 {
 	char *filename;
@@ -1466,6 +1585,11 @@ struct {
 	{ "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "
 	    "[x, y, 0] : x >= 0 and y < 0 }",
 	    "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },
+	{ "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "
+			    "c <= a; "
+	    "[0, 2, 0]; [3, 1, 0] }",
+	    "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "
+			    "5c <= 6 - a - 3b }" },
 };
 
 static int test_convex_hull_algo(isl_ctx *ctx, int convex)
@@ -1733,10 +1857,11 @@ static int test_gist(struct isl_ctx *ctx)
 	const char *str;
 	isl_basic_set *bset1, *bset2;
 	isl_map *map1, *map2;
-	int equal;
+	isl_bool equal;
+	isl_size n_div;
 
 	for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
-		int equal_input, equal_intersection;
+		isl_bool equal_input, equal_intersection;
 		isl_set *set1, *set2, *copy, *context;
 
 		set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
@@ -1814,10 +1939,13 @@ static int test_gist(struct isl_ctx *ctx)
 	if (map1->n != 1)
 		isl_die(ctx, isl_error_unknown, "expecting single disjunct",
 			isl_map_free(map1); return -1);
-	if (isl_basic_map_dim(map1->p[0], isl_dim_div) != 1)
-		isl_die(ctx, isl_error_unknown, "expecting single div",
-			isl_map_free(map1); return -1);
+	n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);
 	isl_map_free(map1);
+	if (n_div < 0)
+		return -1;
+	if (n_div != 1)
+		isl_die(ctx, isl_error_unknown, "expecting single div",
+			return -1);
 
 	if (test_plain_gist(ctx) < 0)
 		return -1;
@@ -1869,6 +1997,8 @@ struct {
 	{ 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },
 	{ 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },
 	{ 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },
+	{ 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "
+		"[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },
 };
 
 /* Test the functionality of isl_set_coalesce with the bounded wrapping
@@ -2159,6 +2289,9 @@ struct {
 		"(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "
 		    "a > 0 and a <= 5) }" },
 	{ 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },
+	{ 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "
+			"2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "
+		"[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },
 };
 
 /* A specialized coalescing test case that would result
@@ -2264,6 +2397,77 @@ static int test_coalesce_special3(isl_ctx *ctx)
 	return 0;
 }
 
+/* Check that calling isl_set_coalesce on the intersection of
+ * the sets described by "s1" and "s2" does not leave other sets
+ * that may share some information with the input to isl_set_coalesce
+ * in an inconsistent state.
+ * In particular, when isl_set_coalesce detects equality constraints,
+ * it does not immediately perform Gaussian elimination on them,
+ * but then it needs to ensure that it is performed at some point.
+ * The input set has implicit equality constraints in the first disjunct.
+ * It is constructed as an intersection, because otherwise
+ * those equality constraints would already be detected during parsing.
+ */
+static isl_stat test_coalesce_intersection(isl_ctx *ctx,
+	const char *s1, const char *s2)
+{
+	isl_set *set1, *set2;
+
+	set1 = isl_set_read_from_str(ctx, s1);
+	set2 = isl_set_read_from_str(ctx, s2);
+	set1 = isl_set_intersect(set1, set2);
+	isl_set_free(isl_set_coalesce(isl_set_copy(set1)));
+	set1 = isl_set_coalesce(set1);
+	isl_set_free(set1);
+
+	if (!set1)
+		return isl_stat_error;
+
+	return isl_stat_ok;
+}
+
+/* Check that calling isl_set_coalesce does not leave other sets
+ * that may share some information with the input to isl_set_coalesce
+ * in an inconsistent state, for the case where one disjunct
+ * is a subset of the other.
+ */
+static isl_stat test_coalesce_special4(isl_ctx *ctx)
+{
+	const char *s1, *s2;
+
+	s1 = "{ [a, b] : b <= 0 or a <= 1 }";
+	s2 = "{ [a, b] : -1 <= -a < b }";
+	return test_coalesce_intersection(ctx, s1, s2);
+}
+
+/* Check that calling isl_set_coalesce does not leave other sets
+ * that may share some information with the input to isl_set_coalesce
+ * in an inconsistent state, for the case where two disjuncts
+ * can be fused.
+ */
+static isl_stat test_coalesce_special5(isl_ctx *ctx)
+{
+	const char *s1, *s2;
+
+	s1 = "{ [a, b, c] : b <= 0 }";
+	s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";
+	return test_coalesce_intersection(ctx, s1, s2);
+}
+
+/* Check that calling isl_set_coalesce does not leave other sets
+ * that may share some information with the input to isl_set_coalesce
+ * in an inconsistent state, for the case where two disjuncts
+ * can be fused and where both disjuncts have implicit equality constraints.
+ */
+static isl_stat test_coalesce_special6(isl_ctx *ctx)
+{
+	const char *s1, *s2;
+
+	s1 = "{ [a, b, c] : c <= 0 }";
+	s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";
+	return test_coalesce_intersection(ctx, s1, s2);
+}
+
 /* Test the functionality of isl_set_coalesce.
  * That is, check that the output is always equal to the input
  * and in some cases that the result consists of a single disjunct.
@@ -2287,6 +2491,13 @@ static int test_coalesce(struct isl_ctx *ctx)
 		return -1;
 	if (test_coalesce_special3(ctx) < 0)
 		return -1;
+	if (test_coalesce_special4(ctx) < 0)
+		return -1;
+	if (test_coalesce_special5(ctx) < 0)
+		return -1;
+	if (test_coalesce_special6(ctx) < 0)
+		return -1;
+
 
 	return 0;
 }
@@ -2339,7 +2550,7 @@ static int test_closure(isl_ctx *ctx)
 {
 	const char *str;
 	isl_map *map, *map2;
-	int exact, equal;
+	isl_bool exact, equal;
 
 	/* COCOA example 1 */
 	map = isl_map_read_from_str(ctx,
@@ -2573,6 +2784,46 @@ static int test_closure(isl_ctx *ctx)
 	return 0;
 }
 
+/* Check that the actual result of a boolean operation is equal
+ * to the expected result.
+ */
+static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)
+{
+	if (actual != expected)
+		isl_die(ctx, isl_error_unknown,
+			"incorrect boolean operation", return isl_stat_error);
+	return isl_stat_ok;
+}
+
+/* Test operations on isl_bool values.
+ *
+ * This tests:
+ *
+ * 	isl_bool_not
+ * 	isl_bool_ok
+ */
+static int test_isl_bool(isl_ctx *ctx)
+{
+	if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)
+		return -1;
+	if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)
+		return -1;
+	if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)
+		return -1;
+	if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)
+		return -1;
+	if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)
+		return -1;
+	if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)
+		return -1;
+	if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)
+		return -1;
+	if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)
+		return -1;
+
+	return 0;
+}
+
 static int test_lex(struct isl_ctx *ctx)
 {
 	isl_space *dim;
@@ -2667,6 +2918,8 @@ static int test_lexmin(struct isl_ctx *ctx)
 	map = isl_map_read_from_str(ctx, str);
 	map = isl_map_lexmin(map);
 	isl_map_free(map);
+	if (!map)
+		return -1;
 
 	str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
 	    "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
@@ -2890,6 +3143,71 @@ static int map_check_equal(__isl_keep isl_map *map, const char *str)
 	return 0;
 }
 
+/* Is "set" equal to the set described by "str"?
+ */
+static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)
+{
+	isl_set *set2;
+	isl_bool equal;
+
+	if (!set)
+		return isl_bool_error;
+
+	set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);
+	equal = isl_set_is_equal(set, set2);
+	isl_set_free(set2);
+
+	return equal;
+}
+
+/* Check that "set" is equal to the set described by "str".
+ */
+static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)
+{
+	isl_bool equal;
+
+	equal = set_is_equal(set, str);
+	if (equal < 0)
+		return isl_stat_error;
+	if (!equal)
+		isl_die(isl_set_get_ctx(set), isl_error_unknown,
+			"result not as expected", return isl_stat_error);
+	return isl_stat_ok;
+}
+
+/* Is "uset" equal to the union set described by "str"?
+ */
+static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)
+{
+	isl_union_set *uset2;
+	isl_bool equal;
+
+	if (!uset)
+		return isl_bool_error;
+
+	uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);
+	equal = isl_union_set_is_equal(uset, uset2);
+	isl_union_set_free(uset2);
+
+	return equal;
+}
+
+/* Check that "uset" is equal to the union set described by "str".
+ */
+static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,
+	const char *str)
+{
+	isl_bool equal;
+
+	equal = uset_is_equal(uset, str);
+	if (equal < 0)
+		return isl_stat_error;
+	if (!equal)
+		isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,
+			"result not as expected", return isl_stat_error);
+	return isl_stat_ok;
+}
+
 static int test_dep(struct isl_ctx *ctx)
 {
 	const char *str;
@@ -3202,28 +3520,15 @@ struct {
 	{ "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
 };
 
-static int test_pwqp(struct isl_ctx *ctx)
+/* Perform some basic isl_pw_qpolynomial_gist tests.
+ */
+static isl_stat test_pwqp_gist(isl_ctx *ctx)
 {
 	int i;
 	const char *str;
 	isl_set *set;
 	isl_pw_qpolynomial *pwqp1, *pwqp2;
-	int equal;
-
-	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
-	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
-
-	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
-						isl_dim_in, 1, 1);
-
-	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
-	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
-
-	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
-
-	assert(isl_pw_qpolynomial_is_zero(pwqp1));
-
-	isl_pw_qpolynomial_free(pwqp1);
+	isl_bool equal;
 
 	for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
 		str = pwqp_gist_tests[i].pwqp;
@@ -3238,12 +3543,64 @@ static int test_pwqp(struct isl_ctx *ctx)
 		isl_pw_qpolynomial_free(pwqp1);
 
 		if (equal < 0)
-			return -1;
+			return isl_stat_error;
 		if (!equal)
 			isl_die(ctx, isl_error_unknown,
-				"unexpected result", return -1);
+				"unexpected result", return isl_stat_error);
 	}
 
+	return isl_stat_ok;
+}
+
+/* Perform a basic isl_pw_qpolynomial_max test.
+ */
+static isl_stat test_pwqp_max(isl_ctx *ctx)
+{
+	const char *str;
+	isl_pw_qpolynomial *pwqp;
+	isl_val *v;
+	int ok;
+
+	str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";
+	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+	v = isl_pw_qpolynomial_max(pwqp);
+	ok = isl_val_cmp_si(v, -1) == 0;
+	isl_val_free(v);
+
+	if (!v)
+		return isl_stat_error;
+	if (!ok)
+		isl_die(ctx, isl_error_unknown, "unexpected maximum",
+			return isl_stat_error);
+
+	return isl_stat_ok;
+}
+
+static int test_pwqp(struct isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_pw_qpolynomial *pwqp1, *pwqp2;
+	int equal;
+
+	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
+						isl_dim_in, 1, 1);
+
+	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+	assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+	isl_pw_qpolynomial_free(pwqp1);
+
+	if (test_pwqp_gist(ctx) < 0)
+		return -1;
+
 	str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
 	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
 	str = "{ [i] -> ([(2 * [i/2])/5]) }";
@@ -3302,6 +3659,9 @@ static int test_pwqp(struct isl_ctx *ctx)
 	if (!equal)
 		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
 
+	if (test_pwqp_max(ctx) < 0)
+		return -1;
+
 	return 0;
 }
 
@@ -3403,7 +3763,7 @@ static int test_bound_unbounded_domain(isl_ctx *ctx)
 static int test_bound(isl_ctx *ctx)
 {
 	const char *str;
-	unsigned dim;
+	isl_size dim;
 	isl_pw_qpolynomial *pwqp;
 	isl_pw_qpolynomial_fold *pwf;
 
@@ -3415,6 +3775,8 @@ static int test_bound(isl_ctx *ctx)
 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
 	dim = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in);
 	isl_pw_qpolynomial_fold_free(pwf);
+	if (dim < 0)
+		return -1;
 	if (dim != 4)
 		isl_die(ctx, isl_error_unknown, "unexpected input dimension",
 			return -1);
@@ -3424,6 +3786,8 @@ static int test_bound(isl_ctx *ctx)
 	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
 	dim = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in);
 	isl_pw_qpolynomial_fold_free(pwf);
+	if (dim < 0)
+		return -1;
 	if (dim != 1)
 		isl_die(ctx, isl_error_unknown, "unexpected input dimension",
 			return -1);
@@ -3431,203 +3795,54 @@ static int test_bound(isl_ctx *ctx)
 	return 0;
 }
 
-/* Check that the conversion from 'set' to 'basic set list' works as expected.
- */
-static isl_stat test_get_list_bset_from_set(isl_ctx *ctx)
-{
-	int i;
-	isl_bool equal;
-	isl_set *set, *set2;
-	isl_basic_set_list *bset_list;
-
-	set = isl_set_read_from_str(ctx, "{ [0]; [2]; [3] }");
-	bset_list = isl_set_get_basic_set_list(set);
-
-	set2 = isl_set_empty(isl_set_get_space(set));
-
-	for (i = 0; i < isl_basic_set_list_n_basic_set(bset_list); i++) {
-		isl_basic_set *bset;
-		bset = isl_basic_set_list_get_basic_set(bset_list, i);
-		set2 = isl_set_union(set2, isl_set_from_basic_set(bset));
-	}
-
-	equal = isl_set_is_equal(set, set2);
-
-	isl_set_free(set);
-	isl_set_free(set2);
-	isl_basic_set_list_free(bset_list);
-
-	if (equal < 0)
-		return isl_stat_error;
-
-	if (!equal)
-		isl_die(ctx, isl_error_unknown, "sets are not equal",
-			return isl_stat_error);
-
-	return isl_stat_ok;
-}
-
-/* Check that the conversion from 'union set' to 'basic set list' works as
- * expected.
- */
-static isl_stat test_get_list_bset_from_uset(isl_ctx *ctx)
-{
-	int i;
-	isl_bool equal;
-	isl_union_set *uset, *uset2;
-	isl_basic_set_list *bset_list;
-
-	uset = isl_union_set_read_from_str(ctx, "{ A[0]; B[2]; B[3] }");
-	bset_list = isl_union_set_get_basic_set_list(uset);
-
-	uset2 = isl_union_set_empty(isl_union_set_get_space(uset));
-
-	for (i = 0; i < isl_basic_set_list_n_basic_set(bset_list); i++) {
-		isl_basic_set *bset;
-		bset = isl_basic_set_list_get_basic_set(bset_list, i);
-		uset2 = isl_union_set_union(uset2,
-				isl_union_set_from_basic_set(bset));
-	}
-
-	equal = isl_union_set_is_equal(uset, uset2);
-
-	isl_union_set_free(uset);
-	isl_union_set_free(uset2);
-	isl_basic_set_list_free(bset_list);
-
-	if (equal < 0)
-		return isl_stat_error;
-
-	if (!equal)
-		isl_die(ctx, isl_error_unknown, "sets are not equal",
-			return isl_stat_error);
-
-	return isl_stat_ok;
-}
-
-/* Check that the conversion from 'union set' to 'set list' works as expected.
- */
-static isl_stat test_get_list_set_from_uset(isl_ctx *ctx)
-{
-	int i;
-	isl_bool equal;
-	isl_union_set *uset, *uset2;
-	isl_set_list *set_list;
-
-	uset = isl_union_set_read_from_str(ctx, "{ A[0]; A[2]; B[3] }");
-	set_list = isl_union_set_get_set_list(uset);
-
-	uset2 = isl_union_set_empty(isl_union_set_get_space(uset));
-
-	for (i = 0; i < isl_set_list_n_set(set_list); i++) {
-		isl_set *set;
-		set = isl_set_list_get_set(set_list, i);
-		uset2 = isl_union_set_union(uset2, isl_union_set_from_set(set));
-	}
-
-	equal = isl_union_set_is_equal(uset, uset2);
-
-	isl_union_set_free(uset);
-	isl_union_set_free(uset2);
-	isl_set_list_free(set_list);
-
-	if (equal < 0)
-		return isl_stat_error;
-
-	if (!equal)
-		isl_die(ctx, isl_error_unknown, "union sets are not equal",
-			return isl_stat_error);
-
-	return isl_stat_ok;
-}
-
-/* Check that the conversion from 'map' to 'basic map list' works as expected.
- */
-static isl_stat test_get_list_bmap_from_map(isl_ctx *ctx)
-{
-	int i;
-	isl_bool equal;
-	isl_map *map, *map2;
-	isl_basic_map_list *bmap_list;
-
-	map = isl_map_read_from_str(ctx,
-		"{ [0] -> [0]; [2] -> [0]; [3] -> [0] }");
-	bmap_list = isl_map_get_basic_map_list(map);
-
-	map2 = isl_map_empty(isl_map_get_space(map));
-
-	for (i = 0; i < isl_basic_map_list_n_basic_map(bmap_list); i++) {
-		isl_basic_map *bmap;
-		bmap = isl_basic_map_list_get_basic_map(bmap_list, i);
-		map2 = isl_map_union(map2, isl_map_from_basic_map(bmap));
-	}
-
-	equal = isl_map_is_equal(map, map2);
-
-	isl_map_free(map);
-	isl_map_free(map2);
-	isl_basic_map_list_free(bmap_list);
-
-	if (equal < 0)
-		return isl_stat_error;
-
-	if (!equal)
-		isl_die(ctx, isl_error_unknown, "maps are not equal",
-			return isl_stat_error);
-
-	return isl_stat_ok;
-}
-
-/* Check that the conversion from 'union map' to 'map list' works as expected.
+/* isl_set is defined to isl_map internally, so the corresponding elements
+ * are isl_basic_map objects.
  */
-static isl_stat test_get_list_map_from_umap(isl_ctx *ctx)
-{
-	int i;
-	isl_bool equal;
-	isl_union_map *umap, *umap2;
-	isl_map_list *map_list;
-
-	umap = isl_union_map_read_from_str(ctx,
-		"{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }");
-	map_list = isl_union_map_get_map_list(umap);
-
-	umap2 = isl_union_map_empty(isl_union_map_get_space(umap));
-
-	for (i = 0; i < isl_map_list_n_map(map_list); i++) {
-		isl_map *map;
-		map = isl_map_list_get_map(map_list, i);
-		umap2 = isl_union_map_union(umap2, isl_union_map_from_map(map));
-	}
-
-	equal = isl_union_map_is_equal(umap, umap2);
+#undef EL_BASE
+#undef SET_BASE
+#define EL_BASE		basic_map
+#define SET_BASE	set
+#include "isl_test_list_templ.c"
 
-	isl_union_map_free(umap);
-	isl_union_map_free(umap2);
-	isl_map_list_free(map_list);
+#undef EL_BASE
+#undef SET_BASE
+#define EL_BASE		basic_set
+#define SET_BASE	union_set
+#include "isl_test_list_templ.c"
 
-	if (equal < 0)
-		return isl_stat_error;
+#undef EL_BASE
+#undef SET_BASE
+#define EL_BASE		set
+#define SET_BASE	union_set
+#include "isl_test_list_templ.c"
 
-	if (!equal)
-		isl_die(ctx, isl_error_unknown, "union maps are not equal",
-			return isl_stat_error);
+#undef EL_BASE
+#undef SET_BASE
+#define EL_BASE		basic_map
+#define SET_BASE	map
+#include "isl_test_list_templ.c"
 
-	return isl_stat_ok;
-}
+#undef EL_BASE
+#undef SET_BASE
+#define EL_BASE		map
+#define SET_BASE	union_map
+#include "isl_test_list_templ.c"
 
 /* Check that the conversion from isl objects to lists works as expected.
  */
 static int test_get_list(isl_ctx *ctx)
 {
-	if (test_get_list_bset_from_set(ctx))
+	if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))
 		return -1;
-	if (test_get_list_bset_from_uset(ctx))
+	if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))
 		return -1;
-	if (test_get_list_set_from_uset(ctx))
+	if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))
 		return -1;
-	if (test_get_list_bmap_from_map(ctx))
+	if (test_get_list_basic_map_from_map(ctx,
+				"{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))
 		return -1;
-	if (test_get_list_map_from_umap(ctx))
+	if (test_get_list_map_from_union_map(ctx,
+				"{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))
 		return -1;
 
 	return 0;
@@ -3813,7 +4028,7 @@ static int test_subtract(isl_ctx *ctx)
  */
 static int test_intersect_1(isl_ctx *ctx)
 {
-	int n1, n2;
+	isl_size n1, n2;
 	isl_basic_set *bset1, *bset2;
 
 	bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");
@@ -3822,7 +4037,7 @@ static int test_intersect_1(isl_ctx *ctx)
 	bset1 = isl_basic_set_intersect(bset1, bset2);
 	n2 = isl_basic_set_n_constraint(bset1);
 	isl_basic_set_free(bset1);
-	if (!bset1)
+	if (n1 < 0 || n2 < 0)
 		return -1;
 	if (n1 != n2)
 		isl_die(ctx, isl_error_unknown,
@@ -3935,6 +4150,7 @@ int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
 	isl_schedule_constraints *sc;
 	isl_schedule *sched;
 	int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
+	isl_size n;
 
 	D = isl_union_set_read_from_str(ctx, d);
 	W = isl_union_map_read_from_str(ctx, w);
@@ -3985,12 +4201,19 @@ int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
 	test = isl_union_map_apply_range(test, schedule);
 
 	delta = isl_union_map_deltas(test);
-	if (isl_union_set_n_set(delta) == 0) {
+	n = isl_union_set_n_set(delta);
+	if (n < 0) {
+		isl_union_set_free(delta);
+		return -1;
+	}
+	if (n == 0) {
 		is_tilable = 1;
 		is_parallel = 1;
 		is_nonneg = 1;
 		isl_union_set_free(delta);
 	} else {
+		isl_size dim;
+
 		delta_set = isl_set_from_union_set(delta);
 
 		slice = isl_set_universe(isl_set_get_space(delta_set));
@@ -4006,7 +4229,10 @@ int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
 		isl_set_free(slice);
 
 		origin = isl_set_universe(isl_set_get_space(delta_set));
-		for (i = 0; i < isl_set_dim(origin, isl_dim_set); ++i)
+		dim = isl_set_dim(origin, isl_dim_set);
+		if (dim < 0)
+			origin = isl_set_free(origin);
+		for (i = 0; i < dim; ++i)
 			origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
 
 		delta_set = isl_set_union(delta_set, isl_set_copy(origin));
@@ -4384,7 +4610,7 @@ static int test_conditional_schedule_constraints(isl_ctx *ctx)
 	isl_schedule_constraints *sc;
 	isl_schedule *schedule;
 	isl_schedule_node *node;
-	int n_member;
+	isl_size n_member;
 
 	if (test_special_conditional_schedule_constraints(ctx) < 0)
 		return -1;
@@ -4415,7 +4641,7 @@ static int test_conditional_schedule_constraints(isl_ctx *ctx)
 		isl_schedule_node_free(node);
 		isl_schedule_free(schedule);
 
-		if (!schedule)
+		if (!schedule || n_member < 0)
 			return -1;
 		if (n_member != live_range_tests[i].outer_band_n)
 			isl_die(ctx, isl_error_unknown,
@@ -4927,70 +5153,17 @@ int test_injective(isl_ctx *ctx)
 	return 0;
 }
 
-static int aff_plain_is_equal(__isl_keep isl_aff *aff, const char *str)
-{
-	isl_aff *aff2;
-	int equal;
-
-	if (!aff)
-		return -1;
-
-	aff2 = isl_aff_read_from_str(isl_aff_get_ctx(aff), str);
-	equal = isl_aff_plain_is_equal(aff, aff2);
-	isl_aff_free(aff2);
-
-	return equal;
-}
-
-static int aff_check_plain_equal(__isl_keep isl_aff *aff, const char *str)
-{
-	int equal;
-
-	equal = aff_plain_is_equal(aff, str);
-	if (equal < 0)
-		return -1;
-	if (!equal)
-		isl_die(isl_aff_get_ctx(aff), isl_error_unknown,
-			"result not as expected", return -1);
-	return 0;
-}
-
-/* Is "upa" obviously equal to the isl_union_pw_aff represented by "str"?
- */
-static isl_bool union_pw_aff_plain_is_equal(__isl_keep isl_union_pw_aff *upa,
-	const char *str)
-{
-	isl_ctx *ctx;
-	isl_union_pw_aff *upa2;
-	isl_bool equal;
-
-	if (!upa)
-		return isl_bool_error;
-
-	ctx = isl_union_pw_aff_get_ctx(upa);
-	upa2 = isl_union_pw_aff_read_from_str(ctx, str);
-	equal = isl_union_pw_aff_plain_is_equal(upa, upa2);
-	isl_union_pw_aff_free(upa2);
-
-	return equal;
-}
+#undef BASE
+#define BASE	aff
+#include "isl_test_plain_equal_templ.c"
 
-/* Check that "upa" is obviously equal to the isl_union_pw_aff
- * represented by "str".
- */
-static isl_stat union_pw_aff_check_plain_equal(__isl_keep isl_union_pw_aff *upa,
-	const char *str)
-{
-	isl_bool equal;
+#undef BASE
+#define BASE	pw_multi_aff
+#include "isl_test_plain_equal_templ.c"
 
-	equal = union_pw_aff_plain_is_equal(upa, str);
-	if (equal < 0)
-		return isl_stat_error;
-	if (!equal)
-		isl_die(isl_union_pw_aff_get_ctx(upa), isl_error_unknown,
-			"result not as expected", return isl_stat_error);
-	return isl_stat_ok;
-}
+#undef BASE
+#define BASE	union_pw_aff
+#include "isl_test_plain_equal_templ.c"
 
 /* Basic tests on isl_union_pw_aff.
  *
@@ -5275,32 +5448,98 @@ static int test_bin_upma_fail(isl_ctx *ctx)
 	return 0;
 }
 
-/* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.
- * "fn" is the function that is tested.
- * "arg" is a string description of the input.
+/* Inputs for basic tests of binary operations on
+ * pairs of isl_union_pw_multi_aff and isl_union_set objects.
+ * "fn" is the function that is being tested.
+ * "arg1" and "arg2" are string descriptions of the inputs.
  * "res" is a string description of the expected result.
  */
 struct {
-	__isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);
-	const char *arg;
+	__isl_give isl_union_pw_multi_aff *(*fn)(
+		__isl_take isl_union_pw_multi_aff *upma,
+		__isl_take isl_union_set *uset);
+	const char *arg1;
+	const char *arg2;
 	const char *res;
-} mpa_un_tests[] = {
-	{ &isl_multi_pw_aff_range_factor_domain,
-	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
-	  "{ A[x] -> B[(1 : x >= 5)] }" },
-	{ &isl_multi_pw_aff_range_factor_range,
-	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
-	  "{ A[y] -> C[(2 : y <= 10)] }" },
-	{ &isl_multi_pw_aff_range_factor_domain,
-	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
-	  "{ A[x] -> B[(1 : x >= 5)] }" },
-	{ &isl_multi_pw_aff_range_factor_range,
-	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
-	  "{ A[y] -> C[] }" },
-	{ &isl_multi_pw_aff_range_factor_domain,
-	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
-	  "{ A[x] -> B[] }" },
-	{ &isl_multi_pw_aff_range_factor_range,
+} upma_uset_tests[] = {
+	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
+	  "{ A[i] -> B[i] }", "{ B[0] }",
+	  "{ }" },
+	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,
+	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
+	  "{ [A[1] -> B[1]] -> C[2] }" },
+	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
+	  "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",
+	  "{ [A[0] -> B[0]] -> C[1] }" },
+	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
+	  "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",
+	  "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },
+	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
+	  "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",
+	  "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },
+	{ &isl_union_pw_multi_aff_intersect_domain_wrapped_range,
+	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",
+	  "{ B[] }",
+	  "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },
+};
+
+/* Perform some basic tests of binary operations on
+ * pairs of isl_union_pw_multi_aff and isl_union_set objects.
+ */
+static isl_stat test_upma_uset(isl_ctx *ctx)
+{
+	int i;
+	isl_bool ok;
+	isl_union_pw_multi_aff *upma, *res;
+	isl_union_set *uset;
+
+	for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {
+		upma = isl_union_pw_multi_aff_read_from_str(ctx,
+						    upma_uset_tests[i].arg1);
+		uset = isl_union_set_read_from_str(ctx,
+						    upma_uset_tests[i].arg2);
+		res = isl_union_pw_multi_aff_read_from_str(ctx,
+						    upma_uset_tests[i].res);
+		upma = upma_uset_tests[i].fn(upma, uset);
+		ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);
+		isl_union_pw_multi_aff_free(upma);
+		isl_union_pw_multi_aff_free(res);
+		if (ok < 0)
+			return isl_stat_error;
+		if (!ok)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return isl_stat_error);
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.
+ * "fn" is the function that is tested.
+ * "arg" is a string description of the input.
+ * "res" is a string description of the expected result.
+ */
+struct {
+	__isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);
+	const char *arg;
+	const char *res;
+} mpa_un_tests[] = {
+	{ &isl_multi_pw_aff_range_factor_domain,
+	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
+	  "{ A[x] -> B[(1 : x >= 5)] }" },
+	{ &isl_multi_pw_aff_range_factor_range,
+	  "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",
+	  "{ A[y] -> C[(2 : y <= 10)] }" },
+	{ &isl_multi_pw_aff_range_factor_domain,
+	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
+	  "{ A[x] -> B[(1 : x >= 5)] }" },
+	{ &isl_multi_pw_aff_range_factor_range,
+	  "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",
+	  "{ A[y] -> C[] }" },
+	{ &isl_multi_pw_aff_range_factor_domain,
+	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
+	  "{ A[x] -> B[] }" },
+	{ &isl_multi_pw_aff_range_factor_range,
 	  "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",
 	  "{ A[y] -> C[(2 : y <= 10)] }" },
 	{ &isl_multi_pw_aff_range_factor_domain,
@@ -6238,93 +6477,658 @@ static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)
 {
 	isl_id *id;
 	isl_aff *aff;
-	int equal;
+	isl_stat equal;
+
+	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");
+	id = isl_id_alloc(ctx, "A", NULL);
+	aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);
+	equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");
+	isl_aff_free(aff);
+	if (equal < 0)
+		return isl_stat_error;
+
+	return isl_stat_ok;
+}
+
+/* Check that affine expressions get normalized on addition/subtraction.
+ * In particular, check that (final) unused integer divisions get removed
+ * such that an expression derived from expressions with integer divisions
+ * is found to be obviously equal to one that is created directly.
+ */
+static isl_stat test_aff_normalize(isl_ctx *ctx)
+{
+	isl_aff *aff, *aff2;
+	isl_stat ok;
+
+	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");
+	aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");
+	aff = isl_aff_sub(aff2, aff);
+	ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");
+	isl_aff_free(aff);
+
+	return ok;
+}
+
+int test_aff(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_space *space;
+	isl_local_space *ls;
+	isl_aff *aff;
+	int zero;
+	isl_stat equal;
+
+	if (test_upa(ctx) < 0)
+		return -1;
+	if (test_bin_aff(ctx) < 0)
+		return -1;
+	if (test_bin_pw_aff(ctx) < 0)
+		return -1;
+	if (test_bin_upma(ctx) < 0)
+		return -1;
+	if (test_bin_upma_fail(ctx) < 0)
+		return -1;
+	if (test_upma_uset(ctx) < 0)
+		return -1;
+	if (test_un_mpa(ctx) < 0)
+		return -1;
+	if (test_bin_mpa(ctx) < 0)
+		return -1;
+	if (test_un_mupa(ctx) < 0)
+		return -1;
+	if (test_bin_mupa(ctx) < 0)
+		return -1;
+	if (test_mupa_set(ctx) < 0)
+		return -1;
+	if (test_mupa_uset(ctx) < 0)
+		return -1;
+	if (test_mupa_ma(ctx) < 0)
+		return -1;
+	if (test_mupa_pa(ctx) < 0)
+		return -1;
+	if (test_mupa_pma(ctx) < 0)
+		return -1;
+	if (test_mupa_upma(ctx) < 0)
+		return -1;
+
+	space = isl_space_set_alloc(ctx, 0, 1);
+	ls = isl_local_space_from_space(space);
+	aff = isl_aff_zero_on_domain(ls);
+
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+	aff = isl_aff_scale_down_ui(aff, 3);
+	aff = isl_aff_floor(aff);
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+	aff = isl_aff_scale_down_ui(aff, 2);
+	aff = isl_aff_floor(aff);
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+
+	str = "{ [10] }";
+	set = isl_set_read_from_str(ctx, str);
+	aff = isl_aff_gist(aff, set);
+
+	aff = isl_aff_add_constant_si(aff, -16);
+	zero = isl_aff_plain_is_zero(aff);
+	isl_aff_free(aff);
+
+	if (zero < 0)
+		return -1;
+	if (!zero)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	aff = isl_aff_read_from_str(ctx, "{ [-1] }");
+	aff = isl_aff_scale_down_ui(aff, 64);
+	aff = isl_aff_floor(aff);
+	equal = aff_check_plain_equal(aff, "{ [-1] }");
+	isl_aff_free(aff);
+	if (equal < 0)
+		return -1;
+
+	if (test_aff_set_tuple_id(ctx) < 0)
+		return -1;
+	if (test_aff_normalize(ctx) < 0)
+		return -1;
+
+	return 0;
+}
+
+/* Inputs for isl_set_bind tests.
+ * "set" is the input set.
+ * "tuple" is the binding tuple.
+ * "res" is the expected result.
+ */
+static
+struct {
+	const char *set;
+	const char *tuple;
+	const char *res;
+} bind_set_tests[] = {
+	{ "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ A[M, N] }",
+	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
+	{ "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ B[N, M] }",
+	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
+	{ "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ C[N] }",
+	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },
+	{ "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",
+	  "{ D[M, N] }",
+	  "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },
+};
+
+/* Perform basic isl_set_bind tests.
+ */
+static isl_stat test_bind_set(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {
+		const char *str;
+		isl_set *set;
+		isl_multi_id *tuple;
+		isl_stat r;
+
+		set = isl_set_read_from_str(ctx, bind_set_tests[i].set);
+		str = bind_set_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		set = isl_set_bind(set, tuple);
+		r = set_check_equal(set, bind_set_tests[i].res);
+		isl_set_free(set);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for isl_map_bind_domain tests.
+ * "map" is the input map.
+ * "tuple" is the binding tuple.
+ * "res" is the expected result.
+ */
+struct {
+	const char *map;
+	const char *tuple;
+	const char *res;
+} bind_map_domain_tests[] = {
+	{ "{ A[M, N] -> [M + floor(N/2)] }",
+	  "{ A[M, N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "{ B[N, M] -> [M + floor(N/2)] }",
+	  "{ B[N, M] }",
+	  "[N, M] -> { [M + floor(N/2)] }" },
+	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
+	  "{ C[N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
+	  "{ C[M, N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
+	  "{ C[M, N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
+	  "{ C[N, M] }",
+	  "[A, N, M] -> { [M + floor(N/2)] }" },
+};
+
+/* Perform basic isl_map_bind_domain tests.
+ */
+static isl_stat test_bind_map_domain(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {
+		const char *str;
+		isl_map *map;
+		isl_set *set;
+		isl_multi_id *tuple;
+		isl_stat r;
+
+		str = bind_map_domain_tests[i].map;
+		map = isl_map_read_from_str(ctx, str);
+		str = bind_map_domain_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		set = isl_map_bind_domain(map, tuple);
+		str = bind_map_domain_tests[i].res;
+		r = set_check_equal(set, str);
+		isl_set_free(set);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for isl_union_map_bind_range tests.
+ * "map" is the input union map.
+ * "tuple" is the binding tuple.
+ * "res" is the expected result.
+ */
+struct {
+	const char *map;
+	const char *tuple;
+	const char *res;
+} bind_umap_range_tests[] = {
+	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ A[M, N] }",
+	  "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
+	{ "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ B[M, N] }",
+	  "{ }" },
+	{ "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",
+	  "{ B[] }",
+	  "{ A[]; E[] }" },
+};
+
+/* Perform basic isl_union_map_bind_range tests.
+ */
+static isl_stat test_bind_umap_range(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {
+		const char *str;
+		isl_union_map *umap;
+		isl_union_set *uset;
+		isl_multi_id *tuple;
+		isl_stat r;
+
+		str = bind_umap_range_tests[i].map;
+		umap = isl_union_map_read_from_str(ctx, str);
+		str = bind_umap_range_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		uset = isl_union_map_bind_range(umap, tuple);
+		str = bind_umap_range_tests[i].res;
+		r = uset_check_equal(uset, str);
+		isl_union_set_free(uset);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for isl_pw_multi_aff_bind_domain tests.
+ * "pma" is the input expression.
+ * "tuple" is the binding tuple.
+ * "res" is the expected result.
+ */
+struct {
+	const char *pma;
+	const char *tuple;
+	const char *res;
+} bind_pma_domain_tests[] = {
+	{ "{ A[M, N] -> [M + floor(N/2)] }",
+	  "{ A[M, N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "{ B[N, M] -> [M + floor(N/2)] }",
+	  "{ B[N, M] }",
+	  "[N, M] -> { [M + floor(N/2)] }" },
+	{ "[M] -> { C[N] -> [M + floor(N/2)] }",
+	  "{ C[N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "[M] -> { C[x, N] -> [x + floor(N/2)] }",
+	  "{ C[M, N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "[M] -> { C[x, N] -> [M + floor(N/2)] }",
+	  "{ C[M, N] }",
+	  "[M, N] -> { [M + floor(N/2)] }" },
+	{ "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",
+	  "{ C[N, M] }",
+	  "[A, N, M] -> { [M + floor(N/2)] }" },
+};
+
+/* Perform basic isl_pw_multi_aff_bind_domain tests.
+ */
+static isl_stat test_bind_pma_domain(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {
+		const char *str;
+		isl_pw_multi_aff *pma;
+		isl_multi_id *tuple;
+		isl_stat r;
+
+		str = bind_pma_domain_tests[i].pma;
+		pma = isl_pw_multi_aff_read_from_str(ctx, str);
+		str = bind_pma_domain_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		pma = isl_pw_multi_aff_bind_domain(pma, tuple);
+		str = bind_pma_domain_tests[i].res;
+		r = pw_multi_aff_check_plain_equal(pma, str);
+		isl_pw_multi_aff_free(pma);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.
+ * "pma" is the input expression.
+ * "tuple" is the binding tuple.
+ * "res" is the expected result.
+ */
+struct {
+	const char *pma;
+	const char *tuple;
+	const char *res;
+} bind_pma_domain_wrapped_tests[] = {
+	{ "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",
+	  "{ A[M, N] }",
+	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
+	{ "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",
+	  "{ B[N, M] }",
+	  "[N, M] -> { D[] -> [M + floor(N/2)] }" },
+	{ "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",
+	  "{ C[N] }",
+	  "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },
+	{ "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",
+	  "{ C[M, N] }",
+	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
+	{ "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",
+	  "{ C[M, N] }",
+	  "[M, N] -> { B[] -> [M + floor(N/2)] }" },
+	{ "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",
+	  "{ C[N, M] }",
+	  "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },
+};
+
+/* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.
+ */
+static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {
+		const char *str;
+		isl_pw_multi_aff *pma;
+		isl_multi_id *tuple;
+		isl_stat r;
+
+		str = bind_pma_domain_wrapped_tests[i].pma;
+		pma = isl_pw_multi_aff_read_from_str(ctx, str);
+		str = bind_pma_domain_wrapped_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);
+		str = bind_pma_domain_wrapped_tests[i].res;
+		r = pw_multi_aff_check_plain_equal(pma, str);
+		isl_pw_multi_aff_free(pma);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for isl_aff_bind_id tests.
+ * "aff" is the input expression.
+ * "id" is the binding id.
+ * "res" is the expected result.
+ */
+static
+struct {
+	const char *aff;
+	const char *id;
+	const char *res;
+} bind_aff_tests[] = {
+	{ "{ [4] }", "M", "[M = 4] -> { : }" },
+	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
+	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
+	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
+	{ "{ [NaN] }", "M", "{ : false }" },
+	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
+};
+
+/* Perform basic isl_aff_bind_id tests.
+ */
+static isl_stat test_bind_aff(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {
+		isl_aff *aff;
+		isl_set *res;
+		isl_id *id;
+		isl_stat r;
+
+		aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);
+		id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);
+		res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));
+		r = set_check_equal(res, bind_aff_tests[i].res);
+		isl_set_free(res);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for isl_pw_aff_bind_id tests.
+ * "pa" is the input expression.
+ * "id" is the binding id.
+ * "res" is the expected result.
+ */
+static
+struct {
+	const char *pa;
+	const char *id;
+	const char *res;
+} bind_pa_tests[] = {
+	{ "{ [4] }", "M", "[M = 4] -> { : }" },
+	{ "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },
+	{ "[M] -> { [4] }", "M", "[M = 4] -> { : }" },
+	{ "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },
+	{ "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },
+	{ "{ [NaN] }", "M", "{ : false }" },
+	{ "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },
+};
+
+/* Perform basic isl_pw_aff_bind_id tests.
+ */
+static isl_stat test_bind_pa(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {
+		isl_pw_aff *pa;
+		isl_set *res;
+		isl_id *id;
+		isl_stat r;
+
+		pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);
+		id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);
+		res = isl_pw_aff_bind_id(pa, id);
+		r = set_check_equal(res, bind_pa_tests[i].res);
+		isl_set_free(res);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for isl_multi_union_pw_aff_bind tests.
+ * "mupa" is the input expression.
+ * "tuple" is the binding tuple.
+ * "res" is the expected result.
+ */
+static
+struct {
+	const char *mupa;
+	const char *tuple;
+	const char *res;
+} bind_mupa_tests[] = {
+	{ "A[{ [4] }, { [5] }]",
+	  "{ A[M, N] }",
+	  "[M = 4, N = 5] -> { : }" },
+	{ "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",
+	  "{ A[M, N] }",
+	  "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },
+	{ "[M] -> A[{ [4] }, { [M + 1] }]",
+	  "{ A[M, N] }",
+	  "[M = 4, N = 5] -> { : }" },
+};
+
+/* Perform basic isl_multi_union_pw_aff_bind tests.
+ */
+static isl_stat test_bind_mupa(isl_ctx *ctx)
+{
+	int i;
 
-	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");
-	id = isl_id_alloc(ctx, "A", NULL);
-	aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);
-	equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");
-	isl_aff_free(aff);
-	if (equal < 0)
-		return isl_stat_error;
+	for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {
+		const char *str;
+		isl_multi_union_pw_aff *mupa;
+		isl_union_set *res;
+		isl_multi_id *tuple;
+		isl_stat r;
+
+		str = bind_mupa_tests[i].mupa;
+		mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
+		str = bind_mupa_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		res = isl_multi_union_pw_aff_bind(mupa, tuple);
+		r = uset_check_equal(res, bind_mupa_tests[i].res);
+		isl_union_set_free(res);
+		if (r < 0)
+			return isl_stat_error;
+	}
 
 	return isl_stat_ok;
 }
 
-int test_aff(isl_ctx *ctx)
+/* Perform tests that reinterpret dimensions as parameters.
+ */
+static int test_bind(isl_ctx *ctx)
 {
-	const char *str;
-	isl_set *set;
-	isl_space *space;
-	isl_local_space *ls;
-	isl_aff *aff;
-	int zero, equal;
-
-	if (test_upa(ctx) < 0)
-		return -1;
-	if (test_bin_aff(ctx) < 0)
-		return -1;
-	if (test_bin_pw_aff(ctx) < 0)
-		return -1;
-	if (test_bin_upma(ctx) < 0)
-		return -1;
-	if (test_bin_upma_fail(ctx) < 0)
-		return -1;
-	if (test_un_mpa(ctx) < 0)
-		return -1;
-	if (test_bin_mpa(ctx) < 0)
-		return -1;
-	if (test_un_mupa(ctx) < 0)
+	if (test_bind_set(ctx) < 0)
 		return -1;
-	if (test_bin_mupa(ctx) < 0)
+	if (test_bind_map_domain(ctx) < 0)
 		return -1;
-	if (test_mupa_set(ctx) < 0)
+	if (test_bind_umap_range(ctx) < 0)
 		return -1;
-	if (test_mupa_uset(ctx) < 0)
+	if (test_bind_pma_domain(ctx) < 0)
 		return -1;
-	if (test_mupa_ma(ctx) < 0)
+	if (test_bind_pma_domain_wrapped(ctx) < 0)
 		return -1;
-	if (test_mupa_pa(ctx) < 0)
+	if (test_bind_aff(ctx) < 0)
 		return -1;
-	if (test_mupa_pma(ctx) < 0)
+	if (test_bind_pa(ctx) < 0)
 		return -1;
-	if (test_mupa_upma(ctx) < 0)
+	if (test_bind_mupa(ctx) < 0)
 		return -1;
 
-	space = isl_space_set_alloc(ctx, 0, 1);
-	ls = isl_local_space_from_space(space);
-	aff = isl_aff_zero_on_domain(ls);
+	return 0;
+}
 
-	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
-	aff = isl_aff_scale_down_ui(aff, 3);
-	aff = isl_aff_floor(aff);
-	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
-	aff = isl_aff_scale_down_ui(aff, 2);
-	aff = isl_aff_floor(aff);
-	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+/* Inputs for isl_set_unbind_params tests.
+ * "set" is the input parameter domain.
+ * "tuple" is the tuple of the constructed set.
+ * "res" is the expected result.
+ */
+struct {
+	const char *set;
+	const char *tuple;
+	const char *res;
+} unbind_set_tests[] = {
+	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ A[M, N] }",
+	  "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },
+	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ B[N, M] }",
+	  "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },
+	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ C[N] }",
+	  "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },
+	{ "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",
+	  "{ D[T, N] }",
+	  "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },
+};
 
-	str = "{ [10] }";
-	set = isl_set_read_from_str(ctx, str);
-	aff = isl_aff_gist(aff, set);
+/* Perform basic isl_set_unbind_params tests.
+ */
+static isl_stat test_unbind_set(isl_ctx *ctx)
+{
+	int i;
 
-	aff = isl_aff_add_constant_si(aff, -16);
-	zero = isl_aff_plain_is_zero(aff);
-	isl_aff_free(aff);
+	for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {
+		const char *str;
+		isl_set *set;
+		isl_multi_id *tuple;
+		isl_stat r;
 
-	if (zero < 0)
-		return -1;
-	if (!zero)
-		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+		set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);
+		str = unbind_set_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		set = isl_set_unbind_params(set, tuple);
+		r = set_check_equal(set, unbind_set_tests[i].res);
+		isl_set_free(set);
+		if (r < 0)
+			return isl_stat_error;
+	}
 
-	aff = isl_aff_read_from_str(ctx, "{ [-1] }");
-	aff = isl_aff_scale_down_ui(aff, 64);
-	aff = isl_aff_floor(aff);
-	equal = aff_check_plain_equal(aff, "{ [-1] }");
-	isl_aff_free(aff);
-	if (equal < 0)
-		return -1;
+	return isl_stat_ok;
+}
 
-	if (test_aff_set_tuple_id(ctx) < 0)
+/* Inputs for isl_aff_unbind_params_insert_domain tests.
+ * "aff" is the input affine expression defined over a parameter domain.
+ * "tuple" is the tuple of the domain that gets introduced.
+ * "res" is the expected result.
+ */
+struct {
+	const char *aff;
+	const char *tuple;
+	const char *res;
+} unbind_aff_tests[] = {
+	{ "[M, N] -> { [M + floor(N/2)] }",
+	  "{ A[M, N] }",
+	  "{ A[M, N] -> [M + floor(N/2)] }" },
+	{ "[M, N] -> { [M + floor(N/2)] }",
+	  "{ B[N, M] }",
+	  "{ B[N, M] -> [M + floor(N/2)] }" },
+	{ "[M, N] -> { [M + floor(N/2)] }",
+	  "{ C[N] }",
+	  "[M] -> { C[N] -> [M + floor(N/2)] }" },
+	{ "[M, N] -> { [M + floor(N/2)] }",
+	  "{ D[A, B, C, N, Z] }",
+	  "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },
+};
+
+/* Perform basic isl_aff_unbind_params_insert_domain tests.
+ */
+static isl_stat test_unbind_aff(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {
+		const char *str;
+		isl_aff *aff;
+		isl_multi_id *tuple;
+		isl_stat r;
+
+		aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);
+		str = unbind_aff_tests[i].tuple;
+		tuple = isl_multi_id_read_from_str(ctx, str);
+		aff = isl_aff_unbind_params_insert_domain(aff, tuple);
+		r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);
+		isl_aff_free(aff);
+		if (r < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
+/* Perform tests that reinterpret parameters.
+ */
+static int test_unbind(isl_ctx *ctx)
+{
+	if (test_unbind_set(ctx) < 0)
+		return -1;
+	if (test_unbind_aff(ctx) < 0)
 		return -1;
 
 	return 0;
@@ -6334,12 +7138,12 @@ int test_aff(isl_ctx *ctx)
  */
 static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)
 {
-	int n;
+	isl_size n;
 
 	n = isl_pw_aff_n_piece(pa);
 	isl_pw_aff_free(pa);
 
-	if (!pa)
+	if (n < 0)
 		return -1;
 	if (n != 1)
 		isl_die(ctx, isl_error_unknown, "expecting single expression",
@@ -6511,50 +7315,13 @@ int test_dim_max(isl_ctx *ctx)
 	return 0;
 }
 
-/* Is "pma" obviously equal to the isl_pw_multi_aff represented by "str"?
- */
-static int pw_multi_aff_plain_is_equal(__isl_keep isl_pw_multi_aff *pma,
-	const char *str)
-{
-	isl_ctx *ctx;
-	isl_pw_multi_aff *pma2;
-	int equal;
-
-	if (!pma)
-		return -1;
-
-	ctx = isl_pw_multi_aff_get_ctx(pma);
-	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
-	equal = isl_pw_multi_aff_plain_is_equal(pma, pma2);
-	isl_pw_multi_aff_free(pma2);
-
-	return equal;
-}
-
-/* Check that "pma" is obviously equal to the isl_pw_multi_aff
- * represented by "str".
- */
-static int pw_multi_aff_check_plain_equal(__isl_keep isl_pw_multi_aff *pma,
-	const char *str)
-{
-	int equal;
-
-	equal = pw_multi_aff_plain_is_equal(pma, str);
-	if (equal < 0)
-		return -1;
-	if (!equal)
-		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_unknown,
-			"result not as expected", return -1);
-	return 0;
-}
-
 /* Basic test for isl_pw_multi_aff_product.
  *
  * Check that multiple pieces are properly handled.
  */
 static int test_product_pma(isl_ctx *ctx)
 {
-	int equal;
+	isl_stat equal;
 	const char *str;
 	isl_pw_multi_aff *pma1, *pma2;
 
@@ -6799,7 +7566,7 @@ int test_vertices(isl_ctx *ctx)
 		isl_basic_set *bset;
 		isl_vertices *vertices;
 		int ok = 1;
-		int n;
+		isl_size n;
 
 		bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
 		vertices = isl_basic_set_compute_vertices(bset);
@@ -6812,7 +7579,7 @@ int test_vertices(isl_ctx *ctx)
 		isl_vertices_free(vertices);
 		isl_basic_set_free(bset);
 
-		if (!vertices)
+		if (n < 0)
 			return -1;
 		if (!ok)
 			isl_die(ctx, isl_error_unknown, "unexpected vertices",
@@ -6822,6 +7589,152 @@ int test_vertices(isl_ctx *ctx)
 	return 0;
 }
 
+/* Inputs for basic tests of unary operations on isl_union_map.
+ * "fn" is the function that is being tested.
+ * "arg" is a string description of the input.
+ * "res" is a string description of the expected result.
+ */
+static struct {
+	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap);
+	const char *arg;
+	const char *res;
+} umap_un_tests[] = {
+	{ &isl_union_map_range_reverse,
+	  "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",
+	  "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },
+	{ &isl_union_map_range_reverse,
+	  "{ A[] -> N[B[] -> C[]] }",
+	  "{ A[] -> [C[] -> B[]] }" },
+	{ &isl_union_map_range_reverse,
+	  "{ A[] -> N[B[x] -> B[y]] }",
+	  "{ A[] -> N[B[*] -> B[*]] }" },
+};
+
+/* Perform basic tests of unary operations on isl_union_map.
+ */
+static isl_stat test_un_union_map(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(umap_un_tests); ++i) {
+		const char *str;
+		isl_union_map *umap, *res;
+		isl_bool equal;
+
+		str = umap_un_tests[i].arg;
+		umap = isl_union_map_read_from_str(ctx, str);
+		str = umap_un_tests[i].res;
+		res = isl_union_map_read_from_str(ctx, str);
+		umap = umap_un_tests[i].fn(umap);
+		equal = isl_union_map_is_equal(umap, res);
+		isl_union_map_free(umap);
+		isl_union_map_free(res);
+		if (equal < 0)
+			return isl_stat_error;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return isl_stat_error);
+	}
+
+	return isl_stat_ok;
+}
+
+/* Inputs for basic tests of binary operations on isl_union_map.
+ * "fn" is the function that is being tested.
+ * "arg1" and "arg2" are string descriptions of the inputs.
+ * "res" is a string description of the expected result.
+ */
+static struct {
+	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,
+				__isl_take isl_union_map *umap2);
+	const char *arg1;
+	const char *arg2;
+	const char *res;
+} umap_bin_tests[] = {
+	{ &isl_union_map_intersect,
+	  "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",
+	  "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",
+	  "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },
+	{ &isl_union_map_intersect_domain_factor_range,
+	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
+	  "[N] -> { B[i] -> C[N] }",
+	  "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },
+	{ &isl_union_map_intersect_domain_factor_range,
+	  "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",
+	  "[N] -> { B[i] -> C[N] }",
+	  "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },
+	{ &isl_union_map_intersect_domain_factor_range,
+	  "{ [A[i] -> B[i + 1]] -> C[i + 2] }",
+	  "[N] -> { A[i] -> C[N] }",
+	  "{ }" },
+	{ &isl_union_map_intersect_range_factor_domain,
+	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
+	  "[N] -> { A[i] -> B[N] }",
+	  "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },
+	{ &isl_union_map_intersect_range_factor_domain,
+	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
+	  "[N] -> { A[i] -> B[N] }",
+	  "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },
+	{ &isl_union_map_intersect_range_factor_domain,
+	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
+	  "[N] -> { A[i] -> C[N] }",
+	  "{ }" },
+	{ &isl_union_map_intersect_range_factor_range,
+	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
+	  "[N] -> { A[i] -> C[N] }",
+	  "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },
+	{ &isl_union_map_intersect_range_factor_range,
+	  "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",
+	  "[N] -> { A[i] -> C[N] }",
+	  "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },
+	{ &isl_union_map_intersect_range_factor_range,
+	  "{ A[i] -> [B[i + 1] -> C[i + 2]] }",
+	  "[N] -> { A[i] -> B[N] }",
+	  "{ }" },
+};
+
+/* Perform basic tests of binary operations on isl_union_map.
+ */
+static isl_stat test_bin_union_map(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {
+		const char *str;
+		isl_union_map *umap1, *umap2, *res;
+		isl_bool equal;
+
+		str = umap_bin_tests[i].arg1;
+		umap1 = isl_union_map_read_from_str(ctx, str);
+		str = umap_bin_tests[i].arg2;
+		umap2 = isl_union_map_read_from_str(ctx, str);
+		str = umap_bin_tests[i].res;
+		res = isl_union_map_read_from_str(ctx, str);
+		umap1 = umap_bin_tests[i].fn(umap1, umap2);
+		equal = isl_union_map_is_equal(umap1, res);
+		isl_union_map_free(umap1);
+		isl_union_map_free(res);
+		if (equal < 0)
+			return isl_stat_error;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return isl_stat_error);
+	}
+
+	return isl_stat_ok;
+}
+
+/* Perform basic tests of operations on isl_union_map.
+ */
+static int test_union_map(isl_ctx *ctx)
+{
+	if (test_un_union_map(ctx) < 0)
+		return -1;
+	if (test_bin_union_map(ctx) < 0)
+		return -1;
+	return 0;
+}
+
 int test_union_pw(isl_ctx *ctx)
 {
 	int equal;
@@ -7064,6 +7977,27 @@ static int test_eval_2(isl_ctx *ctx)
 	return 0;
 }
 
+/* Check that a polynomial (without local variables) can be evaluated
+ * in a rational point.
+ */
+static isl_stat test_eval_3(isl_ctx *ctx)
+{
+	isl_pw_qpolynomial *pwqp;
+	isl_point *pnt;
+	isl_val *v;
+	isl_stat r;
+
+	pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");
+	pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));
+	v = isl_val_read_from_str(ctx, "1/2");
+	pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);
+	v = isl_pw_qpolynomial_eval(pwqp, pnt);
+	r = val_check_equal(v, "1/4");
+	isl_val_free(v);
+
+	return r;
+}
+
 /* Inputs for isl_pw_aff_eval test.
  * "f" is the affine function.
  * "p" is the point where the function should be evaluated.
@@ -7132,6 +8066,8 @@ static int test_eval(isl_ctx *ctx)
 		return -1;
 	if (test_eval_2(ctx) < 0)
 		return -1;
+	if (test_eval_3(ctx) < 0)
+		return -1;
 	if (test_eval_aff(ctx) < 0)
 		return -1;
 	return 0;
@@ -7415,6 +8351,25 @@ int test_eliminate(isl_ctx *ctx)
 	return 0;
 }
 
+/* Check basic functionality of isl_map_deltas_map.
+ */
+static int test_deltas_map(isl_ctx *ctx)
+{
+	const char *str;
+	isl_map *map;
+	int equal;
+
+	str = "{ A[i] -> A[i + 1] }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_deltas_map(map);
+	equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	return 0;
+}
+
 /* Check that isl_set_dim_residue_class detects that the values of j
  * in the set below are all odd and that it does not detect any spurious
  * strides.
@@ -7573,6 +8528,7 @@ static int test_list(isl_ctx *ctx)
 {
 	isl_id *a, *b, *c, *d, *id;
 	isl_id_list *list;
+	isl_size n;
 	int ok;
 
 	a = isl_id_alloc(ctx, "a", NULL);
@@ -7587,9 +8543,10 @@ static int test_list(isl_ctx *ctx)
 	list = isl_id_list_add(list, d);
 	list = isl_id_list_drop(list, 1, 1);
 
-	if (!list)
+	n = isl_id_list_n_id(list);
+	if (n < 0)
 		return -1;
-	if (isl_id_list_n_id(list) != 3) {
+	if (n != 3) {
 		isl_id_list_free(list);
 		isl_die(ctx, isl_error_unknown,
 			"unexpected number of elements in list", return -1);
@@ -7614,6 +8571,30 @@ static int test_list(isl_ctx *ctx)
 	return 0;
 }
 
+/* Check the conversion from an isl_multi_aff to an isl_basic_set.
+ */
+static isl_stat test_ma_conversion(isl_ctx *ctx)
+{
+	const char *str;
+	isl_bool equal;
+	isl_multi_aff *ma;
+	isl_basic_set *bset1, *bset2;
+
+	str = "[N] -> { A[0, N + 1] }";
+	ma = isl_multi_aff_read_from_str(ctx, str);
+	bset1 = isl_basic_set_read_from_str(ctx, str);
+	bset2 = isl_basic_set_from_multi_aff(ma);
+	equal = isl_basic_set_is_equal(bset1, bset2);
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	if (equal < 0)
+		return isl_stat_error;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "bad conversion",
+			return isl_stat_error);
+	return isl_stat_ok;
+}
+
 const char *set_conversion_tests[] = {
 	"[N] -> { [i] : N - 1 <= 2 i <= N }",
 	"[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
@@ -7786,6 +8767,8 @@ static int test_union_map_mupa_conversion(isl_ctx *ctx)
 
 static int test_conversion(isl_ctx *ctx)
 {
+	if (test_ma_conversion(ctx) < 0)
+		return -1;
 	if (test_set_conversion(ctx) < 0)
 		return -1;
 	if (test_map_conversion(ctx) < 0)
@@ -8105,7 +9088,8 @@ static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
 	isl_union_map *schedule;
 	isl_union_set *uset;
 	isl_set *set;
-	int empty;
+	isl_bool empty;
+	isl_size n;
 	char name[] = "d0";
 
 	ctx = isl_ast_build_get_ctx(build);
@@ -8123,10 +9107,11 @@ static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
 
 	schedule = isl_ast_build_get_schedule(build);
 	uset = isl_union_map_range(schedule);
-	if (!uset)
-		return NULL;
-	if (isl_union_set_n_set(uset) != 1) {
+	n = isl_union_set_n_set(uset);
+	if (n != 1) {
 		isl_union_set_free(uset);
+		if (n < 0)
+			return NULL;
 		isl_die(ctx, isl_error_unknown,
 			"expecting single range space", return NULL);
 	}
@@ -8462,7 +9447,7 @@ static int test_ast_expr(isl_ctx *ctx)
 	build = isl_ast_build_alloc(ctx);
 	expr = isl_ast_build_expr_from_pw_aff(build, pa);
 	is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&
-		 isl_ast_expr_get_op_type(expr) == isl_ast_op_min;
+		 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;
 	isl_ast_build_free(build);
 	isl_ast_expr_free(expr);
 
@@ -9254,12 +10239,13 @@ static isl_stat add_cell(__isl_take isl_cell *cell, void *user)
  */
 static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)
 {
-	int i, j, n;
+	int i, j;
+	isl_size n;
 
-	if (!list)
+	n = isl_basic_set_list_n_basic_set(list);
+	if (n < 0)
 		return isl_stat_error;
 
-	n = isl_basic_set_list_n_basic_set(list);
 	for (i = 0; i < n; ++i) {
 		isl_basic_set *bset_i;
 
@@ -9342,6 +10328,7 @@ struct {
 	{ "AST build", &test_ast_build },
 	{ "AST generation", &test_ast_gen },
 	{ "eliminate", &test_eliminate },
+	{ "deltas_map", &test_deltas_map },
 	{ "residue class", &test_residue_class },
 	{ "div", &test_div },
 	{ "slice", &test_slice },
@@ -9363,13 +10350,16 @@ struct {
 	{ "schedule tree prefix", &test_schedule_tree_prefix },
 	{ "schedule tree grouping", &test_schedule_tree_group },
 	{ "tile", &test_tile },
+	{ "union map", &test_union_map },
 	{ "union_pw", &test_union_pw },
 	{ "locus", &test_locus },
 	{ "eval", &test_eval },
 	{ "parse", &test_parse },
 	{ "single-valued", &test_sv },
+	{ "recession cone", &test_recession_cone },
 	{ "affine hull", &test_affine_hull },
 	{ "simple_hull", &test_simple_hull },
+	{ "box hull", &test_box_hull },
 	{ "coalesce", &test_coalesce },
 	{ "factorize", &test_factorize },
 	{ "subset", &test_subset },
@@ -9380,6 +10370,8 @@ struct {
 	{ "gist", &test_gist },
 	{ "piecewise quasi-polynomials", &test_pwqp },
 	{ "lift", &test_lift },
+	{ "bind parameters", &test_bind },
+	{ "unbind parameters", &test_unbind },
 	{ "bound", &test_bound },
 	{ "get lists", &test_get_list },
 	{ "union", &test_union },
@@ -9394,6 +10386,7 @@ struct {
 	{ "map application", &test_application },
 	{ "convex hull", &test_convex_hull },
 	{ "transitive closure", &test_closure },
+	{ "isl_bool", &test_isl_bool},
 };
 
 int main(int argc, char **argv)

diff  --git a/polly/lib/External/isl/isl_test_cpp-checked.cc b/polly/lib/External/isl/isl_test_cpp-checked.cc
index 84bb01a953a3..1f74e7f9cb67 100644
--- a/polly/lib/External/isl/isl_test_cpp-checked.cc
+++ b/polly/lib/External/isl/isl_test_cpp-checked.cc
@@ -32,8 +32,16 @@ static void assert_impl(isl::boolean condition, const char *file, int line,
 	assert_impl(bool(condition), file, line, message);
 }
 
+/* Return the value encapsulated by "s".
+ */
+static int size_val(isl::size s)
+{
+	return s.is_error() ? -1 : unsigned(s);
+}
+
 #define assert(exp) assert_impl(exp, __FILE__, __LINE__, #exp)
 #define IS_TRUE(b)	(b).is_true()
+#define SIZE_VAL(s)	size_val(s)
 
 #include "isl_test_cpp-generic.cc"
 
@@ -151,6 +159,121 @@ void test_foreach(isl::ctx ctx)
 	assert(ret2.is_error());
 }
 
+/* Test the functionality of "every" functions.
+ *
+ * In particular, test the generic functionality and
+ * test that error conditions are properly propagated.
+ */
+static void test_every(isl::ctx ctx)
+{
+	isl::union_set us(ctx, "{ A[i]; B[j] }");
+
+	test_every_generic(ctx);
+
+	auto fail = [] (isl::set s){
+		return isl::boolean::error();
+	};
+	assert(us.every_set(fail).is_error());
+}
+
+/* Test basic schedule tree functionality.
+ *
+ * In particular, create a simple schedule tree and
+ * - perform some generic tests
+ * - test map_descendant_bottom_up in the failing case
+ * - test foreach_descendant_top_down
+ * - test every_descendant
+ */
+static void test_schedule_tree(isl::ctx ctx)
+{
+	auto root = test_schedule_tree_generic(ctx);
+
+	auto fail_map = [](isl::schedule_node node) {
+		return isl::schedule_node();
+	};
+	assert(root.map_descendant_bottom_up(fail_map).is_null());
+
+	int count = 0;
+	auto inc_count = [&count](isl::schedule_node node) {
+		count++;
+		return isl::boolean(true);
+	};
+	assert(root.foreach_descendant_top_down(inc_count).is_ok());
+	assert(count == 8);
+
+	count = 0;
+	auto inc_count_once = [&count](isl::schedule_node node) {
+		count++;
+		return isl::boolean(false);
+	};
+	assert(root.foreach_descendant_top_down(inc_count_once).is_ok());
+	assert(count == 1);
+
+	auto is_not_domain = [](isl::schedule_node node) {
+		return !node.isa<isl::schedule_node_domain>();
+	};
+	assert(root.child(0).every_descendant(is_not_domain).is_true());
+	assert(root.every_descendant(is_not_domain).is_false());
+
+	auto fail = [](isl::schedule_node node) {
+		return isl::boolean();
+	};
+	assert(root.every_descendant(fail).is_error());
+
+	auto domain = root.as<isl::schedule_node_domain>().domain();
+	auto filters = isl::union_set(ctx, "{}");
+	auto collect_filters = [&filters](isl::schedule_node node) {
+		if (node.isa<isl::schedule_node_filter>().is_true()) {
+			auto filter = node.as<isl::schedule_node_filter>();
+			filters = filters.unite(filter.filter());
+		}
+		return isl::boolean(true);
+	};
+	assert(!root.every_descendant(collect_filters).is_error());
+	assert(domain.is_equal(filters).is_true());
+}
+
+/* Test basic AST generation from a schedule tree.
+ *
+ * In particular, create a simple schedule tree and
+ * - perform some generic tests
+ * - test at_each_domain in the failing case
+ */
+static void test_ast_build(isl::ctx ctx)
+{
+	auto schedule = test_ast_build_generic(ctx);
+
+	bool do_fail = true;
+	int count_ast_fail = 0;
+	auto fail_inc_count_ast =
+	    [&count_ast_fail, &do_fail](isl::ast_node node,
+					isl::ast_build build) {
+		count_ast_fail++;
+		return do_fail ? isl::ast_node() : node;
+	};
+	auto build = isl::ast_build(ctx);
+	build = build.set_at_each_domain(fail_inc_count_ast);
+	auto ast = build.node_from(schedule);
+	assert(ast.is_null());
+	assert(count_ast_fail > 0);
+	auto build_copy = build;
+	int count_ast = 0;
+	auto inc_count_ast =
+	    [&count_ast](isl::ast_node node, isl::ast_build build) {
+		count_ast++;
+		return node;
+	};
+	build_copy = build_copy.set_at_each_domain(inc_count_ast);
+	ast = build_copy.node_from(schedule);
+	assert(!ast.is_null());
+	assert(count_ast == 2);
+	count_ast_fail = 0;
+	do_fail = false;
+	ast = build.node_from(schedule);
+	assert(!ast.is_null());
+	assert(count_ast_fail == 2);
+}
+
 /* Test the isl checked C++ interface
  *
  * This includes:
@@ -159,6 +282,11 @@ void test_foreach(isl::ctx ctx)
  *  - Different parameter types
  *  - Different return types
  *  - Foreach functions
+ *  - Every functions
+ *  - Spaces
+ *  - Schedule trees
+ *  - AST generation
+ *  - AST expression generation
  */
 int main()
 {
@@ -171,6 +299,11 @@ int main()
 	test_parameters(ctx);
 	test_return(ctx);
 	test_foreach(ctx);
+	test_every(ctx);
+	test_space(ctx);
+	test_schedule_tree(ctx);
+	test_ast_build(ctx);
+	test_ast_build_expr(ctx);
 
 	isl_ctx_free(ctx);
 

diff  --git a/polly/lib/External/isl/isl_test_cpp-generic.cc b/polly/lib/External/isl/isl_test_cpp-generic.cc
index c3ae55b1950c..e225a71b06fc 100644
--- a/polly/lib/External/isl/isl_test_cpp-generic.cc
+++ b/polly/lib/External/isl/isl_test_cpp-generic.cc
@@ -8,6 +8,9 @@
 #ifndef IS_TRUE
 #define IS_TRUE(b)	(b)
 #endif
+#ifndef SIZE_VAL
+#define SIZE_VAL(s)	(s)
+#endif
 
 /* Test the pointer interface for interaction between isl C and C++ types.
  *
@@ -46,6 +49,7 @@ void test_pointer(isl::ctx ctx)
  *  - static constructor without a parameter
  *  - conversion construction (implicit)
  *  - conversion construction (explicit)
+ *  - construction of empty union set
  *
  *  The tests to construct from integers and strings cover functionality that
  *  is also tested in the parameter type tests, but here we verify that
@@ -74,6 +78,10 @@ void test_constructors(isl::ctx ctx)
 	assert(IS_TRUE(s.is_equal(result)));
 	isl::set s2(bs);
 	assert(IS_TRUE(s.unite(s2).is_equal(result)));
+
+	isl::union_set us(ctx, "{ A[1]; B[2, 3] }");
+	isl::union_set empty = isl::union_set::empty(ctx);
+	assert(IS_TRUE(us.is_equal(us.unite(empty))));
 }
 
 /* Test integer function parameters.
@@ -183,3 +191,184 @@ void test_return_string(isl::ctx ctx)
 	expected_string = "n >= 0";
 	assert(expected_string == expr.to_C_str());
 }
+
+/* Test the functionality of "every" functions
+ * that does not depend on the type of C++ bindings.
+ */
+static void test_every_generic(isl::ctx ctx)
+{
+	isl::union_set us(ctx, "{ A[i]; B[j] }");
+
+	auto is_empty = [] (isl::set s) {
+		return s.is_empty();
+	};
+	assert(!IS_TRUE(us.every_set(is_empty)));
+
+	auto is_non_empty = [] (isl::set s) {
+		return !s.is_empty();
+	};
+	assert(IS_TRUE(us.every_set(is_non_empty)));
+
+	auto in_A = [] (isl::set s) {
+		return s.is_subset(isl::set(s.ctx(), "{ A[x] }"));
+	};
+	assert(!IS_TRUE(us.every_set(in_A)));
+
+	auto not_in_A = [] (isl::set s) {
+		return !s.is_subset(isl::set(s.ctx(), "{ A[x] }"));
+	};
+	assert(!IS_TRUE(us.every_set(not_in_A)));
+}
+
+/* Check basic construction of spaces.
+ */
+static void test_space(isl::ctx ctx)
+{
+	isl::space unit = isl::space::unit(ctx);
+	isl::space set_space = unit.add_named_tuple("A", 3);
+	isl::space map_space = set_space.add_named_tuple("B", 2);
+
+	isl::set set = isl::set::universe(set_space);
+	isl::map map = isl::map::universe(map_space);
+	assert(IS_TRUE(set.is_equal(isl::set(ctx, "{ A[*,*,*] }"))));
+	assert(IS_TRUE(map.is_equal(isl::map(ctx, "{ A[*,*,*] -> B[*,*] }"))));
+}
+
+/* Construct a simple schedule tree with an outer sequence node and
+ * a single-dimensional band node in each branch, with one of them
+ * marked coincident.
+ */
+static isl::schedule construct_schedule_tree(isl::ctx ctx)
+{
+	isl::union_set A(ctx, "{ A[i] : 0 <= i < 10 }");
+	isl::union_set B(ctx, "{ B[i] : 0 <= i < 20 }");
+
+	auto node = isl::schedule_node::from_domain(A.unite(B));
+	node = node.child(0);
+
+	isl::union_set_list filters(ctx, 0);
+	filters = filters.add(A).add(B);
+	node = node.insert_sequence(filters);
+
+	isl::multi_union_pw_aff f_A(ctx, "[ { A[i] -> [i] } ]");
+	node = node.child(0);
+	node = node.child(0);
+	node = node.insert_partial_schedule(f_A);
+	auto band = node.as<isl::schedule_node_band>();
+	band = band.member_set_coincident(0, true);
+	node = band.ancestor(2);
+
+	isl::multi_union_pw_aff f_B(ctx, "[ { B[i] -> [i] } ]");
+	node = node.child(1);
+	node = node.child(0);
+	node = node.insert_partial_schedule(f_B);
+	node = node.ancestor(2);
+
+	return node.schedule();
+}
+
+/* Test basic schedule tree functionality that is independent
+ * of the type of bindings.
+ *
+ * In particular, create a simple schedule tree and
+ * - check that the root node is a domain node
+ * - check that an object of a subclass can be used as one of the superclass
+ * - test map_descendant_bottom_up in the successful case
+ */
+static isl::schedule_node test_schedule_tree_generic(isl::ctx ctx)
+{
+	auto schedule = construct_schedule_tree(ctx);
+	auto root = schedule.root();
+
+	assert(IS_TRUE(root.isa<isl::schedule_node_domain>()));
+	root = root.as<isl::schedule_node_domain>().child(0).parent();
+
+	int count = 0;
+	auto inc_count = [&count](isl::schedule_node node) {
+		count++;
+		return node;
+	};
+	root = root.map_descendant_bottom_up(inc_count);
+	assert(count == 8);
+
+	return root;
+}
+
+/* Test marking band members for unrolling.
+ * "schedule" is the schedule created by construct_schedule_tree.
+ * It schedules two statements, with 10 and 20 instances, respectively.
+ * Unrolling all band members therefore results in 30 at-domain calls
+ * by the AST generator.
+ */
+static void test_ast_build_unroll(isl::schedule schedule)
+{
+	auto root = schedule.root();
+	auto mark_unroll = [](isl::schedule_node node) {
+		if (IS_TRUE(node.isa<isl::schedule_node_band>())) {
+			auto band = node.as<isl::schedule_node_band>();
+			node = band.member_set_ast_loop_unroll(0);
+		}
+		return node;
+	};
+	root = root.map_descendant_bottom_up(mark_unroll);
+	schedule = root.schedule();
+
+	int count_ast = 0;
+	auto inc_count_ast =
+	    [&count_ast](isl::ast_node node, isl::ast_build build) {
+		count_ast++;
+		return node;
+	};
+	auto build = isl::ast_build(schedule.ctx());
+	build = build.set_at_each_domain(inc_count_ast);
+	auto ast = build.node_from(schedule);
+	assert(count_ast == 30);
+}
+
+/* Test basic AST generation from a schedule tree that is independent
+ * of the type of bindings.
+ *
+ * In particular, create a simple schedule tree and
+ * - generate an AST from the schedule tree
+ * - test at_each_domain in the successful case
+ * - test unrolling
+ */
+static isl::schedule test_ast_build_generic(isl::ctx ctx)
+{
+	auto schedule = construct_schedule_tree(ctx);
+
+	int count_ast = 0;
+	auto inc_count_ast =
+	    [&count_ast](isl::ast_node node, isl::ast_build build) {
+		count_ast++;
+		return node;
+	};
+	auto build = isl::ast_build(ctx);
+	auto build_copy = build.set_at_each_domain(inc_count_ast);
+	auto ast = build.node_from(schedule);
+	assert(count_ast == 0);
+	count_ast = 0;
+	ast = build_copy.node_from(schedule);
+	assert(count_ast == 2);
+	build = build_copy;
+	count_ast = 0;
+	ast = build.node_from(schedule);
+	assert(count_ast == 2);
+
+	test_ast_build_unroll(schedule);
+
+	return schedule;
+}
+
+/* Test basic AST expression generation from an affine expression.
+ */
+static void test_ast_build_expr(isl::ctx ctx)
+{
+	isl::pw_aff pa(ctx, "[n] -> { [n + 1] }");
+	isl::ast_build build = isl::ast_build::from_context(pa.domain());
+
+	auto expr = build.expr_from(pa);
+	auto op = expr.as<isl::ast_expr_op>();
+	assert(IS_TRUE(op.isa<isl::ast_expr_op_add>()));
+	assert(SIZE_VAL(op.n_arg()) == 2);
+}

diff  --git a/polly/lib/External/isl/isl_test_cpp.cc b/polly/lib/External/isl/isl_test_cpp.cc
index 929d69c4dd6a..2183ad4328f1 100644
--- a/polly/lib/External/isl/isl_test_cpp.cc
+++ b/polly/lib/External/isl/isl_test_cpp.cc
@@ -113,6 +113,30 @@ static void test_foreach(isl::ctx ctx)
 	assert(caught);
 }
 
+/* Test the functionality of "every" functions.
+ *
+ * In particular, test the generic functionality and
+ * test that exceptions are properly propagated.
+ */
+static void test_every(isl::ctx ctx)
+{
+	isl::union_set us(ctx, "{ A[i]; B[j] }");
+
+	test_every_generic(ctx);
+
+	auto fail = [] (isl::set s) -> bool {
+		throw "fail";
+	};
+	bool caught = false;
+	try {
+		us.every_set(fail);
+		die("no exception raised");
+	} catch (char const *s) {
+		caught = true;
+	}
+	assert(caught);
+}
+
 /* Test that an exception is generated for an isl error and
  * that the error message is captured by the exception.
  * Also check that the exception can be copied and that copying
@@ -140,6 +164,125 @@ static void test_exception(isl::ctx ctx)
 	assert(strstr(copy.what(), "without explicit domain"));
 }
 
+/* Test basic schedule tree functionality.
+ *
+ * In particular, create a simple schedule tree and
+ * - perform some generic tests
+ * - test map_descendant_bottom_up in the failing case
+ * - test foreach_descendant_top_down
+ * - test every_descendant
+ */
+static void test_schedule_tree(isl::ctx ctx)
+{
+	auto root = test_schedule_tree_generic(ctx);
+
+	auto fail_map = [](isl::schedule_node node) {
+		throw "fail";
+		return node;
+	};
+	auto caught = false;
+	try {
+		root.map_descendant_bottom_up(fail_map);
+		die("no exception raised");
+	} catch (char const *s) {
+		caught = true;
+	}
+	assert(caught);
+
+	int count = 0;
+	auto inc_count = [&count](isl::schedule_node node) {
+		count++;
+		return true;
+	};
+	root.foreach_descendant_top_down(inc_count);
+	assert(count == 8);
+
+	count = 0;
+	auto inc_count_once = [&count](isl::schedule_node node) {
+		count++;
+		return false;
+	};
+	root.foreach_descendant_top_down(inc_count_once);
+	assert(count == 1);
+
+	auto is_not_domain = [](isl::schedule_node node) {
+		return !node.isa<isl::schedule_node_domain>();
+	};
+	assert(root.child(0).every_descendant(is_not_domain));
+	assert(!root.every_descendant(is_not_domain));
+
+	auto fail = [](isl::schedule_node node) {
+		throw "fail";
+		return true;
+	};
+	caught = false;
+	try {
+		root.every_descendant(fail);
+		die("no exception raised");
+	} catch (char const *s) {
+		caught = true;
+	}
+	assert(caught);
+
+	auto domain = root.as<isl::schedule_node_domain>().domain();
+	auto filters = isl::union_set(ctx, "{}");
+	auto collect_filters = [&filters](isl::schedule_node node) {
+		if (node.isa<isl::schedule_node_filter>()) {
+			auto filter = node.as<isl::schedule_node_filter>();
+			filters = filters.unite(filter.filter());
+		}
+		return true;
+	};
+	root.every_descendant(collect_filters);
+	assert(domain.is_equal(filters));
+}
+
+/* Test basic AST generation from a schedule tree.
+ *
+ * In particular, create a simple schedule tree and
+ * - perform some generic tests
+ * - test at_each_domain in the failing case
+ */
+static void test_ast_build(isl::ctx ctx)
+{
+	auto schedule = test_ast_build_generic(ctx);
+
+	bool do_fail = true;
+	int count_ast_fail = 0;
+	auto fail_inc_count_ast =
+	    [&count_ast_fail, &do_fail](isl::ast_node node,
+					isl::ast_build build) {
+		count_ast_fail++;
+		if (do_fail)
+			throw "fail";
+		return node;
+	};
+	auto build = isl::ast_build(ctx);
+	build = build.set_at_each_domain(fail_inc_count_ast);
+	auto caught = false;
+	try {
+		auto ast = build.node_from(schedule);
+	} catch (char const *s) {
+		caught = true;
+	}
+	assert(caught);
+	assert(count_ast_fail > 0);
+	auto build_copy = build;
+	int count_ast = 0;
+	auto inc_count_ast =
+	    [&count_ast](isl::ast_node node, isl::ast_build build) {
+		count_ast++;
+		return node;
+	};
+	build_copy = build_copy.set_at_each_domain(inc_count_ast);
+	auto ast = build_copy.node_from(schedule);
+	assert(count_ast == 2);
+	count_ast_fail = 0;
+	do_fail = false;
+	ast = build.node_from(schedule);
+	assert(count_ast_fail == 2);
+}
+
 /* Test the (unchecked) isl C++ interface
  *
  * This includes:
@@ -149,6 +292,10 @@ static void test_exception(isl::ctx ctx)
  *  - Different return types
  *  - Foreach functions
  *  - Exceptions
+ *  - Spaces
+ *  - Schedule trees
+ *  - AST generation
+ *  - AST expression generation
  */
 int main()
 {
@@ -161,7 +308,12 @@ int main()
 	test_parameters(ctx);
 	test_return(ctx);
 	test_foreach(ctx);
+	test_every(ctx);
 	test_exception(ctx);
+	test_space(ctx);
+	test_schedule_tree(ctx);
+	test_ast_build(ctx);
+	test_ast_build_expr(ctx);
 
 	isl_ctx_free(ctx);
 

diff  --git a/polly/lib/External/isl/isl_test_list_templ.c b/polly/lib/External/isl/isl_test_list_templ.c
new file mode 100644
index 000000000000..fa5cb32ff638
--- /dev/null
+++ b/polly/lib/External/isl/isl_test_list_templ.c
@@ -0,0 +1,51 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xLIST(EL) EL ## _list
+#define LIST(EL) xLIST(EL)
+
+#undef SET
+#define SET	CAT(isl_,SET_BASE)
+#undef EL
+#define EL	CAT(isl_,EL_BASE)
+
+/* Check that the conversion from SET to list of EL works as expected,
+ * using input described by "str".
+ */
+static isl_stat FN(FN(FN(test_get_list,EL_BASE),from),SET_BASE)(isl_ctx *ctx,
+	const char *str)
+{
+	int i;
+	isl_size n;
+	isl_bool equal;
+	SET *set, *set2;
+	LIST(EL) *list;
+
+	set = FN(SET,read_from_str)(ctx, str);
+	list = FN(FN(SET,get),LIST(EL_BASE))(set);
+
+	set2 = FN(SET,empty)(FN(SET,get_space)(set));
+
+	n = FN(LIST(EL),size)(list);
+	for (i = 0; i < n; i++) {
+		EL *el;
+		el = FN(LIST(EL),get_at)(list, i);
+		set2 = FN(SET,union)(set2, FN(FN(SET,from),EL_BASE)(el));
+	}
+
+	equal = FN(SET,is_equal)(set, set2);
+
+	FN(SET,free)(set);
+	FN(SET,free)(set2);
+	FN(LIST(EL),free)(list);
+
+	if (n < 0 || equal < 0)
+		return isl_stat_error;
+
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "collections are not equal",
+			return isl_stat_error);
+
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/isl_test_plain_equal_templ.c b/polly/lib/External/isl/isl_test_plain_equal_templ.c
new file mode 100644
index 000000000000..5acbf1e85450
--- /dev/null
+++ b/polly/lib/External/isl/isl_test_plain_equal_templ.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012      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
+ */
+
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef TYPE
+#define TYPE CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Is "obj" obviously equal to the object represented by "str"?
+ */
+static isl_bool FN(BASE,plain_is_equal)(__isl_keep TYPE *obj, const char *str)
+{
+	isl_ctx *ctx;
+	TYPE *obj2;
+	isl_bool equal;
+
+	if (!obj)
+		return isl_bool_error;
+
+	ctx = FN(TYPE,get_ctx)(obj);
+	obj2 = FN(TYPE,read_from_str)(ctx, str);
+	equal = FN(TYPE,plain_is_equal)(obj, obj2);
+	FN(TYPE,free)(obj2);
+
+	return equal;
+}
+
+/* Check that "obj" is obviously equal to the object represented by "str".
+ */
+static isl_stat FN(BASE,check_plain_equal)(__isl_keep TYPE *obj,
+	const char *str)
+{
+	isl_bool equal;
+
+	equal = FN(BASE,plain_is_equal)(obj, str);
+	if (equal < 0)
+		return isl_stat_error;
+	if (!equal)
+		isl_die(FN(TYPE,get_ctx)(obj), isl_error_unknown,
+			"result not as expected", return isl_stat_error);
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/isl_test_python.py b/polly/lib/External/isl/isl_test_python.py
index 10b9c95e9a8b..5373f967e6fd 100755
--- a/polly/lib/External/isl/isl_test_python.py
+++ b/polly/lib/External/isl/isl_test_python.py
@@ -14,6 +14,7 @@
 #  - construction from an integer
 #  - static constructor without a parameter
 #  - conversion construction
+#  - construction of empty union set
 #
 #  The tests to construct from integers and strings cover functionality that
 #  is also tested in the parameter type tests, but here the presence of
@@ -34,6 +35,10 @@ def test_constructors():
 	s = isl.set(bs)
 	assert(s.is_equal(result))
 
+	us = isl.union_set("{ A[1]; B[2, 3] }")
+	empty = isl.union_set.empty()
+	assert(us.is_equal(us.union(empty)))
+
 # Test integer function parameters for a particular integer value.
 #
 def test_int(i):
@@ -187,6 +192,239 @@ def fail(bs):
 		caught = True
 	assert(caught)
 
+# Test the functionality of "every" functions.
+#
+# In particular, test the generic functionality and
+# test that exceptions are properly propagated.
+#
+def test_every():
+	us = isl.union_set("{ A[i]; B[j] }")
+
+	def is_empty(s):
+		return s.is_empty()
+	assert(not us.every_set(is_empty))
+
+	def is_non_empty(s):
+		return not s.is_empty()
+	assert(us.every_set(is_non_empty))
+
+	def in_A(s):
+		return s.is_subset(isl.set("{ A[x] }"))
+	assert(not us.every_set(in_A))
+
+	def not_in_A(s):
+		return not s.is_subset(isl.set("{ A[x] }"))
+	assert(not us.every_set(not_in_A))
+
+	def fail(s):
+		raise "fail"
+
+	caught = False
+	try:
+		us.ever_set(fail)
+	except:
+		caught = True
+	assert(caught)
+
+# Check basic construction of spaces.
+#
+def test_space():
+	unit = isl.space.unit()
+	set_space = unit.add_named_tuple("A", 3)
+	map_space = set_space.add_named_tuple("B", 2)
+
+	set = isl.set.universe(set_space)
+	map = isl.map.universe(map_space)
+	assert(set.is_equal(isl.set("{ A[*,*,*] }")))
+	assert(map.is_equal(isl.map("{ A[*,*,*] -> B[*,*] }")))
+
+# Construct a simple schedule tree with an outer sequence node and
+# a single-dimensional band node in each branch, with one of them
+# marked coincident.
+#
+def construct_schedule_tree():
+	A = isl.union_set("{ A[i] : 0 <= i < 10 }")
+	B = isl.union_set("{ B[i] : 0 <= i < 20 }")
+
+	node = isl.schedule_node.from_domain(A.union(B))
+	node = node.child(0)
+
+	filters = isl.union_set_list(A).add(B)
+	node = node.insert_sequence(filters)
+
+	f_A = isl.multi_union_pw_aff("[ { A[i] -> [i] } ]")
+	node = node.child(0)
+	node = node.child(0)
+	node = node.insert_partial_schedule(f_A)
+	node = node.member_set_coincident(0, True)
+	node = node.ancestor(2)
+
+	f_B = isl.multi_union_pw_aff("[ { B[i] -> [i] } ]")
+	node = node.child(1)
+	node = node.child(0)
+	node = node.insert_partial_schedule(f_B)
+	node = node.ancestor(2)
+
+	return node.schedule()
+
+# Test basic schedule tree functionality.
+#
+# In particular, create a simple schedule tree and
+# - check that the root node is a domain node
+# - test map_descendant_bottom_up
+# - test foreach_descendant_top_down
+# - test every_descendant
+#
+def test_schedule_tree():
+	schedule = construct_schedule_tree()
+	root = schedule.root()
+
+	assert(type(root) == isl.schedule_node_domain)
+
+	count = [0]
+	def inc_count(node):
+		count[0] += 1
+		return node
+	root = root.map_descendant_bottom_up(inc_count)
+	assert(count[0] == 8)
+
+	def fail_map(node):
+		raise "fail"
+		return node
+	caught = False
+	try:
+		root.map_descendant_bottom_up(fail_map)
+	except:
+		caught = True
+	assert(caught)
+
+	count = [0]
+	def inc_count(node):
+		count[0] += 1
+		return True
+	root.foreach_descendant_top_down(inc_count)
+	assert(count[0] == 8)
+
+	count = [0]
+	def inc_count(node):
+		count[0] += 1
+		return False
+	root.foreach_descendant_top_down(inc_count)
+	assert(count[0] == 1)
+
+	def is_not_domain(node):
+		return type(node) != isl.schedule_node_domain
+	assert(root.child(0).every_descendant(is_not_domain))
+	assert(not root.every_descendant(is_not_domain))
+
+	def fail(node):
+		raise "fail"
+	caught = False
+	try:
+		root.every_descendant(fail)
+	except:
+		caught = True
+	assert(caught)
+
+	domain = root.domain()
+	filters = [isl.union_set("{}")]
+	def collect_filters(node):
+		if type(node) == isl.schedule_node_filter:
+			filters[0] = filters[0].union(node.filter())
+		return True
+	root.every_descendant(collect_filters)
+	assert(domain.is_equal(filters[0]))
+
+# Test marking band members for unrolling.
+# "schedule" is the schedule created by construct_schedule_tree.
+# It schedules two statements, with 10 and 20 instances, respectively.
+# Unrolling all band members therefore results in 30 at-domain calls
+# by the AST generator.
+#
+def test_ast_build_unroll(schedule):
+	root = schedule.root()
+	def mark_unroll(node):
+		if type(node) == isl.schedule_node_band:
+			node = node.member_set_ast_loop_unroll(0)
+		return node
+	root = root.map_descendant_bottom_up(mark_unroll)
+	schedule = root.schedule()
+
+	count_ast = [0]
+	def inc_count_ast(node, build):
+		count_ast[0] += 1
+		return node
+
+	build = isl.ast_build()
+	build = build.set_at_each_domain(inc_count_ast)
+	ast = build.node_from(schedule)
+	assert(count_ast[0] == 30)
+
+# Test basic AST generation from a schedule tree.
+#
+# In particular, create a simple schedule tree and
+# - generate an AST from the schedule tree
+# - test at_each_domain
+# - test unrolling
+#
+def test_ast_build():
+	schedule = construct_schedule_tree()
+
+	count_ast = [0]
+	def inc_count_ast(node, build):
+		count_ast[0] += 1
+		return node
+
+	build = isl.ast_build()
+	build_copy = build.set_at_each_domain(inc_count_ast)
+	ast = build.node_from(schedule)
+	assert(count_ast[0] == 0)
+	count_ast[0] = 0
+	ast = build_copy.node_from(schedule)
+	assert(count_ast[0] == 2)
+	build = build_copy
+	count_ast[0] = 0
+	ast = build.node_from(schedule)
+	assert(count_ast[0] == 2)
+
+	do_fail = True
+	count_ast_fail = [0]
+	def fail_inc_count_ast(node, build):
+		count_ast_fail[0] += 1
+		if do_fail:
+			raise "fail"
+		return node
+	build = isl.ast_build()
+	build = build.set_at_each_domain(fail_inc_count_ast)
+	caught = False
+	try:
+		ast = build.node_from(schedule)
+	except:
+		caught = True
+	assert(caught)
+	assert(count_ast_fail[0] > 0)
+	build_copy = build
+	build_copy = build_copy.set_at_each_domain(inc_count_ast)
+	count_ast[0] = 0
+	ast = build_copy.node_from(schedule)
+	assert(count_ast[0] == 2)
+	count_ast_fail[0] = 0
+	do_fail = False
+	ast = build.node_from(schedule)
+	assert(count_ast_fail[0] == 2)
+
+	test_ast_build_unroll(schedule)
+
+# Test basic AST expression generation from an affine expression.
+#
+def test_ast_build_expr():
+	pa = isl.pw_aff("[n] -> { [n + 1] }")
+	build = isl.ast_build.from_context(pa.domain())
+
+	op = build.expr_from(pa)
+	assert(type(op) == isl.ast_expr_op_add)
+	assert(op.n_arg() == 2)
+
 # Test the isl Python interface
 #
 # This includes:
@@ -194,8 +432,18 @@ def fail(bs):
 #  - Different parameter types
 #  - Different return types
 #  - Foreach functions
+#  - Every functions
+#  - Spaces
+#  - Schedule trees
+#  - AST generation
+#  - AST expression generation
 #
 test_constructors()
 test_parameters()
 test_return()
 test_foreach()
+test_every()
+test_space()
+test_schedule_tree()
+test_ast_build()
+test_ast_build_expr()

diff  --git a/polly/lib/External/isl/isl_transitive_closure.c b/polly/lib/External/isl/isl_transitive_closure.c
index 6e1b4bb60d0a..f485680afc0e 100644
--- a/polly/lib/External/isl/isl_transitive_closure.c
+++ b/polly/lib/External/isl/isl_transitive_closure.c
@@ -20,10 +20,10 @@
 #include <isl_options_private.h>
 #include <isl_tarjan.h>
 
-int isl_map_is_transitively_closed(__isl_keep isl_map *map)
+isl_bool isl_map_is_transitively_closed(__isl_keep isl_map *map)
 {
 	isl_map *map2;
-	int closed;
+	isl_bool closed;
 
 	map2 = isl_map_apply_range(isl_map_copy(map), isl_map_copy(map));
 	closed = isl_map_is_subset(map2, map);
@@ -32,10 +32,10 @@ int isl_map_is_transitively_closed(__isl_keep isl_map *map)
 	return closed;
 }
 
-int isl_union_map_is_transitively_closed(__isl_keep isl_union_map *umap)
+isl_bool isl_union_map_is_transitively_closed(__isl_keep isl_union_map *umap)
 {
 	isl_union_map *umap2;
-	int closed;
+	isl_bool closed;
 
 	umap2 = isl_union_map_apply_range(isl_union_map_copy(umap),
 					  isl_union_map_copy(umap));
@@ -54,20 +54,24 @@ int isl_union_map_is_transitively_closed(__isl_keep isl_union_map *umap)
 static __isl_give isl_map *set_path_length(__isl_take isl_map *map,
 	int exactly, int length)
 {
-	isl_space *dim;
+	isl_space *space;
 	struct isl_basic_map *bmap;
-	unsigned d;
-	unsigned nparam;
+	isl_size d;
+	isl_size nparam;
+	isl_size total;
 	int k;
 	isl_int *c;
 
 	if (!map)
 		return NULL;
 
-	dim = isl_map_get_space(map);
-	d = isl_space_dim(dim, isl_dim_in);
-	nparam = isl_space_dim(dim, isl_dim_param);
-	bmap = isl_basic_map_alloc_space(dim, 0, 1, 1);
+	space = isl_map_get_space(map);
+	d = isl_space_dim(space, isl_dim_in);
+	nparam = isl_space_dim(space, isl_dim_param);
+	total = isl_space_dim(space, isl_dim_all);
+	if (d < 0 || nparam < 0 || total < 0)
+		space = isl_space_free(space);
+	bmap = isl_basic_map_alloc_space(space, 0, 1, 1);
 	if (exactly) {
 		k = isl_basic_map_alloc_equality(bmap);
 		if (k < 0)
@@ -79,7 +83,7 @@ static __isl_give isl_map *set_path_length(__isl_take isl_map *map,
 			goto error;
 		c = bmap->ineq[k];
 	}
-	isl_seq_clr(c, 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(c, 1 + total);
 	isl_int_set_si(c[0], -length);
 	isl_int_set_si(c[1 + nparam + d - 1], -1);
 	isl_int_set_si(c[1 + nparam + d + d - 1], 1);
@@ -111,10 +115,10 @@ static __isl_give isl_map *set_path_length(__isl_take isl_map *map,
  * this coordinate to "map" and set the length of the path to
  * one.
  */
-static int check_power_exactness(__isl_take isl_map *map,
+static isl_bool check_power_exactness(__isl_take isl_map *map,
 	__isl_take isl_map *app)
 {
-	int exact;
+	isl_bool exact;
 	isl_map *app_1;
 	isl_map *app_2;
 
@@ -166,17 +170,19 @@ static int check_power_exactness(__isl_take isl_map *map,
  * the length of the part.  If we are only interested in the transitive
  * closure, then we can simply project out these coordinates first.
  */
-static int check_exactness(__isl_take isl_map *map, __isl_take isl_map *app,
-	int project)
+static isl_bool check_exactness(__isl_take isl_map *map,
+	__isl_take isl_map *app, int project)
 {
 	isl_map *test;
-	int exact;
-	unsigned d;
+	isl_bool exact;
+	isl_size d;
 
 	if (!project)
 		return check_power_exactness(map, app);
 
 	d = isl_map_dim(map, isl_dim_in);
+	if (d < 0)
+		app = isl_map_free(app);
 	app = set_path_length(app, 0, 1);
 	app = isl_map_project_out(app, isl_dim_in, d, 1);
 	app = isl_map_project_out(app, isl_dim_out, d, 1);
@@ -215,23 +221,24 @@ static int check_exactness(__isl_take isl_map *map, __isl_take isl_map *app,
  * For any element in this relation, the number of steps taken
  * is equal to the 
diff erence in the final coordinates.
  */
-static __isl_give isl_map *path_along_steps(__isl_take isl_space *dim,
+static __isl_give isl_map *path_along_steps(__isl_take isl_space *space,
 	__isl_keep isl_mat *steps)
 {
 	int i, j, k;
 	struct isl_basic_map *path = NULL;
-	unsigned d;
+	isl_size d;
 	unsigned n;
-	unsigned nparam;
+	isl_size nparam;
+	isl_size total;
 
-	if (!dim || !steps)
+	d = isl_space_dim(space, isl_dim_in);
+	nparam = isl_space_dim(space, isl_dim_param);
+	if (d < 0 || nparam < 0 || !steps)
 		goto error;
 
-	d = isl_space_dim(dim, isl_dim_in);
 	n = steps->n_row;
-	nparam = isl_space_dim(dim, isl_dim_param);
 
-	path = isl_basic_map_alloc_space(isl_space_copy(dim), n, d, n);
+	path = isl_basic_map_alloc_space(isl_space_copy(space), n, d, n);
 
 	for (i = 0; i < n; ++i) {
 		k = isl_basic_map_alloc_div(path);
@@ -241,11 +248,14 @@ static __isl_give isl_map *path_along_steps(__isl_take isl_space *dim,
 		isl_int_set_si(path->div[k][0], 0);
 	}
 
+	total = isl_basic_map_dim(path, isl_dim_all);
+	if (total < 0)
+		goto error;
 	for (i = 0; i < d; ++i) {
 		k = isl_basic_map_alloc_equality(path);
 		if (k < 0)
 			goto error;
-		isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
+		isl_seq_clr(path->eq[k], 1 + total);
 		isl_int_set_si(path->eq[k][1 + nparam + i], 1);
 		isl_int_set_si(path->eq[k][1 + nparam + d + i], -1);
 		if (i == d - 1)
@@ -261,17 +271,17 @@ static __isl_give isl_map *path_along_steps(__isl_take isl_space *dim,
 		k = isl_basic_map_alloc_inequality(path);
 		if (k < 0)
 			goto error;
-		isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
+		isl_seq_clr(path->ineq[k], 1 + total);
 		isl_int_set_si(path->ineq[k][1 + nparam + 2 * d + i], 1);
 	}
 
-	isl_space_free(dim);
+	isl_space_free(space);
 
 	path = isl_basic_map_simplify(path);
 	path = isl_basic_map_finalize(path);
 	return isl_map_from_basic_map(path);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_basic_map_free(path);
 	return NULL;
 }
@@ -287,9 +297,10 @@ static __isl_give isl_map *path_along_steps(__isl_take isl_space *dim,
 static isl_bool parametric_constant_never_positive(
 	__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity)
 {
-	unsigned d;
-	unsigned n_div;
-	unsigned nparam;
+	isl_size d;
+	isl_size n_div;
+	isl_size nparam;
+	isl_size total;
 	int i;
 	int k;
 	isl_bool empty;
@@ -297,6 +308,9 @@ static isl_bool parametric_constant_never_positive(
 	n_div = isl_basic_set_dim(bset, isl_dim_div);
 	d = isl_basic_set_dim(bset, isl_dim_set);
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (n_div < 0 || d < 0 || nparam < 0 || total < 0)
+		return isl_bool_error;
 
 	bset = isl_basic_set_copy(bset);
 	bset = isl_basic_set_cow(bset);
@@ -304,7 +318,7 @@ static isl_bool parametric_constant_never_positive(
 	k = isl_basic_set_alloc_inequality(bset);
 	if (k < 0)
 		goto error;
-	isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
+	isl_seq_clr(bset->ineq[k], 1 + total);
 	isl_seq_cpy(bset->ineq[k], c, 1 + nparam);
 	for (i = 0; i < n_div; ++i) {
 		if (div_purity[i] != PURE_PARAM)
@@ -332,9 +346,9 @@ static isl_bool parametric_constant_never_positive(
 static int purity(__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity,
 	int eq)
 {
-	unsigned d;
-	unsigned n_div;
-	unsigned nparam;
+	isl_size d;
+	isl_size n_div;
+	isl_size nparam;
 	isl_bool empty;
 	int i;
 	int p = 0, v = 0;
@@ -342,6 +356,8 @@ static int purity(__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity,
 	n_div = isl_basic_set_dim(bset, isl_dim_div);
 	d = isl_basic_set_dim(bset, isl_dim_set);
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (n_div < 0 || d < 0 || nparam < 0)
+		return -1;
 
 	for (i = 0; i < n_div; ++i) {
 		if (isl_int_is_zero(c[1 + nparam + d + i]))
@@ -377,16 +393,15 @@ static __isl_give int *get_div_purity(__isl_keep isl_basic_set *bset)
 {
 	int i, j;
 	int *div_purity;
-	unsigned d;
-	unsigned n_div;
-	unsigned nparam;
-
-	if (!bset)
-		return NULL;
+	isl_size d;
+	isl_size n_div;
+	isl_size nparam;
 
 	n_div = isl_basic_set_dim(bset, isl_dim_div);
 	d = isl_basic_set_dim(bset, isl_dim_set);
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (n_div < 0 || d < 0 || nparam < 0)
+		return NULL;
 
 	div_purity = isl_alloc_array(bset->ctx, int, n_div);
 	if (n_div && !div_purity)
@@ -417,33 +432,24 @@ static __isl_give int *get_div_purity(__isl_keep isl_basic_set *bset)
 	return div_purity;
 }
 
-/* Given a path with the as yet unconstrained length at position "pos",
+/* Given a path with the as yet unconstrained length at div position "pos",
  * check if setting the length to zero results in only the identity
  * mapping.
  */
-static int empty_path_is_identity(__isl_keep isl_basic_map *path, unsigned pos)
+static isl_bool empty_path_is_identity(__isl_keep isl_basic_map *path,
+	unsigned pos)
 {
 	isl_basic_map *test = NULL;
 	isl_basic_map *id = NULL;
-	int k;
-	int is_id;
+	isl_bool is_id;
 
 	test = isl_basic_map_copy(path);
-	test = isl_basic_map_extend_constraints(test, 1, 0);
-	k = isl_basic_map_alloc_equality(test);
-	if (k < 0)
-		goto error;
-	isl_seq_clr(test->eq[k], 1 + isl_basic_map_total_dim(test));
-	isl_int_set_si(test->eq[k][pos], 1);
-	test = isl_basic_map_gauss(test, NULL);
+	test = isl_basic_map_fix_si(test, isl_dim_div, pos, 0);
 	id = isl_basic_map_identity(isl_basic_map_get_space(path));
 	is_id = isl_basic_map_is_equal(test, id);
 	isl_basic_map_free(test);
 	isl_basic_map_free(id);
 	return is_id;
-error:
-	isl_basic_map_free(test);
-	return -1;
 }
 
 /* If any of the constraints is found to be impure then this function
@@ -460,9 +466,12 @@ static __isl_give isl_basic_map *add_delta_constraints(
 	int i, k;
 	int n = eq ? delta->n_eq : delta->n_ineq;
 	isl_int **delta_c = eq ? delta->eq : delta->ineq;
-	unsigned n_div;
+	isl_size n_div, total;
 
 	n_div = isl_basic_set_dim(delta, isl_dim_div);
+	total = isl_basic_map_dim(path, isl_dim_all);
+	if (n_div < 0 || total < 0)
+		return isl_basic_map_free(path);
 
 	for (i = 0; i < n; ++i) {
 		isl_int *path_c;
@@ -486,7 +495,7 @@ static __isl_give isl_basic_map *add_delta_constraints(
 				goto error;
 			path_c = path->ineq[k];
 		}
-		isl_seq_clr(path_c, 1 + isl_basic_map_total_dim(path));
+		isl_seq_clr(path_c, 1 + total);
 		if (p == PURE_VAR) {
 			isl_seq_cpy(path_c + off,
 				    delta_c[i] + 1 + nparam, d);
@@ -563,25 +572,26 @@ static __isl_give isl_basic_map *add_delta_constraints(
  *
  * to the constructed relation.
  */
-static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
+static __isl_give isl_map *path_along_delta(__isl_take isl_space *space,
 	__isl_take isl_basic_set *delta)
 {
 	isl_basic_map *path = NULL;
-	unsigned d;
-	unsigned n_div;
-	unsigned nparam;
+	isl_size d;
+	isl_size n_div;
+	isl_size nparam;
+	isl_size total;
 	unsigned off;
 	int i, k;
-	int is_id;
+	isl_bool is_id;
 	int *div_purity = NULL;
 	int impurity = 0;
 
-	if (!delta)
-		goto error;
 	n_div = isl_basic_set_dim(delta, isl_dim_div);
 	d = isl_basic_set_dim(delta, isl_dim_set);
 	nparam = isl_basic_set_dim(delta, isl_dim_param);
-	path = isl_basic_map_alloc_space(isl_space_copy(dim), n_div + d + 1,
+	if (n_div < 0 || d < 0 || nparam < 0)
+		goto error;
+	path = isl_basic_map_alloc_space(isl_space_copy(space), n_div + d + 1,
 			d + 1 + delta->n_eq, delta->n_eq + delta->n_ineq + 1);
 	off = 1 + nparam + 2 * (d + 1) + n_div;
 
@@ -592,11 +602,14 @@ static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
 		isl_int_set_si(path->div[k][0], 0);
 	}
 
+	total = isl_basic_map_dim(path, isl_dim_all);
+	if (total < 0)
+		goto error;
 	for (i = 0; i < d + 1; ++i) {
 		k = isl_basic_map_alloc_equality(path);
 		if (k < 0)
 			goto error;
-		isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
+		isl_seq_clr(path->eq[k], 1 + total);
 		isl_int_set_si(path->eq[k][1 + nparam + i], 1);
 		isl_int_set_si(path->eq[k][1 + nparam + d + 1 + i], -1);
 		isl_int_set_si(path->eq[k][off + i], 1);
@@ -611,11 +624,11 @@ static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
 	path = add_delta_constraints(path, delta, off, nparam, d,
 				     div_purity, 0, &impurity);
 	if (impurity) {
-		isl_space *dim = isl_basic_set_get_space(delta);
+		isl_space *space = isl_basic_set_get_space(delta);
 		delta = isl_basic_set_project_out(delta,
 						  isl_dim_param, 0, nparam);
 		delta = isl_basic_set_add_dims(delta, isl_dim_param, nparam);
-		delta = isl_basic_set_reset_space(delta, dim);
+		delta = isl_basic_set_reset_space(delta, space);
 		if (!delta)
 			goto error;
 		path = isl_basic_map_extend_constraints(path, delta->n_eq,
@@ -627,14 +640,14 @@ static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
 		path = isl_basic_map_gauss(path, NULL);
 	}
 
-	is_id = empty_path_is_identity(path, off + d);
+	is_id = empty_path_is_identity(path, n_div + d);
 	if (is_id < 0)
 		goto error;
 
 	k = isl_basic_map_alloc_inequality(path);
 	if (k < 0)
 		goto error;
-	isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
+	isl_seq_clr(path->ineq[k], 1 + total);
 	if (!is_id)
 		isl_int_set_si(path->ineq[k][0], -1);
 	isl_int_set_si(path->ineq[k][off + d], 1);
@@ -643,13 +656,13 @@ static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
 	isl_basic_set_free(delta);
 	path = isl_basic_map_finalize(path);
 	if (is_id) {
-		isl_space_free(dim);
+		isl_space_free(space);
 		return isl_map_from_basic_map(path);
 	}
-	return isl_basic_map_union(path, isl_basic_map_identity(dim));
+	return isl_basic_map_union(path, isl_basic_map_identity(space));
 error:
 	free(div_purity);
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_basic_set_free(delta);
 	isl_basic_map_free(path);
 	return NULL;
@@ -662,21 +675,25 @@ static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
  *
  *	{ [x,x_s] -> [y,y_s] : k = y_s - x_s > 0 }
  */
-static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_space *dim,
-	unsigned param)
+static __isl_give isl_map *equate_parameter_to_length(
+	__isl_take isl_space *space, unsigned param)
 {
 	struct isl_basic_map *bmap;
-	unsigned d;
-	unsigned nparam;
+	isl_size d;
+	isl_size nparam;
+	isl_size total;
 	int k;
 
-	d = isl_space_dim(dim, isl_dim_in);
-	nparam = isl_space_dim(dim, isl_dim_param);
-	bmap = isl_basic_map_alloc_space(dim, 0, 1, 1);
+	d = isl_space_dim(space, isl_dim_in);
+	nparam = isl_space_dim(space, isl_dim_param);
+	total = isl_space_dim(space, isl_dim_all);
+	if (d < 0 || nparam < 0 || total < 0)
+		space = isl_space_free(space);
+	bmap = isl_basic_map_alloc_space(space, 0, 1, 1);
 	k = isl_basic_map_alloc_equality(bmap);
 	if (k < 0)
 		goto error;
-	isl_seq_clr(bmap->eq[k], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->eq[k], 1 + total);
 	isl_int_set_si(bmap->eq[k][1 + param], -1);
 	isl_int_set_si(bmap->eq[k][1 + nparam + d - 1], -1);
 	isl_int_set_si(bmap->eq[k][1 + nparam + d + d - 1], 1);
@@ -684,7 +701,7 @@ static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_space *dim,
 	k = isl_basic_map_alloc_inequality(bmap);
 	if (k < 0)
 		goto error;
-	isl_seq_clr(bmap->ineq[k], 1 + isl_basic_map_total_dim(bmap));
+	isl_seq_clr(bmap->ineq[k], 1 + total);
 	isl_int_set_si(bmap->ineq[k][1 + param], 1);
 	isl_int_set_si(bmap->ineq[k][0], -1);
 
@@ -704,15 +721,17 @@ static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_space *dim,
  * does not contain any element with positive last coordinate (positive length)
  * and zero remaining coordinates (cycle).
  */
-static int is_acyclic(__isl_take isl_map *path)
+static isl_bool is_acyclic(__isl_take isl_map *path)
 {
 	int i;
-	int acyclic;
-	unsigned dim;
+	isl_bool acyclic;
+	isl_size dim;
 	struct isl_set *delta;
 
 	delta = isl_map_deltas(path);
 	dim = isl_set_dim(delta, isl_dim_set);
+	if (dim < 0)
+		delta = isl_set_free(delta);
 	for (i = 0; i < dim; ++i) {
 		if (i == dim -1)
 			delta = isl_set_lower_bound_si(delta, isl_dim_set, i, 1);
@@ -751,20 +770,19 @@ static int is_acyclic(__isl_take isl_map *path)
  * Since each of these paths performs an addition, composition is
  * symmetric and we can simply compose all resulting paths in any order.
  */
-static __isl_give isl_map *construct_extended_path(__isl_take isl_space *dim,
+static __isl_give isl_map *construct_extended_path(__isl_take isl_space *space,
 	__isl_keep isl_map *map, int *project)
 {
 	struct isl_mat *steps = NULL;
 	struct isl_map *path = NULL;
-	unsigned d;
+	isl_size d;
 	int i, j, n;
 
-	if (!map)
-		goto error;
-
 	d = isl_map_dim(map, isl_dim_in);
+	if (d < 0)
+		goto error;
 
-	path = isl_map_identity(isl_space_copy(dim));
+	path = isl_map_identity(isl_space_copy(space));
 
 	steps = isl_mat_alloc(map->ctx, map->n, d);
 	if (!steps)
@@ -792,7 +810,7 @@ static __isl_give isl_map *construct_extended_path(__isl_take isl_space *dim,
 
 		if (j < d) {
 			path = isl_map_apply_range(path,
-				path_along_delta(isl_space_copy(dim), delta));
+				path_along_delta(isl_space_copy(space), delta));
 			path = isl_map_coalesce(path);
 		} else {
 			isl_basic_set_free(delta);
@@ -803,7 +821,7 @@ static __isl_give isl_map *construct_extended_path(__isl_take isl_space *dim,
 	if (n > 0) {
 		steps->n_row = n;
 		path = isl_map_apply_range(path,
-				path_along_steps(isl_space_copy(dim), steps));
+				path_along_steps(isl_space_copy(space), steps));
 	}
 
 	if (project && *project) {
@@ -812,11 +830,11 @@ static __isl_give isl_map *construct_extended_path(__isl_take isl_space *dim,
 			goto error;
 	}
 
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_mat_free(steps);
 	return path;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_mat_free(steps);
 	isl_map_free(path);
 	return NULL;
@@ -825,21 +843,7 @@ static __isl_give isl_map *construct_extended_path(__isl_take isl_space *dim,
 static isl_bool isl_set_overlaps(__isl_keep isl_set *set1,
 	__isl_keep isl_set *set2)
 {
-	isl_set *i;
-	isl_bool no_overlap;
-
-	if (!set1 || !set2)
-		return isl_bool_error;
-
-	if (!isl_space_tuple_is_equal(set1->dim, isl_dim_set,
-					set2->dim, isl_dim_set))
-		return isl_bool_false;
-
-	i = isl_set_intersect(isl_set_copy(set1), isl_set_copy(set2));
-	no_overlap = isl_set_is_empty(i);
-	isl_set_free(i);
-
-	return isl_bool_not(no_overlap);
+	return isl_bool_not(isl_set_is_disjoint(set1, set2));
 }
 
 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
@@ -862,13 +866,14 @@ static isl_bool isl_set_overlaps(__isl_keep isl_set *set1,
  *				\sum_i k_i >= 1 }
  */
 static __isl_give isl_map *construct_component(__isl_take isl_space *dim,
-	__isl_keep isl_map *map, int *exact, int project)
+	__isl_keep isl_map *map, isl_bool *exact, int project)
 {
 	struct isl_set *domain = NULL;
 	struct isl_set *range = NULL;
 	struct isl_map *app = NULL;
 	struct isl_map *path = NULL;
 	isl_bool overlaps;
+	int check;
 
 	domain = isl_map_domain(isl_map_copy(map));
 	domain = isl_set_coalesce(domain);
@@ -892,11 +897,12 @@ static __isl_give isl_map *construct_component(__isl_take isl_space *dim,
 	app = isl_map_add_dims(app, isl_dim_in, 1);
 	app = isl_map_add_dims(app, isl_dim_out, 1);
 
+	check = exact && *exact == isl_bool_true;
 	path = construct_extended_path(isl_space_copy(dim), map,
-					exact && *exact ? &project : NULL);
+					check ? &project : NULL);
 	app = isl_map_intersect(app, path);
 
-	if (exact && *exact &&
+	if (check &&
 	    (*exact = check_exactness(isl_map_copy(map), isl_map_copy(app),
 				      project)) < 0)
 		goto error;
@@ -914,17 +920,17 @@ static __isl_give isl_map *construct_component(__isl_take isl_space *dim,
  * the final coordinates.
  */
 static __isl_give isl_map *construct_projected_component(
-	__isl_take isl_space *dim,
-	__isl_keep isl_map *map, int *exact, int project)
+	__isl_take isl_space *space,
+	__isl_keep isl_map *map, isl_bool *exact, int project)
 {
 	isl_map *app;
 	unsigned d;
 
-	if (!dim)
+	if (!space)
 		return NULL;
-	d = isl_space_dim(dim, isl_dim_in);
+	d = isl_space_dim(space, isl_dim_in);
 
-	app = construct_component(dim, map, exact, project);
+	app = construct_component(space, map, exact, project);
 	if (project) {
 		app = isl_map_project_out(app, isl_dim_in, d - 1, 1);
 		app = isl_map_project_out(app, isl_dim_out, d - 1, 1);
@@ -938,7 +944,8 @@ static __isl_give isl_map *construct_projected_component(
  * domain and range equal to "dom".
  */
 static __isl_give isl_map *q_closure(__isl_take isl_space *dim,
-	__isl_take isl_set *dom, __isl_keep isl_basic_map *bmap, int *exact)
+	__isl_take isl_set *dom, __isl_keep isl_basic_map *bmap,
+	isl_bool *exact)
 {
 	int project = 1;
 	isl_map *path;
@@ -963,17 +970,16 @@ static __isl_give isl_map *q_closure(__isl_take isl_space *dim,
 /* Check whether qc has any elements of length at least one
  * with domain and/or range outside of dom and ran.
  */
-static int has_spurious_elements(__isl_keep isl_map *qc,
+static isl_bool has_spurious_elements(__isl_keep isl_map *qc,
 	__isl_keep isl_set *dom, __isl_keep isl_set *ran)
 {
 	isl_set *s;
-	int subset;
-	unsigned d;
-
-	if (!qc || !dom || !ran)
-		return -1;
+	isl_bool subset;
+	isl_size d;
 
 	d = isl_map_dim(qc, isl_dim_in);
+	if (d < 0 || !dom || !ran)
+		return isl_bool_error;
 
 	qc = isl_map_copy(qc);
 	qc = set_path_length(qc, 0, 1);
@@ -987,17 +993,17 @@ static int has_spurious_elements(__isl_keep isl_map *qc,
 		goto error;
 	if (!subset) {
 		isl_map_free(qc);
-		return 1;
+		return isl_bool_true;
 	}
 
 	s = isl_map_range(qc);
 	subset = isl_set_is_subset(s, ran);
 	isl_set_free(s);
 
-	return subset < 0 ? -1 : !subset;
+	return isl_bool_not(subset);
 error:
 	isl_map_free(qc);
-	return -1;
+	return isl_bool_error;
 }
 
 #define LEFT	2
@@ -1152,8 +1158,8 @@ static __isl_give isl_map *compose(__isl_keep isl_map *map, int i,
  * depending on whether left or right are NULL.
  */
 static __isl_give isl_map *compute_incremental(
-	__isl_take isl_space *dim, __isl_keep isl_map *map,
-	int i, __isl_take isl_map *qc, int *left, int *right, int *exact)
+	__isl_take isl_space *space, __isl_keep isl_map *map,
+	int i, __isl_take isl_map *qc, int *left, int *right, isl_bool *exact)
 {
 	isl_map *map_i;
 	isl_map *tc;
@@ -1164,7 +1170,7 @@ static __isl_give isl_map *compute_incremental(
 	isl_assert(map->ctx, left || right, goto error);
 
 	map_i = isl_map_from_basic_map(isl_basic_map_copy(map->p[i]));
-	tc = construct_projected_component(isl_space_copy(dim), map_i,
+	tc = construct_projected_component(isl_space_copy(space), map_i,
 						exact, 1);
 	isl_map_free(map_i);
 
@@ -1172,7 +1178,7 @@ static __isl_give isl_map *compute_incremental(
 		qc = isl_map_transitive_closure(qc, exact);
 
 	if (!*exact) {
-		isl_space_free(dim);
+		isl_space_free(space);
 		isl_map_free(tc);
 		isl_map_free(qc);
 		return isl_map_universe(isl_map_get_space(map));
@@ -1187,11 +1193,11 @@ static __isl_give isl_map *compute_incremental(
 		qc = isl_map_apply_range(qc, rtc);
 	qc = isl_map_union(tc, qc);
 
-	isl_space_free(dim);
+	isl_space_free(space);
 
 	return qc;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_map_free(qc);
 	return NULL;
 }
@@ -1211,38 +1217,41 @@ static __isl_give isl_map *compute_incremental(
  * after computing the integer divisions, is smaller than the number
  * of basic maps in the input map.
  */
-static int incemental_on_entire_domain(__isl_keep isl_space *dim,
+static isl_bool incremental_on_entire_domain(__isl_keep isl_space *space,
 	__isl_keep isl_map *map,
 	isl_set **dom, isl_set **ran, int *left, int *right,
 	__isl_give isl_map **res)
 {
 	int i;
 	isl_set *C;
-	unsigned d;
+	isl_size d;
 
 	*res = NULL;
 
+	d = isl_map_dim(map, isl_dim_in);
+	if (d < 0)
+		return isl_bool_error;
+
 	C = isl_set_union(isl_map_domain(isl_map_copy(map)),
 			  isl_map_range(isl_map_copy(map)));
 	C = isl_set_from_basic_set(isl_set_simple_hull(C));
 	if (!C)
-		return -1;
+		return isl_bool_error;
 	if (C->n != 1) {
 		isl_set_free(C);
-		return 0;
+		return isl_bool_false;
 	}
 
-	d = isl_map_dim(map, isl_dim_in);
-
 	for (i = 0; i < map->n; ++i) {
 		isl_map *qc;
-		int exact_i, spurious;
+		isl_bool exact_i;
+		isl_bool spurious;
 		int j;
 		dom[i] = isl_set_from_basic_set(isl_basic_map_domain(
 					isl_basic_map_copy(map->p[i])));
 		ran[i] = isl_set_from_basic_set(isl_basic_map_range(
 					isl_basic_map_copy(map->p[i])));
-		qc = q_closure(isl_space_copy(dim), isl_set_copy(C),
+		qc = q_closure(isl_space_copy(space), isl_set_copy(C),
 				map->p[i], &exact_i);
 		if (!qc)
 			goto error;
@@ -1269,7 +1278,7 @@ static int incemental_on_entire_domain(__isl_keep isl_space *dim,
 			isl_map_free(qc);
 			continue;
 		}
-		*res = compute_incremental(isl_space_copy(dim), map, i, qc,
+		*res = compute_incremental(isl_space_copy(space), map, i, qc,
 				left, right, &exact_i);
 		if (!*res)
 			goto error;
@@ -1281,10 +1290,10 @@ static int incemental_on_entire_domain(__isl_keep isl_space *dim,
 
 	isl_set_free(C);
 
-	return *res != NULL;
+	return isl_bool_ok(*res != NULL);
 error:
 	isl_set_free(C);
-	return -1;
+	return isl_bool_error;
 }
 
 /* Try and compute the transitive closure of "map" as
@@ -1295,8 +1304,8 @@ static int incemental_on_entire_domain(__isl_keep isl_space *dim,
  * with C either the simple hull of the domain and range of the entire
  * map or the simple hull of domain and range of map_i.
  */
-static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
-	__isl_keep isl_map *map, int *exact, int project)
+static __isl_give isl_map *incremental_closure(__isl_take isl_space *space,
+	__isl_keep isl_map *map, isl_bool *exact, int project)
 {
 	int i;
 	isl_set **dom = NULL;
@@ -1304,18 +1313,22 @@ static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
 	int *left = NULL;
 	int *right = NULL;
 	isl_set *C;
-	unsigned d;
+	isl_size d;
 	isl_map *res = NULL;
 
 	if (!project)
-		return construct_projected_component(dim, map, exact, project);
+		return construct_projected_component(space, map, exact,
+							project);
 
 	if (!map)
 		goto error;
 	if (map->n <= 1)
-		return construct_projected_component(dim, map, exact, project);
+		return construct_projected_component(space, map, exact,
+							project);
 
 	d = isl_map_dim(map, isl_dim_in);
+	if (d < 0)
+		goto error;
 
 	dom = isl_calloc_array(map->ctx, isl_set *, map->n);
 	ran = isl_calloc_array(map->ctx, isl_set *, map->n);
@@ -1324,12 +1337,14 @@ static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
 	if (!ran || !dom || !left || !right)
 		goto error;
 
-	if (incemental_on_entire_domain(dim, map, dom, ran, left, right, &res) < 0)
+	if (incremental_on_entire_domain(space, map, dom, ran, left, right,
+					&res) < 0)
 		goto error;
 
 	for (i = 0; !res && i < map->n; ++i) {
 		isl_map *qc;
-		int exact_i, spurious, comp;
+		int comp;
+		isl_bool exact_i, spurious;
 		if (!dom[i])
 			dom[i] = isl_set_from_basic_set(
 					isl_basic_map_domain(
@@ -1358,7 +1373,7 @@ static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
 				goto error;
 			continue;
 		}
-		qc = q_closure(isl_space_copy(dim), C, map->p[i], &exact_i);
+		qc = q_closure(isl_space_copy(space), C, map->p[i], &exact_i);
 		if (!qc)
 			goto error;
 		if (!exact_i) {
@@ -1383,7 +1398,7 @@ static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
 			isl_map_free(qc);
 			continue;
 		}
-		res = compute_incremental(isl_space_copy(dim), map, i, qc,
+		res = compute_incremental(isl_space_copy(space), map, i, qc,
 				(comp & LEFT) ? left : NULL,
 				(comp & RIGHT) ? right : NULL, &exact_i);
 		if (!res)
@@ -1404,11 +1419,11 @@ static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
 	free(right);
 
 	if (res) {
-		isl_space_free(dim);
+		isl_space_free(space);
 		return res;
 	}
 
-	return construct_projected_component(dim, map, exact, project);
+	return construct_projected_component(space, map, exact, project);
 error:
 	if (dom)
 		for (i = 0; i < map->n; ++i)
@@ -1420,7 +1435,7 @@ static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
 	free(ran);
 	free(left);
 	free(right);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -1467,38 +1482,46 @@ static int merge(isl_set **set, int *group, __isl_take isl_set *dom, int pos)
 	return -1;
 }
 
+/* Construct a map [x] -> [x+1], with parameters prescribed by "space".
+ */
+static __isl_give isl_map *increment(__isl_take isl_space *space)
+{
+	int k;
+	isl_basic_map *bmap;
+	isl_size total;
+
+	space = isl_space_set_from_params(space);
+	space = isl_space_add_dims(space, isl_dim_set, 1);
+	space = isl_space_map_from_set(space);
+	bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	k = isl_basic_map_alloc_equality(bmap);
+	if (total < 0 || k < 0)
+		goto error;
+	isl_seq_clr(bmap->eq[k], 1 + total);
+	isl_int_set_si(bmap->eq[k][0], 1);
+	isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_in)], 1);
+	isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_out)], -1);
+	return isl_map_from_basic_map(bmap);
+error:
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
 /* Replace each entry in the n by n grid of maps by the cross product
  * with the relation { [i] -> [i + 1] }.
  */
-static int add_length(__isl_keep isl_map *map, isl_map ***grid, int n)
+static isl_stat add_length(__isl_keep isl_map *map, isl_map ***grid, int n)
 {
-	int i, j, k;
-	isl_space *dim;
-	isl_basic_map *bstep;
+	int i, j;
+	isl_space *space;
 	isl_map *step;
-	unsigned nparam;
 
-	if (!map)
-		return -1;
+	space = isl_space_params(isl_map_get_space(map));
+	step = increment(space);
 
-	dim = isl_map_get_space(map);
-	nparam = isl_space_dim(dim, isl_dim_param);
-	dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
-	dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
-	dim = isl_space_add_dims(dim, isl_dim_in, 1);
-	dim = isl_space_add_dims(dim, isl_dim_out, 1);
-	bstep = isl_basic_map_alloc_space(dim, 0, 1, 0);
-	k = isl_basic_map_alloc_equality(bstep);
-	if (k < 0) {
-		isl_basic_map_free(bstep);
-		return -1;
-	}
-	isl_seq_clr(bstep->eq[k], 1 + isl_basic_map_total_dim(bstep));
-	isl_int_set_si(bstep->eq[k][0], 1);
-	isl_int_set_si(bstep->eq[k][1 + nparam], 1);
-	isl_int_set_si(bstep->eq[k][1 + nparam + 1], -1);
-	bstep = isl_basic_map_finalize(bstep);
-	step = isl_map_from_basic_map(bstep);
+	if (!step)
+		return isl_stat_error;
 
 	for (i = 0; i < n; ++i)
 		for (j = 0; j < n; ++j)
@@ -1507,7 +1530,7 @@ static int add_length(__isl_keep isl_map *map, isl_map ***grid, int n)
 
 	isl_map_free(step);
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* The core of the Floyd-Warshall algorithm.
@@ -1521,16 +1544,17 @@ static int add_length(__isl_keep isl_map *map, isl_map ***grid, int n)
  * transitive closure to account for all indirect paths that stay
  * in the current vertex.
  */
-static void floyd_warshall_iterate(isl_map ***grid, int n, int *exact)
+static void floyd_warshall_iterate(isl_map ***grid, int n, isl_bool *exact)
 {
 	int r, p, q;
 
 	for (r = 0; r < n; ++r) {
-		int r_exact;
+		isl_bool r_exact;
+		int check = exact && *exact == isl_bool_true;
 		grid[r][r] = isl_map_transitive_closure(grid[r][r],
-				(exact && *exact) ? &r_exact : NULL);
-		if (exact && *exact && !r_exact)
-			*exact = 0;
+				check ? &r_exact : NULL);
+		if (check && !r_exact)
+			*exact = isl_bool_false;
 
 		for (p = 0; p < n; ++p)
 			for (q = 0; q < n; ++q) {
@@ -1571,8 +1595,9 @@ static void floyd_warshall_iterate(isl_map ***grid, int n, int *exact)
  * the input relation by the cross product with the unit length relation
  * { [i] -> [i + 1] }.
  */
-static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_space *dim,
-	__isl_keep isl_map *map, int *exact, int project, int *group, int n)
+static __isl_give isl_map *floyd_warshall_with_groups(
+	__isl_take isl_space *space, __isl_keep isl_map *map,
+	isl_bool *exact, int project, int *group, int n)
 {
 	int i, j, k;
 	isl_map ***grid = NULL;
@@ -1583,7 +1608,7 @@ static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_space *dim,
 
 	if (n == 1) {
 		free(group);
-		return incremental_closure(dim, map, exact, project);
+		return incremental_closure(space, map, exact, project);
 	}
 
 	grid = isl_calloc_array(map->ctx, isl_map **, n);
@@ -1620,7 +1645,7 @@ static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_space *dim,
 	free(grid);
 
 	free(group);
-	isl_space_free(dim);
+	isl_space_free(space);
 
 	return app;
 error:
@@ -1634,7 +1659,7 @@ static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_space *dim,
 		}
 	free(grid);
 	free(group);
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -1710,8 +1735,8 @@ static int *setup_groups(isl_ctx *ctx, __isl_keep isl_basic_map **list, int n,
  * calls inside the Floyd-Warshall algorithm typically result in
  * non-linear path lengths quite quickly.
  */
-static __isl_give isl_map *floyd_warshall(__isl_take isl_space *dim,
-	__isl_keep isl_map *map, int *exact, int project)
+static __isl_give isl_map *floyd_warshall(__isl_take isl_space *space,
+	__isl_keep isl_map *map, isl_bool *exact, int project)
 {
 	int i;
 	isl_set **set = NULL;
@@ -1721,7 +1746,7 @@ static __isl_give isl_map *floyd_warshall(__isl_take isl_space *dim,
 	if (!map)
 		goto error;
 	if (map->n <= 1)
-		return incremental_closure(dim, map, exact, project);
+		return incremental_closure(space, map, exact, project);
 
 	group = setup_groups(map->ctx, map->p, map->n, &set, &n);
 	if (!group)
@@ -1732,9 +1757,9 @@ static __isl_give isl_map *floyd_warshall(__isl_take isl_space *dim,
 
 	free(set);
 
-	return floyd_warshall_with_groups(dim, map, exact, project, group, n);
+	return floyd_warshall_with_groups(space, map, exact, project, group, n);
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
@@ -1812,7 +1837,7 @@ static isl_bool basic_map_follows(int i, int j, void *user)
 	if (subset)
 		data->check_closed = 1;
 
-	return subset < 0 ? isl_bool_error : !subset;
+	return isl_bool_not(subset);
 error:
 	isl_map_free(map21);
 	return isl_bool_error;
@@ -1851,20 +1876,21 @@ static isl_bool basic_map_follows(int i, int j, void *user)
  * order, at each join also taking in the union of both arguments
  * to allow for paths that do not go through one of the two arguments.
  */
-static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
-	__isl_keep isl_map *map, int *exact, int project)
+static __isl_give isl_map *construct_power_components(
+	__isl_take isl_space *space, __isl_keep isl_map *map, isl_bool *exact,
+	int project)
 {
 	int i, n, c;
 	struct isl_map *path = NULL;
 	struct isl_tc_follows_data data;
 	struct isl_tarjan_graph *g = NULL;
-	int *orig_exact;
-	int local_exact;
+	isl_bool *orig_exact;
+	isl_bool local_exact;
 
 	if (!map)
 		goto error;
 	if (map->n <= 1)
-		return floyd_warshall(dim, map, exact, project);
+		return floyd_warshall(space, map, exact, project);
 
 	data.list = map->p;
 	data.check_closed = 0;
@@ -1882,7 +1908,7 @@ static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
 	if (project)
 		path = isl_map_empty(isl_map_get_space(map));
 	else
-		path = isl_map_empty(isl_space_copy(dim));
+		path = isl_map_empty(isl_space_copy(space));
 	path = anonymize(path);
 	while (n) {
 		struct isl_map *comp;
@@ -1894,7 +1920,7 @@ static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
 			--n;
 			++i;
 		}
-		path_comp = floyd_warshall(isl_space_copy(dim),
+		path_comp = floyd_warshall(isl_space_copy(space),
 						comp, exact, project);
 		path_comp = anonymize(path_comp);
 		path_comb = isl_map_apply_range(isl_map_copy(path),
@@ -1907,7 +1933,7 @@ static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
 	}
 
 	if (c > 1 && data.check_closed && !*exact) {
-		int closed;
+		isl_bool closed;
 
 		closed = isl_map_is_transitively_closed(path);
 		if (closed < 0)
@@ -1915,17 +1941,17 @@ static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
 		if (!closed) {
 			isl_tarjan_graph_free(g);
 			isl_map_free(path);
-			return floyd_warshall(dim, map, orig_exact, project);
+			return floyd_warshall(space, map, orig_exact, project);
 		}
 	}
 
 	isl_tarjan_graph_free(g);
-	isl_space_free(dim);
+	isl_space_free(space);
 
 	return path;
 error:
 	isl_tarjan_graph_free(g);
-	isl_space_free(dim);
+	isl_space_free(space);
 	isl_map_free(path);
 	return NULL;
 }
@@ -1960,23 +1986,23 @@ static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
  * image element(s).
  */
 static __isl_give isl_map *construct_power(__isl_keep isl_map *map,
-	int *exact, int project)
+	isl_bool *exact, int project)
 {
 	struct isl_map *app = NULL;
-	isl_space *dim = NULL;
+	isl_space *space = NULL;
 
 	if (!map)
 		return NULL;
 
-	dim = isl_map_get_space(map);
+	space = isl_map_get_space(map);
 
-	dim = isl_space_add_dims(dim, isl_dim_in, 1);
-	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+	space = isl_space_add_dims(space, isl_dim_in, 1);
+	space = isl_space_add_dims(space, isl_dim_out, 1);
 
-	app = construct_power_components(isl_space_copy(dim), map,
+	app = construct_power_components(isl_space_copy(space), map,
 					exact, project);
 
-	isl_space_free(dim);
+	isl_space_free(space);
 
 	return app;
 }
@@ -1990,28 +2016,20 @@ static __isl_give isl_map *construct_power(__isl_keep isl_map *map,
  * encoded as the 
diff erence between an extra pair of final coordinates.
  */
 static __isl_give isl_map *map_power(__isl_take isl_map *map,
-	int *exact, int project)
+	isl_bool *exact, int project)
 {
 	struct isl_map *app = NULL;
 
 	if (exact)
-		*exact = 1;
+		*exact = isl_bool_true;
 
-	if (!map)
-		return NULL;
-
-	isl_assert(map->ctx,
-		isl_map_dim(map, isl_dim_in) == isl_map_dim(map, isl_dim_out),
-		goto error);
+	if (isl_map_check_equal_tuples(map) < 0)
+		return isl_map_free(map);
 
 	app = construct_power(map, exact, project);
 
 	isl_map_free(map);
 	return app;
-error:
-	isl_map_free(map);
-	isl_map_free(app);
-	return NULL;
 }
 
 /* Compute the positive powers of "map", or an overapproximation.
@@ -2023,19 +2041,18 @@ static __isl_give isl_map *map_power(__isl_take isl_map *map,
  * and made positive.  The extra coordinates are subsequently projected out
  * and the parameter is turned into the domain of the result.
  */
-__isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact)
+__isl_give isl_map *isl_map_power(__isl_take isl_map *map, isl_bool *exact)
 {
-	isl_space *target_dim;
-	isl_space *dim;
+	isl_space *target_space;
+	isl_space *space;
 	isl_map *
diff ;
-	unsigned d;
-	unsigned param;
-
-	if (!map)
-		return NULL;
+	isl_size d;
+	isl_size param;
 
 	d = isl_map_dim(map, isl_dim_in);
 	param = isl_map_dim(map, isl_dim_param);
+	if (d < 0 || param < 0)
+		return isl_map_free(map);
 
 	map = isl_map_compute_divs(map);
 	map = isl_map_coalesce(map);
@@ -2047,23 +2064,23 @@ __isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact)
 		return map;
 	}
 
-	target_dim = isl_map_get_space(map);
-	target_dim = isl_space_from_range(isl_space_wrap(target_dim));
-	target_dim = isl_space_add_dims(target_dim, isl_dim_in, 1);
-	target_dim = isl_space_set_dim_name(target_dim, isl_dim_in, 0, "k");
+	target_space = isl_map_get_space(map);
+	target_space = isl_space_from_range(isl_space_wrap(target_space));
+	target_space = isl_space_add_dims(target_space, isl_dim_in, 1);
+	target_space = isl_space_set_dim_name(target_space, isl_dim_in, 0, "k");
 
 	map = map_power(map, exact, 0);
 
 	map = isl_map_add_dims(map, isl_dim_param, 1);
-	dim = isl_map_get_space(map);
-	
diff  = equate_parameter_to_length(dim, param);
+	space = isl_map_get_space(map);
+	
diff  = equate_parameter_to_length(space, param);
 	map = isl_map_intersect(map, 
diff );
 	map = isl_map_project_out(map, isl_dim_in, d, 1);
 	map = isl_map_project_out(map, isl_dim_out, d, 1);
 	map = isl_map_from_range(isl_map_wrap(map));
 	map = isl_map_move_dims(map, isl_dim_in, 0, isl_dim_param, param, 1);
 
-	map = isl_map_reset_space(map, target_dim);
+	map = isl_map_reset_space(map, target_space);
 
 	return map;
 }
@@ -2078,25 +2095,24 @@ __isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact)
  * of a parameter.
  */
 __isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
-	int *exact)
+	isl_bool *exact)
 {
-	isl_space *dim;
+	isl_space *space;
 	isl_map *
diff ;
-	unsigned d;
-	unsigned param;
-
-	if (!map)
-		return NULL;
+	isl_size d;
+	isl_size param;
 
 	d = isl_map_dim(map, isl_dim_in);
 	param = isl_map_dim(map, isl_dim_param);
+	if (d < 0 || param < 0)
+		return isl_map_free(map);
 
 	map = isl_map_compute_divs(map);
 	map = isl_map_coalesce(map);
 
 	if (isl_map_plain_is_empty(map)) {
 		if (exact)
-			*exact = 1;
+			*exact = isl_bool_true;
 		map = isl_map_project_out(map, isl_dim_out, 0, d);
 		map = isl_map_add_dims(map, isl_dim_out, 1);
 		return map;
@@ -2105,8 +2121,8 @@ __isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
 	map = map_power(map, exact, 0);
 
 	map = isl_map_add_dims(map, isl_dim_param, 1);
-	dim = isl_map_get_space(map);
-	
diff  = equate_parameter_to_length(dim, param);
+	space = isl_map_get_space(map);
+	
diff  = equate_parameter_to_length(space, param);
 	map = isl_map_intersect(map, 
diff );
 	map = isl_map_project_out(map, isl_dim_in, 0, d + 1);
 	map = isl_map_project_out(map, isl_dim_out, d, 1);
@@ -2321,25 +2337,25 @@ static __isl_give isl_map *box_closure_with_identity(__isl_take isl_map *map,
  *
  *	app \subset (map \cup (map \circ app))
  */
-static int check_exactness_omega(__isl_keep isl_map *map,
+static isl_bool check_exactness_omega(__isl_keep isl_map *map,
 	__isl_keep isl_map *app)
 {
 	isl_set *delta;
 	int i;
-	int is_empty, is_exact;
-	unsigned d;
+	isl_bool is_empty, is_exact;
+	isl_size d;
 	isl_map *test;
 
 	delta = isl_map_deltas(isl_map_copy(app));
 	d = isl_set_dim(delta, isl_dim_set);
+	if (d < 0)
+		delta = isl_set_free(delta);
 	for (i = 0; i < d; ++i)
 		delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
 	is_empty = isl_set_is_empty(delta);
 	isl_set_free(delta);
-	if (is_empty < 0)
-		return -1;
-	if (!is_empty)
-		return 0;
+	if (is_empty < 0 || !is_empty)
+		return is_empty;
 
 	test = isl_map_apply_range(isl_map_copy(app), isl_map_copy(map));
 	test = isl_map_union(test, isl_map_copy(map));
@@ -2444,13 +2460,19 @@ static int can_be_split_off(__isl_keep isl_map *map, int i,
 }
 
 static __isl_give isl_map *box_closure_with_check(__isl_take isl_map *map,
-	int *exact)
+	isl_bool *exact)
 {
 	isl_map *app;
 
 	app = box_closure(isl_map_copy(map));
-	if (exact)
-		*exact = check_exactness_omega(map, app);
+	if (exact) {
+		isl_bool is_exact = check_exactness_omega(map, app);
+
+		if (is_exact < 0)
+			app = isl_map_free(app);
+		else
+			*exact = is_exact;
+	}
 
 	isl_map_free(map);
 	return app;
@@ -2475,10 +2497,10 @@ static __isl_give isl_map *box_closure_with_check(__isl_take isl_map *map,
  * If not, we simply call box_closure on the whole map.
  */
 static __isl_give isl_map *transitive_closure_omega(__isl_take isl_map *map,
-	int *exact)
+	isl_bool *exact)
 {
 	int i, j;
-	int exact_i;
+	isl_bool exact_i;
 	isl_map *app;
 
 	if (!map)
@@ -2509,7 +2531,7 @@ static __isl_give isl_map *transitive_closure_omega(__isl_take isl_map *map,
 
 		app = isl_map_union(tc, transitive_closure_omega(app, NULL));
 		exact_i = check_exactness_omega(map, app);
-		if (exact_i == 1) {
+		if (exact_i == isl_bool_true) {
 			if (exact)
 				*exact = exact_i;
 			isl_map_free(map);
@@ -2533,10 +2555,10 @@ static __isl_give isl_map *transitive_closure_omega(__isl_take isl_map *map,
  * the length to a parameter.
  */
 __isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
-	int *exact)
+	isl_bool *exact)
 {
 	isl_space *target_dim;
-	int closed;
+	isl_bool closed;
 
 	if (!map)
 		goto error;
@@ -2551,7 +2573,7 @@ __isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
 		goto error;
 	if (closed) {
 		if (exact)
-			*exact = 1;
+			*exact = isl_bool_true;
 		return map;
 	}
 
@@ -2601,10 +2623,10 @@ static isl_stat collect_basic_map(__isl_take isl_map *map, void *user)
  * grid have domains and ranges of the same dimension and so
  * the standard algorithm can be used because the nested transitive
  * closures are only applied to diagonal elements and because all
- * compositions are peformed on relations with compatible domains and ranges.
+ * compositions are performed on relations with compatible domains and ranges.
  */
 static __isl_give isl_union_map *union_floyd_warshall_on_list(isl_ctx *ctx,
-	__isl_keep isl_basic_map **list, int n, int *exact)
+	__isl_keep isl_basic_map **list, int n, isl_bool *exact)
 {
 	int i, j, k;
 	int n_group;
@@ -2625,11 +2647,11 @@ static __isl_give isl_union_map *union_floyd_warshall_on_list(isl_ctx *ctx,
 		if (!grid[i])
 			goto error;
 		for (j = 0; j < n_group; ++j) {
-			isl_space *dim1, *dim2, *dim;
-			dim1 = isl_space_reverse(isl_set_get_space(set[i]));
-			dim2 = isl_set_get_space(set[j]);
-			dim = isl_space_join(dim1, dim2);
-			grid[i][j] = isl_map_empty(dim);
+			isl_space *space1, *space2, *space;
+			space1 = isl_space_reverse(isl_set_get_space(set[i]));
+			space2 = isl_set_get_space(set[j]);
+			space = isl_space_join(space1, space2);
+			grid[i][j] = isl_map_empty(space);
 		}
 	}
 
@@ -2684,7 +2706,7 @@ static __isl_give isl_union_map *union_floyd_warshall_on_list(isl_ctx *ctx,
  * and then perform the algorithm on this list.
  */
 static __isl_give isl_union_map *union_floyd_warshall(
-	__isl_take isl_union_map *umap, int *exact)
+	__isl_take isl_union_map *umap, isl_bool *exact)
 {
 	int i, n;
 	isl_ctx *ctx;
@@ -2731,7 +2753,7 @@ static __isl_give isl_union_map *union_floyd_warshall(
  * operations are performed on union maps.
  */
 static __isl_give isl_union_map *union_components(
-	__isl_take isl_union_map *umap, int *exact)
+	__isl_take isl_union_map *umap, isl_bool *exact)
 {
 	int i;
 	int n;
@@ -2793,7 +2815,7 @@ static __isl_give isl_union_map *union_components(
 	}
 
 	if (c > 1 && data.check_closed && !*exact) {
-		int closed;
+		isl_bool closed;
 
 		closed = isl_union_map_is_transitively_closed(path);
 		if (closed < 0)
@@ -2831,15 +2853,15 @@ static __isl_give isl_union_map *union_components(
  * If the result is exact, then *exact is set to 1.
  */
 __isl_give isl_union_map *isl_union_map_transitive_closure(
-	__isl_take isl_union_map *umap, int *exact)
+	__isl_take isl_union_map *umap, isl_bool *exact)
 {
-	int closed;
+	isl_bool closed;
 
 	if (!umap)
 		return NULL;
 
 	if (exact)
-		*exact = 1;
+		*exact = isl_bool_true;
 
 	umap = isl_union_map_compute_divs(umap);
 	umap = isl_union_map_coalesce(umap);
@@ -2857,7 +2879,7 @@ __isl_give isl_union_map *isl_union_map_transitive_closure(
 
 struct isl_union_power {
 	isl_union_map *pow;
-	int *exact;
+	isl_bool *exact;
 };
 
 static isl_stat power(__isl_take isl_map *map, void *user)
@@ -2870,29 +2892,6 @@ static isl_stat power(__isl_take isl_map *map, void *user)
 	return isl_stat_error;
 }
 
-/* Construct a map [x] -> [x+1], with parameters prescribed by "dim".
- */
-static __isl_give isl_union_map *increment(__isl_take isl_space *dim)
-{
-	int k;
-	isl_basic_map *bmap;
-
-	dim = isl_space_add_dims(dim, isl_dim_in, 1);
-	dim = isl_space_add_dims(dim, isl_dim_out, 1);
-	bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
-	k = isl_basic_map_alloc_equality(bmap);
-	if (k < 0)
-		goto error;
-	isl_seq_clr(bmap->eq[k], isl_basic_map_total_dim(bmap));
-	isl_int_set_si(bmap->eq[k][0], 1);
-	isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_in)], 1);
-	isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_out)], -1);
-	return isl_union_map_from_map(isl_map_from_basic_map(bmap));
-error:
-	isl_basic_map_free(bmap);
-	return NULL;
-}
-
 /* Construct a map [[x]->[y]] -> [y-x], with parameters prescribed by "dim".
  */
 static __isl_give isl_union_map *deltas_map(__isl_take isl_space *dim)
@@ -2912,15 +2911,15 @@ static __isl_give isl_union_map *deltas_map(__isl_take isl_space *dim)
  * If the result is exact, then *exact is set to 1.
  */
 __isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
-	int *exact)
+	isl_bool *exact)
 {
-	int n;
+	isl_size n;
 	isl_union_map *inc;
 	isl_union_map *dm;
 
-	if (!umap)
-		return NULL;
 	n = isl_union_map_n_map(umap);
+	if (n < 0)
+		return isl_union_map_free(umap);
 	if (n == 0)
 		return umap;
 	if (n == 1) {
@@ -2929,7 +2928,7 @@ __isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
 		isl_union_map_free(umap);
 		return up.pow;
 	}
-	inc = increment(isl_union_map_get_space(umap));
+	inc = isl_union_map_from_map(increment(isl_union_map_get_space(umap)));
 	umap = isl_union_map_product(inc, umap);
 	umap = isl_union_map_transitive_closure(umap, exact);
 	umap = isl_union_map_zip(umap);

diff  --git a/polly/lib/External/isl/isl_type_check_equal_space_templ.c b/polly/lib/External/isl/isl_type_check_equal_space_templ.c
new file mode 100644
index 000000000000..97a0a354a071
--- /dev/null
+++ b/polly/lib/External/isl/isl_type_check_equal_space_templ.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011      Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege
+ */
+
+/* Check that "obj1" and "obj2" live in the same space,
+ * reporting an error if they do not.
+ */
+isl_stat FN(TYPE_PAIR,check_equal_space)(__isl_keep TYPE1 *obj1,
+	__isl_keep TYPE2 *obj2)
+{
+	isl_bool equal;
+
+	equal = FN(TYPE_PAIR,has_equal_space)(obj1, obj2);
+	if (equal < 0)
+		return isl_stat_error;
+	if (!equal)
+		isl_die(FN(TYPE1,get_ctx)(obj1), isl_error_invalid,
+			"spaces don't match", return isl_stat_error);
+
+	return isl_stat_ok;
+}

diff  --git a/polly/lib/External/isl/isl_type_has_equal_space_bin_templ.c b/polly/lib/External/isl/isl_type_has_equal_space_bin_templ.c
new file mode 100644
index 000000000000..f435753aec7c
--- /dev/null
+++ b/polly/lib/External/isl/isl_type_has_equal_space_bin_templ.c
@@ -0,0 +1,8 @@
+#undef TYPE1
+#define TYPE1		TYPE
+#undef TYPE2
+#define TYPE2		TYPE
+#undef TYPE_PAIR
+#define TYPE_PAIR	TYPE
+
+#include "isl_type_has_equal_space_templ.c"

diff  --git a/polly/lib/External/isl/isl_type_has_equal_space_templ.c b/polly/lib/External/isl/isl_type_has_equal_space_templ.c
new file mode 100644
index 000000000000..2753d4599a4c
--- /dev/null
+++ b/polly/lib/External/isl/isl_type_has_equal_space_templ.c
@@ -0,0 +1,28 @@
+/*
+ * 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
+ */
+
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+#ifndef PEEK_SPACE
+#define PEEK_SPACE	peek_space
+#endif
+
+/* Do "obj1" and "obj2" have the same space?
+ */
+isl_bool FN(TYPE_PAIR,has_equal_space)(__isl_keep TYPE1 *obj1,
+	__isl_keep TYPE2 *obj2)
+{
+	isl_space *space1, *space2;
+
+	space1 = FN(TYPE1,PEEK_SPACE)(obj1);
+	space2 = FN(TYPE2,PEEK_SPACE)(obj2);
+	return isl_space_is_equal(space1, space2);
+}

diff  --git a/polly/lib/External/isl/isl_union_eval.c b/polly/lib/External/isl/isl_union_eval.c
index b26a74d52886..bc222ab00f40 100644
--- a/polly/lib/External/isl/isl_union_eval.c
+++ b/polly/lib/External/isl/isl_union_eval.c
@@ -26,7 +26,7 @@ static __isl_give isl_val *FN(UNION,eval_void)(__isl_take UNION *u,
 
 /* Is the domain space of "entry" equal to "space"?
  */
-static int FN(UNION,has_domain_space)(const void *entry, const void *val)
+static isl_bool FN(UNION,has_domain_space)(const void *entry, const void *val)
 {
 	PART *part = (PART *)entry;
 	isl_space *space = (isl_space *) val;
@@ -63,7 +63,9 @@ __isl_give isl_val *FN(UNION,eval)(__isl_take UNION *u,
 				    hash, &FN(UNION,has_domain_space),
 				    space, 0);
 	isl_space_free(space);
-	if (!entry) {
+	if (!entry)
+		goto error;
+	if (entry == isl_hash_table_entry_none) {
 		v = isl_val_zero(isl_point_get_ctx(pnt));
 		isl_point_free(pnt);
 	} else {

diff  --git a/polly/lib/External/isl/isl_union_map.c b/polly/lib/External/isl/isl_union_map.c
index 5ea7c400b878..b237fa88b84d 100644
--- a/polly/lib/External/isl/isl_union_map.c
+++ b/polly/lib/External/isl/isl_union_map.c
@@ -23,6 +23,7 @@
 #include <isl_space_private.h>
 #include <isl/union_set.h>
 #include <isl_maybe_map.h>
+#include <isl_id_private.h>
 
 #include <bset_from_bmap.c>
 #include <set_to_map.c>
@@ -34,15 +35,15 @@
 /* Return the number of parameters of "umap", where "type"
  * is required to be set to isl_dim_param.
  */
-unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+isl_size isl_union_map_dim(__isl_keep isl_union_map *umap,
 	enum isl_dim_type type)
 {
 	if (!umap)
-		return 0;
+		return isl_size_error;
 
 	if (type != isl_dim_param)
 		isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
-			"can only reference parameters", return 0);
+			"can only reference parameters", return isl_size_error);
 
 	return isl_space_dim(umap->dim, type);
 }
@@ -50,7 +51,7 @@ unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
 /* Return the number of parameters of "uset", where "type"
  * is required to be set to isl_dim_param.
  */
-unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+isl_size isl_union_set_dim(__isl_keep isl_union_set *uset,
 	enum isl_dim_type type)
 {
 	return isl_union_map_dim(uset, type);
@@ -121,14 +122,42 @@ static __isl_give isl_union_map *isl_union_map_alloc(
 	return umap;
 }
 
-__isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *space)
+/* Create an empty union map without specifying any parameters.
+ */
+__isl_give isl_union_map *isl_union_map_empty_ctx(isl_ctx *ctx)
+{
+	return isl_union_map_empty_space(isl_space_unit(ctx));
+}
+
+__isl_give isl_union_map *isl_union_map_empty_space(__isl_take isl_space *space)
 {
 	return isl_union_map_alloc(space, 16);
 }
 
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *space)
+{
+	return isl_union_map_empty_space(space);
+}
+
+/* Create an empty union set without specifying any parameters.
+ */
+__isl_give isl_union_set *isl_union_set_empty_ctx(isl_ctx *ctx)
+{
+	return uset_from_umap(isl_union_map_empty_ctx(ctx));
+}
+
+__isl_give isl_union_set *isl_union_set_empty_space(__isl_take isl_space *space)
+{
+	return uset_from_umap(isl_union_map_empty_space(space));
+}
+
+/* This is an alternative name for the function above.
+ */
 __isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *space)
 {
-	return isl_union_map_empty(space);
+	return isl_union_set_empty_space(space);
 }
 
 isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap)
@@ -148,6 +177,13 @@ __isl_keep isl_space *isl_union_map_peek_space(__isl_keep isl_union_map *umap)
 	return umap ? umap->dim : NULL;
 }
 
+/* Return the space of "uset".
+ */
+__isl_keep isl_space *isl_union_set_peek_space(__isl_keep isl_union_set *uset)
+{
+	return isl_union_map_peek_space(uset_to_umap(uset));
+}
+
 __isl_give isl_space *isl_union_map_get_space(__isl_keep isl_union_map *umap)
 {
 	return isl_space_copy(isl_union_map_peek_space(umap));
@@ -366,7 +402,7 @@ isl_bool isl_union_set_space_has_equal_params(__isl_keep isl_union_set *uset,
 	return isl_union_map_space_has_equal_params(uset_to_umap(uset), space);
 }
 
-static int has_space(const void *entry, const void *val)
+static isl_bool has_space(const void *entry, const void *val)
 {
 	isl_map *map = (isl_map *)entry;
 	isl_space *space = (isl_space *) val;
@@ -478,14 +514,14 @@ static isl_stat call_on_copy(void **entry, void *user)
 	return data->fn(isl_map_copy(map), data->user);
 }
 
-int isl_union_map_n_map(__isl_keep isl_union_map *umap)
+isl_size isl_union_map_n_map(__isl_keep isl_union_map *umap)
 {
-	return umap ? umap->table.n : 0;
+	return umap ? umap->table.n : isl_size_error;
 }
 
-int isl_union_set_n_set(__isl_keep isl_union_set *uset)
+isl_size isl_union_set_n_set(__isl_keep isl_union_set *uset)
 {
-	return uset ? uset->table.n : 0;
+	return uset ? uset->table.n : isl_size_error;
 }
 
 isl_stat isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
@@ -573,14 +609,14 @@ static isl_stat add_list_map(__isl_take isl_map *map, void *user)
 __isl_give isl_map_list *isl_union_map_get_map_list(
 	__isl_keep isl_union_map *umap)
 {
-	int n_maps;
+	isl_size n_maps;
 	isl_ctx *ctx;
 	isl_map_list *list;
 
-	if (!umap)
+	n_maps = isl_union_map_n_map(umap);
+	if (n_maps < 0)
 		return NULL;
 	ctx = isl_union_map_get_ctx(umap);
-	n_maps = isl_union_map_n_map(umap);
 	list = isl_map_list_alloc(ctx, n_maps);
 
 	if (isl_union_map_foreach_map(umap, &add_list_map, &list) < 0)
@@ -598,6 +634,27 @@ __isl_give isl_set_list *isl_union_set_get_set_list(
 		isl_union_map_get_map_list(uset_to_umap(uset)));
 }
 
+/* Can "umap" be converted to an isl_map?
+ * That is, does it contain elements in exactly one space?
+ */
+isl_bool isl_union_map_isa_map(__isl_keep isl_union_map *umap)
+{
+	isl_size n;
+
+	n = isl_union_map_n_map(umap);
+	if (n < 0)
+		return isl_bool_error;
+	return isl_bool_ok(n == 1);
+}
+
+/* Can "uset" be converted to an isl_set?
+ * That is, does it contain elements in exactly one space?
+ */
+isl_bool isl_union_set_isa_set(__isl_keep isl_union_set *uset)
+{
+	return isl_union_map_isa_map(uset_to_umap(uset));
+}
+
 static isl_stat copy_map(void **entry, void *user)
 {
 	isl_map *map = *entry;
@@ -610,13 +667,15 @@ static isl_stat copy_map(void **entry, void *user)
 
 __isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap)
 {
+	isl_bool is_map;
 	isl_ctx *ctx;
 	isl_map *map = NULL;
 
-	if (!umap)
-		return NULL;
+	is_map = isl_union_map_isa_map(umap);
+	if (is_map < 0)
+		goto error;
 	ctx = isl_union_map_get_ctx(umap);
-	if (umap->table.n != 1)
+	if (!is_map)
 		isl_die(ctx, isl_error_invalid,
 			"union map needs to contain elements in exactly "
 			"one space", goto error);
@@ -645,8 +704,7 @@ __isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
 	uint32_t hash;
 	struct isl_hash_table_entry *entry;
 
-	space = isl_space_drop_dims(space, isl_dim_param,
-					0, isl_space_dim(space, isl_dim_param));
+	space = isl_space_drop_all_params(space);
 	space = isl_space_align_params(space, isl_union_map_get_space(umap));
 	if (!umap || !space)
 		goto error;
@@ -655,6 +713,8 @@ __isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
 	entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
 				    &has_space, space, 0);
 	if (!entry)
+		goto error;
+	if (entry == isl_hash_table_entry_none)
 		return isl_map_empty(space);
 	isl_space_free(space);
 	return isl_map_copy(entry->data);
@@ -664,9 +724,9 @@ __isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
 }
 
 __isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
-	__isl_take isl_space *dim)
+	__isl_take isl_space *space)
 {
-	return set_from_map(isl_union_map_extract_map(uset, dim));
+	return set_from_map(isl_union_map_extract_map(uset, space));
 }
 
 /* Check if umap contains a map in the given space.
@@ -683,7 +743,9 @@ isl_bool isl_union_map_contains(__isl_keep isl_union_map *umap,
 	hash = isl_space_get_hash(space);
 	entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
 				    &has_space, space, 0);
-	return !!entry;
+	if (!entry)
+		return isl_bool_error;
+	return isl_bool_ok(entry != isl_hash_table_entry_none);
 }
 
 isl_bool isl_union_set_contains(__isl_keep isl_union_set *uset,
@@ -699,6 +761,37 @@ isl_stat isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
 		(isl_stat(*)(__isl_take isl_map *, void*))fn, user);
 }
 
+/* Internal data structure for isl_union_set_every_set.
+ *
+ * "test" is the user-specified callback function.
+ * "user" is the user-specified callback function argument.
+ */
+struct isl_test_set_from_map_data {
+	isl_bool (*test)(__isl_keep isl_set *set, void *user);
+	void *user;
+};
+
+/* Call data->test on "map", which is part of an isl_union_set and
+ * therefore known to be an isl_set.
+ */
+static isl_bool test_set_from_map(__isl_keep isl_map *map, void *user)
+{
+	struct isl_test_set_from_map_data *data = user;
+
+	return data->test(set_from_map(map), data->user);
+}
+
+/* Does "test" succeed on every set in "uset"?
+ */
+isl_bool isl_union_set_every_set(__isl_keep isl_union_set *uset,
+	isl_bool (*test)(__isl_keep isl_set *set, void *user), void *user)
+{
+	struct isl_test_set_from_map_data data = { test, user };
+
+	return isl_union_map_every_map(uset_to_umap(uset),
+					&test_set_from_map, &data);
+}
+
 struct isl_union_set_foreach_point_data {
 	isl_stat (*fn)(__isl_take isl_point *pnt, void *user);
 	void *user;
@@ -829,8 +922,9 @@ static __isl_keep isl_maybe_isl_map bin_try_get_match(
 				     &data->umap2->table, hash,
 				     &has_space, space, 0);
 	isl_space_free(space);
-	res.valid = entry2 != NULL;
 	if (entry2)
+		res.valid = isl_bool_ok(entry2 != isl_hash_table_entry_none);
+	if (res.valid >= 0 && res.valid)
 		res.value = entry2->data;
 
 	return res;
@@ -1031,6 +1125,8 @@ static isl_stat match_bin_entry(void **entry, void *user)
 	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
 				     hash, &has_space, map->dim, 0);
 	if (!entry2)
+		return isl_stat_error;
+	if (entry2 == isl_hash_table_entry_none)
 		return isl_stat_ok;
 
 	map = isl_map_copy(map);
@@ -1331,6 +1427,38 @@ __isl_give isl_union_map *isl_union_map_intersect_range(
 	return gen_bin_op(umap, uset, &control);
 }
 
+/* Intersect each map in "umap" in a space [A -> B] -> C
+ * with the corresponding map in "factor" in the space B -> C and
+ * collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_intersect_domain_factor_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_map *factor)
+{
+	struct isl_bin_op_control control = {
+		.filter = &isl_map_domain_is_wrapping,
+		.match_space = &isl_space_domain_factor_range,
+		.fn_map = &isl_map_intersect_domain_factor_range,
+	};
+
+	return gen_bin_op(umap, factor, &control);
+}
+
+/* Intersect each map in "umap" in a space A -> [B -> C]
+ * with the corresponding map in "factor" in the space A -> B and
+ * collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_intersect_range_factor_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_map *factor)
+{
+	struct isl_bin_op_control control = {
+		.filter = &isl_map_range_is_wrapping,
+		.match_space = &isl_space_range_factor_domain,
+		.fn_map = &isl_map_intersect_range_factor_domain,
+	};
+
+	return gen_bin_op(umap, factor, &control);
+}
+
 /* Intersect each map in "umap" in a space A -> [B -> C]
  * with the corresponding map in "factor" in the space A -> C and
  * collect the results.
@@ -1636,8 +1764,9 @@ __isl_give isl_union_map *isl_union_map_flat_range_product(
  * are taken into account.  "filter_user" is passed as the second argument
  * to "filter".  No filter can be set if "inplace" or
  * "total" is set.
- * "fn_map" specifies how the maps (selected by "filter")
- * should be transformed.
+ * Exactly one of "fn_map" or "fn_map2" should be set, specifying
+ * how the maps (selected by "filter") should be transformed.
+ * If "fn_map2" is set, then "fn_map2_user" is passed as the second argument.
  */
 struct isl_un_op_control {
 	int inplace;
@@ -1645,6 +1774,8 @@ struct isl_un_op_control {
 	isl_bool (*filter)(__isl_keep isl_map *map, void *user);
 	void *filter_user;
 	__isl_give isl_map *(*fn_map)(__isl_take isl_map *map);
+	__isl_give isl_map *(*fn_map2)(__isl_take isl_map *map, void *user);
+	void *fn_map2_user;
 };
 
 /* Data structure for wrapping the data for un_op_filter_drop_user.
@@ -1678,28 +1809,34 @@ struct isl_union_map_un_data {
  *
  * If control->filter is set, then check if this map satisfies the filter.
  * If so (or if control->filter is not set), modify the map
- * by calling control->fn_map and either add the result to data->res or
+ * by calling control->fn_map or control->fn_map2 and
+ * either add the result to data->res or
  * replace the original entry by the result (if control->inplace is set).
  */
 static isl_stat un_entry(void **entry, void *user)
 {
 	struct isl_union_map_un_data *data = user;
+	struct isl_un_op_control *control = data->control;
 	isl_map *map = *entry;
 
-	if (data->control->filter) {
+	if (control->filter) {
 		isl_bool ok;
 
-		ok = data->control->filter(map, data->control->filter_user);
+		ok = control->filter(map, control->filter_user);
 		if (ok < 0)
 			return isl_stat_error;
 		if (!ok)
 			return isl_stat_ok;
 	}
 
-	map = data->control->fn_map(isl_map_copy(map));
+	map = isl_map_copy(map);
+	if (control->fn_map2 != NULL)
+		map = control->fn_map2(map, control->fn_map2_user);
+	else
+		map = control->fn_map(map);
 	if (!map)
 		return isl_stat_error;
-	if (data->control->inplace) {
+	if (control->inplace) {
 		isl_map_free(*entry);
 		*entry = map;
 	} else {
@@ -1725,6 +1862,10 @@ static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap,
 
 	if (!umap)
 		return NULL;
+	if (!!control->fn_map == !!control->fn_map2)
+		isl_die(isl_union_map_get_ctx(umap), isl_error_internal,
+			"exactly one mapping function should be specified",
+			return isl_union_map_free(umap));
 	if ((control->inplace || control->total) && control->filter)
 		isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
 			"inplace/total modification cannot be filtered",
@@ -1988,6 +2129,21 @@ __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
 	return un_op(umap, &control);
 }
 
+/* Given a union map, take the maps of the form A -> (B -> C) and
+ * return the union of the corresponding maps A -> (C -> B).
+ */
+__isl_give isl_union_map *isl_union_map_range_reverse(
+	__isl_take isl_union_map *umap)
+{
+	struct isl_un_op_drop_user_data data = { &isl_map_range_is_wrapping };
+	struct isl_un_op_control control = {
+		.filter = &un_op_filter_drop_user,
+		.filter_user = &data,
+		.fn_map = &isl_map_range_reverse,
+	};
+	return un_op(umap, &control);
+}
+
 /* Compute the parameter domain of the given union map.
  */
 __isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap)
@@ -2292,13 +2448,15 @@ static isl_stat is_subset_entry(void **entry, void *user)
 	hash = isl_space_get_hash(map->dim);
 	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
 				     hash, &has_space, map->dim, 0);
-	if (!entry2) {
+	if (!entry2)
+		return isl_stat_error;
+	if (entry2 == isl_hash_table_entry_none) {
 		int empty = isl_map_is_empty(map);
 		if (empty < 0)
 			return isl_stat_error;
 		if (empty)
 			return isl_stat_ok;
-		data->is_subset = 0;
+		data->is_subset = isl_bool_false;
 		return isl_stat_error;
 	}
 
@@ -2375,9 +2533,7 @@ isl_bool isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
 	if (is_subset != isl_bool_true)
 		return is_subset;
 	is_subset = isl_union_map_is_subset(umap2, umap1);
-	if (is_subset == isl_bool_error)
-		return is_subset;
-	return !is_subset;
+	return isl_bool_not(is_subset);
 }
 
 isl_bool isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
@@ -2410,6 +2566,8 @@ static isl_stat is_disjoint_entry(void **entry, void *user)
 	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
 				     hash, &has_space, map->dim, 0);
 	if (!entry2)
+		return isl_stat_error;
+	if (entry2 == isl_hash_table_entry_none)
 		return isl_stat_ok;
 
 	data->is_disjoint = isl_map_is_disjoint(map, entry2->data);
@@ -2586,9 +2744,12 @@ static isl_bool union_map_forall_user(__isl_keep isl_union_map *umap,
  */
 isl_bool isl_union_map_plain_is_empty(__isl_keep isl_union_map *umap)
 {
-	if (!umap)
+	isl_size n;
+
+	n = isl_union_map_n_map(umap);
+	if (n < 0)
 		return isl_bool_error;
-	return isl_union_map_n_map(umap) == 0;
+	return n == 0;
 }
 
 isl_bool isl_union_map_is_empty(__isl_keep isl_union_map *umap)
@@ -2669,12 +2830,16 @@ static isl_stat single_valued_on_domain(__isl_take isl_set *set, void *user)
 {
 	struct isl_union_map_is_sv_data *data = user;
 	isl_union_map *umap, *test;
+	isl_size n;
 
 	umap = isl_union_map_copy(data->umap);
 	umap = isl_union_map_intersect_domain(umap,
 						isl_union_set_from_set(set));
 
-	if (isl_union_map_n_map(umap) == 1) {
+	n = isl_union_map_n_map(umap);
+	if (n < 0) {
+		data->sv = isl_bool_error;
+	} else if (n == 1) {
 		data->sv = single_map_is_single_valued(umap);
 		isl_union_map_free(umap);
 	} else {
@@ -2702,8 +2867,12 @@ isl_bool isl_union_map_is_single_valued(__isl_keep isl_union_map *umap)
 	isl_union_map *universe;
 	isl_union_set *domain;
 	struct isl_union_map_is_sv_data data;
+	isl_size n;
 
-	if (isl_union_map_n_map(umap) == 1)
+	n = isl_union_map_n_map(umap);
+	if (n < 0)
+		return isl_bool_error;
+	if (n == 1)
 		return single_map_is_single_valued(umap);
 
 	universe = isl_union_map_universe(isl_union_map_copy(umap));
@@ -2961,13 +3130,13 @@ static isl_bool plain_injective_on_range(__isl_take isl_union_map *umap,
 	int first, int n_range)
 {
 	isl_ctx *ctx;
-	int n;
+	isl_size n;
 	struct isl_fixed_dim_data data = { NULL };
 
 	ctx = isl_union_map_get_ctx(umap);
 
 	n = isl_union_map_n_map(umap);
-	if (!umap)
+	if (n < 0)
 		goto error;
 
 	if (n <= 1) {
@@ -3017,12 +3186,17 @@ static isl_bool plain_injective_on_range(__isl_take isl_union_map *umap,
 static isl_bool plain_injective_on_range_wrap(__isl_keep isl_set *ran,
 	void *user)
 {
+	isl_size dim;
 	isl_union_map *umap = user;
 
+	dim = isl_set_dim(ran, isl_dim_set);
+	if (dim < 0)
+		return isl_bool_error;
+
 	umap = isl_union_map_copy(umap);
 	umap = isl_union_map_intersect_range(umap,
 			isl_union_set_from_set(isl_set_copy(ran)));
-	return plain_injective_on_range(umap, 0, isl_set_dim(ran, isl_dim_set));
+	return plain_injective_on_range(umap, 0, dim);
 }
 
 /* Check if the given union_map is obviously injective.
@@ -3714,19 +3888,9 @@ __isl_give isl_union_map *isl_union_map_project_out(
 	return data.res;
 }
 
-/* Project out all parameters from "umap" by existentially quantifying
- * over them.
- */
-__isl_give isl_union_map *isl_union_map_project_out_all_params(
-	__isl_take isl_union_map *umap)
-{
-	unsigned n;
-
-	if (!umap)
-		return NULL;
-	n = isl_union_map_dim(umap, isl_dim_param);
-	return isl_union_map_project_out(umap, isl_dim_param, 0, n);
-}
+#undef TYPE
+#define TYPE	isl_union_map
+#include "isl_project_out_all_params_templ.c"
 
 /* Turn the "n" dimensions of type "type", starting at "first"
  * into existentially quantified variables.
@@ -3740,6 +3904,16 @@ __isl_give isl_union_set *isl_union_set_project_out(
 	return isl_union_map_project_out(uset, type, first, n);
 }
 
+/* Project out all parameters from "uset" by existentially quantifying
+ * over them.
+ */
+__isl_give isl_union_set *isl_union_set_project_out_all_params(
+	__isl_take isl_union_set *uset)
+{
+	return uset_from_umap(
+		    isl_union_map_project_out_all_params(uset_to_umap(uset)));
+}
+
 /* Internal data structure for isl_union_map_involves_dims.
  * "first" and "n" are the arguments for the isl_map_involves_dims calls.
  */
@@ -3757,9 +3931,7 @@ static isl_bool map_excludes(__isl_keep isl_map *map, void *user)
 
 	involves = isl_map_involves_dims(map,
 					isl_dim_param, data->first, data->n);
-	if (involves < 0)
-		return isl_bool_error;
-	return !involves;
+	return isl_bool_not(involves);
 }
 
 /* Does "umap" involve any of the n parameters starting at first?
@@ -3782,10 +3954,7 @@ isl_bool isl_union_map_involves_dims(__isl_keep isl_union_map *umap,
 
 	excludes = union_map_forall_user(umap, &map_excludes, &data);
 
-	if (excludes < 0)
-		return isl_bool_error;
-
-	return !excludes;
+	return isl_bool_not(excludes);
 }
 
 /* Internal data structure for isl_union_map_reset_range_space.
@@ -3843,12 +4012,12 @@ __isl_give isl_union_map *isl_union_map_reset_range_space(
 static isl_stat check_union_map_space_equal_dim(__isl_keep isl_union_map *umap,
 	__isl_keep isl_space *space)
 {
-	unsigned dim1, dim2;
+	isl_size dim1, dim2;
 
-	if (!umap || !space)
-		return isl_stat_error;
 	dim1 = isl_union_map_dim(umap, isl_dim_param);
 	dim2 = isl_space_dim(space, isl_dim_param);
+	if (dim1 < 0 || dim2 < 0)
+		return isl_stat_error;
 	if (dim1 == dim2)
 		return isl_stat_ok;
 	isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
@@ -4052,19 +4221,20 @@ __isl_give isl_union_map *isl_union_map_lex_gt_at_multi_union_pw_aff(
 __isl_give isl_union_set *isl_union_set_list_union(
 	__isl_take isl_union_set_list *list)
 {
-	int i, n;
+	int i;
+	isl_size n;
 	isl_ctx *ctx;
 	isl_space *space;
 	isl_union_set *res;
 
-	if (!list)
-		return NULL;
+	n = isl_union_set_list_n_union_set(list);
+	if (n < 0)
+		goto error;
 
 	ctx = isl_union_set_list_get_ctx(list);
 	space = isl_space_params_alloc(ctx, 0);
 	res = isl_union_set_empty(space);
 
-	n = isl_union_set_list_n_union_set(list);
 	for (i = 0; i < n; ++i) {
 		isl_union_set *uset_i;
 
@@ -4074,6 +4244,9 @@ __isl_give isl_union_set *isl_union_set_list_union(
 
 	isl_union_set_list_free(list);
 	return res;
+error:
+	isl_union_set_list_free(list);
+	return NULL;
 }
 
 /* Update *hash with the hash value of "map".
@@ -4118,11 +4291,13 @@ uint32_t isl_union_set_get_hash(__isl_keep isl_union_set *uset)
 static isl_stat add_n(__isl_take isl_set *set, void *user)
 {
 	int *n = user;
+	isl_size set_n;
 
-	*n += isl_set_n_basic_set(set);
+	set_n = isl_set_n_basic_set(set);
+	*n += set_n;
 	isl_set_free(set);
 
-	return isl_stat_ok;
+	return set_n < 0 ? isl_stat_error : isl_stat_ok;
 }
 
 /* Return the total number of basic sets in "uset".
@@ -4222,3 +4397,41 @@ __isl_give isl_union_map *isl_union_map_remove_map_if(
 	};
 	return un_op(umap, &control);
 }
+
+/* Does "map" have "space" as range (ignoring parameters)?
+ */
+static isl_bool has_range_space(__isl_keep isl_map *map, void *user)
+{
+	isl_space *space = user;
+
+	return isl_space_has_range_tuples(space, isl_map_peek_space(map));
+}
+
+/* Wrapper around isl_map_bind_range for use as a un_op callback.
+ */
+static __isl_give isl_map *bind_range(__isl_take isl_map *map, void *user)
+{
+	isl_multi_id *tuple = user;
+
+	return isl_map_bind_range(map, isl_multi_id_copy(tuple));
+}
+
+/* Bind the output dimensions of "umap" to parameters with identifiers
+ * specified by "tuple", living in the range space of "umap",
+ * for those maps that have a matching range space.
+ */
+__isl_give isl_union_set *isl_union_map_bind_range(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_id *tuple)
+{
+	struct isl_un_op_control control = {
+		.filter = &has_range_space,
+		.filter_user = isl_multi_id_peek_space(tuple),
+		.fn_map2 = &bind_range,
+		.fn_map2_user = tuple,
+	};
+	isl_union_set *bound;
+
+	bound = uset_from_umap(un_op(umap, &control));
+	isl_multi_id_free(tuple);
+	return bound;
+}

diff  --git a/polly/lib/External/isl/isl_union_map_private.h b/polly/lib/External/isl/isl_union_map_private.h
index c402f3835164..2af6c2bb1ad9 100644
--- a/polly/lib/External/isl/isl_union_map_private.h
+++ b/polly/lib/External/isl/isl_union_map_private.h
@@ -11,6 +11,7 @@ struct isl_union_map {
 };
 
 __isl_keep isl_space *isl_union_map_peek_space(__isl_keep isl_union_map *umap);
+__isl_keep isl_space *isl_union_set_peek_space(__isl_keep isl_union_set *uset);
 isl_bool isl_union_map_is_params(__isl_keep isl_union_map *umap);
 isl_bool isl_union_map_space_has_equal_params(__isl_keep isl_union_map *umap,
 	__isl_keep isl_space *space);

diff  --git a/polly/lib/External/isl/isl_union_multi.c b/polly/lib/External/isl/isl_union_multi.c
index 64834e6f31c9..7a280065d6f1 100644
--- a/polly/lib/External/isl/isl_union_multi.c
+++ b/polly/lib/External/isl/isl_union_multi.c
@@ -13,7 +13,7 @@
  * 78153 Le Chesnay Cedex France
  */
 
-#include <isl_hash_private.h>
+#include <isl/hash.h>
 #include <isl_union_macro.h>
 
 /* A group of expressions defined over the same domain space "domain_space".
@@ -93,13 +93,13 @@ static isl_stat FN(UNION,count_part)(__isl_keep S(UNION,group) *group,
 
 /* Return the number of base expressions in "u".
  */
-int FN(FN(UNION,n),BASE)(__isl_keep UNION *u)
+isl_size FN(FN(UNION,n),BASE)(__isl_keep UNION *u)
 {
 	int n;
 
 	n = 0;
 	if (FN(UNION,foreach_group)(u, &FN(UNION,count_part), &n) < 0)
-		n = -1;
+		return isl_size_error;
 	return n;
 }
 
@@ -160,7 +160,7 @@ static __isl_give S(UNION,group) *FN(UNION,group_alloc)(
 
 /* Is the space of "entry" equal to "space"?
  */
-static int FN(UNION,has_space)(const void *entry, const void *val)
+static isl_bool FN(UNION,has_space)(const void *entry, const void *val)
 {
 	PART *part = (PART *) entry;
 	isl_space *space = (isl_space *) val;
@@ -221,9 +221,10 @@ isl_stat FN(FN(UNION,foreach),BASE)(__isl_keep UNION *u,
 }
 
 /* Is the domain space of the group of expressions at "entry"
- * equal to "space"?
+ * equal to that of "space"?
  */
-static int FN(UNION,group_has_domain_space)(const void *entry, const void *val)
+static isl_bool FN(UNION,group_has_same_domain_space)(const void *entry,
+	const void *val)
 {
 	S(UNION,group) *group = (S(UNION,group) *) entry;
 	isl_space *space = (isl_space *) val;
@@ -246,7 +247,7 @@ static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
 {
 	isl_ctx *ctx;
 	uint32_t hash;
-	struct isl_hash_table_entry *group_entry, *part_entry;
+	struct isl_hash_table_entry *group_entry;
 	S(UNION,group) *group;
 
 	if (!u || !space)
@@ -255,9 +256,9 @@ static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
 	ctx = FN(UNION,get_ctx)(u);
 	hash = isl_space_get_domain_hash(space);
 	group_entry = isl_hash_table_find(ctx, &u->table, hash,
-			    &FN(UNION,group_has_domain_space), space, reserve);
-	if (!group_entry)
-		return reserve ? NULL : isl_hash_table_entry_none;
+			&FN(UNION,group_has_same_domain_space), space, reserve);
+	if (!group_entry || group_entry == isl_hash_table_entry_none)
+		return group_entry;
 	if (reserve && !group_entry->data) {
 		isl_space *domain = isl_space_domain(isl_space_copy(space));
 		group = FN(UNION,group_alloc)(domain, 1);
@@ -270,11 +271,8 @@ static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
 	if (!group)
 		return NULL;
 	hash = isl_space_get_hash(space);
-	part_entry = isl_hash_table_find(ctx, &group->part_table, hash,
+	return isl_hash_table_find(ctx, &group->part_table, hash,
 				&FN(UNION,has_space), space, reserve);
-	if (!reserve && !part_entry)
-		return isl_hash_table_entry_none;
-	return part_entry;
 }
 
 /* Remove "part_entry" from the hash table of "u".
@@ -288,6 +286,7 @@ static __isl_give UNION *FN(UNION,remove_part_entry)(__isl_take UNION *u,
 {
 	isl_ctx *ctx;
 	uint32_t hash;
+	isl_space *space;
 	PART *part;
 	struct isl_hash_table_entry *group_entry;
 	S(UNION,group) *group;
@@ -297,10 +296,13 @@ static __isl_give UNION *FN(UNION,remove_part_entry)(__isl_take UNION *u,
 
 	part = part_entry->data;
 	ctx = FN(UNION,get_ctx)(u);
-	hash = isl_space_get_domain_hash(part->dim);
+	space = FN(PART,peek_space)(part);
+	hash = isl_space_get_domain_hash(space);
 	group_entry = isl_hash_table_find(ctx, &u->table, hash,
-			    &FN(UNION,group_has_domain_space), part->dim, 0);
+			    &FN(UNION,group_has_same_domain_space), space, 0);
 	if (!group_entry)
+		return FN(UNION,free)(u);
+	if (group_entry == isl_hash_table_entry_none)
 		isl_die(ctx, isl_error_internal, "missing group",
 			return FN(UNION,free)(u));
 	group = group_entry->data;
@@ -373,16 +375,20 @@ static isl_stat FN(UNION,check_disjoint_domain_other)(__isl_keep UNION *u,
 {
 	isl_ctx *ctx;
 	uint32_t hash;
+	isl_space *space;
 	struct isl_hash_table_entry *group_entry;
 	S(UNION,group) *group;
 
 	if (!u || !part)
 		return isl_stat_error;
 	ctx = FN(UNION,get_ctx)(u);
-	hash = isl_space_get_domain_hash(part->dim);
+	space = FN(PART,peek_space)(part);
+	hash = isl_space_get_domain_hash(space);
 	group_entry = isl_hash_table_find(ctx, &u->table, hash,
-			    &FN(UNION,group_has_domain_space), part->dim, 0);
+			    &FN(UNION,group_has_same_domain_space), space, 0);
 	if (!group_entry)
+		return isl_stat_error;
+	if (group_entry == isl_hash_table_entry_none)
 		return isl_stat_ok;
 	group = group_entry->data;
 	return isl_hash_table_foreach(ctx, &group->part_table,
@@ -445,21 +451,87 @@ static isl_stat FN(UNION,foreach_inplace)(__isl_keep UNION *u,
 	return FN(UNION,foreach_group)(u, &FN(UNION,group_call_inplace), &data);
 }
 
-/* Does "u" have a single reference?
- * That is, can we change "u" inplace?
+static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
+{
+	S(UNION,group) *group = *entry;
+	FN(UNION,group_free)(group);
+	return isl_stat_ok;
+}
+
+/* Set "single" to true if this group of expressions
+ * contains an expression living in exactly one space.
  */
-static isl_bool FN(UNION,has_single_reference)(__isl_keep UNION *u)
+static isl_stat FN(UNION,group_single_space)(__isl_keep S(UNION,group) *group,
+	void *user)
 {
+	isl_bool *single = user;
+
+	if (!group)
+		return isl_stat_error;
+	*single = isl_bool_ok(group->part_table.n == 1);
+	return isl_stat_ok;
+}
+
+/* Can this union expression be converted to a single base expression?
+ * That is, does it contain a base expression in exactly one space?
+ * In particular, is only one domain space involved and
+ * is only a single expression associated to that domain?
+ */
+isl_bool FN(FN(UNION,isa),BASE)(__isl_take UNION *u)
+{
+	isl_bool single;
+
 	if (!u)
 		return isl_bool_error;
-	return u->ref == 1;
+	if (u->table.n != 1)
+		return isl_bool_false;
+	if (FN(UNION,foreach_group)(u,
+				&FN(UNION,group_single_space), &single) < 0)
+		return isl_bool_error;
+	return single;
 }
 
-static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
+/* Callback for isl_union_*_foreach_inplace call
+ * on a union expression with a single base expression.
+ * Store that base expression in "user".
+ * This callback should only be called once
+ * for any given isl_union_*_foreach_inplace call.
+ */
+static isl_stat FN(UNION,extract_part)(void **entry, void *user)
 {
-	S(UNION,group) *group = *entry;
-	FN(UNION,group_free)(group);
+	PART **part_p = user;
+	PART *part = *entry;
+
+	if (*part_p)
+		isl_die(FN(PART,get_ctx)(part), isl_error_internal,
+			"more than one part", return isl_stat_error);
+	*part_p = FN(PART,copy)(part);
+	if (!*part_p)
+		return isl_stat_error;
 	return isl_stat_ok;
 }
 
+/* Convert the union expression to its single base expression.
+ */
+__isl_give PART *FN(FN(UNION,as),BASE)(__isl_take UNION *u)
+{
+	isl_bool has_single_space;
+	PART *part = NULL;
+
+	has_single_space = FN(FN(UNION,isa),BASE)(u);
+	if (has_single_space < 0)
+		goto error;
+	if (!has_single_space)
+		isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+			"expecting elements in exactly one space",
+			goto error);
+	if (FN(UNION,foreach_inplace)(u, &FN(UNION,extract_part), &part) < 0)
+		part = FN(PART,free)(part);
+	FN(UNION,free)(u);
+	return part;
+error:
+	FN(UNION,free)(u);
+	return NULL;
+}
+
 #include <isl_union_templ.c>

diff  --git a/polly/lib/External/isl/isl_union_single.c b/polly/lib/External/isl/isl_union_single.c
index c9926c8a051b..1ec7c45816bb 100644
--- a/polly/lib/External/isl/isl_union_single.c
+++ b/polly/lib/External/isl/isl_union_single.c
@@ -10,7 +10,7 @@
  * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
  */
 
-#include <isl_hash_private.h>
+#include <isl/hash.h>
 #include <isl_union_macro.h>
 
 /* A union of expressions defined over 
diff erent domain spaces.
@@ -29,9 +29,9 @@ struct UNION {
 
 /* Return the number of base expressions in "u".
  */
-int FN(FN(UNION,n),BASE)(__isl_keep UNION *u)
+isl_size FN(FN(UNION,n),BASE)(__isl_keep UNION *u)
 {
-	return u ? u->table.n : 0;
+	return u ? u->table.n : isl_size_error;
 }
 
 S(UNION,foreach_data)
@@ -65,7 +65,8 @@ isl_stat FN(FN(UNION,foreach),BASE)(__isl_keep UNION *u,
 
 /* Is the domain space of "entry" equal to the domain of "space"?
  */
-static int FN(UNION,has_same_domain_space)(const void *entry, const void *val)
+static isl_bool FN(UNION,has_same_domain_space)(const void *entry,
+	const void *val)
 {
 	PART *part = (PART *)entry;
 	isl_space *space = (isl_space *) val;
@@ -102,8 +103,8 @@ static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
 	hash = isl_space_get_domain_hash(space);
 	entry = isl_hash_table_find(ctx, &u->table, hash,
 			&FN(UNION,has_same_domain_space), space, reserve);
-	if (!entry)
-		return reserve ? NULL : isl_hash_table_entry_none;
+	if (!entry || entry == isl_hash_table_entry_none)
+		return entry;
 	if (reserve && !entry->data)
 		return entry;
 	part = entry->data;
@@ -177,16 +178,6 @@ static isl_stat FN(UNION,foreach_inplace)(__isl_keep UNION *u,
 	return isl_hash_table_foreach(ctx, &u->table, fn, user);
 }
 
-/* Does "u" have a single reference?
- * That is, can we change "u" inplace?
- */
-static isl_bool FN(UNION,has_single_reference)(__isl_keep UNION *u)
-{
-	if (!u)
-		return isl_bool_error;
-	return u->ref == 1;
-}
-
 static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
 {
 	PART *part = *entry;

diff  --git a/polly/lib/External/isl/isl_union_templ.c b/polly/lib/External/isl/isl_union_templ.c
index a687b14c4619..1848fa869790 100644
--- a/polly/lib/External/isl/isl_union_templ.c
+++ b/polly/lib/External/isl/isl_union_templ.c
@@ -10,6 +10,11 @@
  * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
  */
 
+#undef TYPE
+#define TYPE	UNION
+static
+#include "has_single_reference_templ.c"
+
 __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u);
 
 isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u)
@@ -36,14 +41,14 @@ __isl_give isl_space *FN(UNION,get_space)(__isl_keep UNION *u)
 /* Return the number of parameters of "u", where "type"
  * is required to be set to isl_dim_param.
  */
-unsigned FN(UNION,dim)(__isl_keep UNION *u, enum isl_dim_type type)
+isl_size FN(UNION,dim)(__isl_keep UNION *u, enum isl_dim_type type)
 {
 	if (!u)
-		return 0;
+		return isl_size_error;
 
 	if (type != isl_dim_param)
 		isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
-			"can only reference parameters", return 0);
+			"can only reference parameters", return isl_size_error);
 
 	return isl_space_dim(u->space, type);
 }
@@ -60,48 +65,55 @@ int FN(UNION,find_dim_by_name)(__isl_keep UNION *u, enum isl_dim_type type,
 	return isl_space_find_dim_by_name(u->space, type, name);
 }
 
-#ifdef HAS_TYPE
-static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim,
-	enum isl_fold type, int size)
-#else
-static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim, int size)
-#endif
+#include "opt_type.h"
+
+static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *space
+	OPT_TYPE_PARAM, int size)
 {
 	UNION *u;
 
-	dim = isl_space_params(dim);
-	if (!dim)
+	space = isl_space_params(space);
+	if (!space)
 		return NULL;
 
-	u = isl_calloc_type(dim->ctx, UNION);
+	u = isl_calloc_type(space->ctx, UNION);
 	if (!u)
 		goto error;
 
 	u->ref = 1;
-#ifdef HAS_TYPE
-	u->type = type;
-#endif
-	u->space = dim;
-	if (isl_hash_table_init(dim->ctx, &u->table, size) < 0)
+	OPT_SET_TYPE(u->, type);
+	u->space = space;
+	if (isl_hash_table_init(space->ctx, &u->table, size) < 0)
 		return FN(UNION,free)(u);
 
 	return u;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
-#ifdef HAS_TYPE
-__isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
+/* Create an empty/zero union without specifying any parameters.
+ */
+__isl_give UNION *FN(FN(UNION,ZERO),ctx)(isl_ctx *ctx OPT_TYPE_PARAM)
 {
-	return FN(UNION,alloc)(dim, type, 16);
+	isl_space *space;
+
+	space = isl_space_unit(ctx);
+	return FN(FN(UNION,ZERO),space)(space OPT_TYPE_ARG(NO_LOC));
 }
-#else
-__isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim)
+
+__isl_give UNION *FN(FN(UNION,ZERO),space)(__isl_take isl_space *space
+	OPT_TYPE_PARAM)
 {
-	return FN(UNION,alloc)(dim, 16);
+	return FN(UNION,alloc)(space OPT_TYPE_ARG(NO_LOC), 16);
+}
+
+/* This is an alternative name for the function above.
+ */
+__isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *space OPT_TYPE_PARAM)
+{
+	return FN(FN(UNION,ZERO),space)(space OPT_TYPE_ARG(NO_LOC));
 }
-#endif
 
 __isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u)
 {
@@ -128,11 +140,7 @@ __isl_give PART *FN(FN(UNION,extract),BASE)(__isl_keep UNION *u,
 	if (!entry)
 		goto error;
 	if (entry == isl_hash_table_entry_none)
-#ifdef HAS_TYPE
-		return FN(PART,ZERO)(space, u->type);
-#else
-		return FN(PART,ZERO)(space);
-#endif
+		return FN(PART,ZERO)(space OPT_TYPE_ARG(u->));
 	isl_space_free(space);
 	return FN(PART,copy)(entry->data);
 error:
@@ -212,8 +220,7 @@ __isl_give UNION *FN(FN(UNION,add),BASE)(__isl_take UNION *u,
 	return FN(UNION,add_part_generic)(u, part, 1);
 }
 
-#ifdef HAS_TYPE
-/* Allocate a UNION with the same type and the same size as "u" and
+/* Allocate a UNION with the same type (if any) and the same size as "u" and
  * with space "space".
  */
 static __isl_give UNION *FN(UNION,alloc_same_size_on_space)(__isl_keep UNION *u,
@@ -221,25 +228,11 @@ static __isl_give UNION *FN(UNION,alloc_same_size_on_space)(__isl_keep UNION *u,
 {
 	if (!u)
 		goto error;
-	return FN(UNION,alloc)(space, u->type, u->table.n);
-error:
-	isl_space_free(space);
-	return NULL;
-}
-#else
-/* Allocate a UNION with the same size as "u" and with space "space".
- */
-static __isl_give UNION *FN(UNION,alloc_same_size_on_space)(__isl_keep UNION *u,
-	__isl_take isl_space *space)
-{
-	if (!u)
-		goto error;
-	return FN(UNION,alloc)(space, u->table.n);
+	return FN(UNION,alloc)(space OPT_TYPE_ARG(u->), u->table.n);
 error:
 	isl_space_free(space);
 	return NULL;
 }
-#endif
 
 /* Allocate a UNION with the same space, the same type (if any) and
  * the same size as "u".
@@ -249,68 +242,104 @@ static __isl_give UNION *FN(UNION,alloc_same_size)(__isl_keep UNION *u)
 	return FN(UNION,alloc_same_size_on_space)(u, FN(UNION,get_space)(u));
 }
 
+/* Data structure that specifies how isl_union_*_transform
+ * should modify the base expressions in the union expression.
+ *
+ * If "inplace" is set, then the base expression in the input union
+ * are modified in place.  This means that "fn" should not
+ * change the meaning of the union or that the union only
+ * has a single reference.
+ * If "space" is not NULL, then a new union is created in this space.
+ * If "filter" is not NULL, then only the base expressions that satisfy "filter"
+ * are taken into account.
+ * "fn" is applied to each entry in the input.
+ * "fn_user" is passed as the second argument to "fn".
+ */
+S(UNION,transform_control) {
+	int inplace;
+	isl_space *space;
+	isl_bool (*filter)(__isl_keep PART *part);
+	__isl_give PART *(*fn)(__isl_take PART *part, void *user);
+	void *fn_user;
+};
+
 /* Internal data structure for isl_union_*_transform_space.
- * "fn' is applied to each entry in the input.
- * "res" collects the results.
+ * "control" specifies how the base expressions should be modified.
+ * "res" collects the results (if control->inplace is not set).
  */
 S(UNION,transform_data)
 {
-	__isl_give PART *(*fn)(__isl_take PART *part, void *user);
-	void *user;
-
+	S(UNION,transform_control) *control;
 	UNION *res;
 };
 
-/* Apply data->fn to "part" and add the result to data->res.
+/* Apply control->fn to "part" and add the result to data->res or
+ * place it back into the input union if control->inplace is set.
  */
-static isl_stat FN(UNION,transform_entry)(__isl_take PART *part, void *user)
+static isl_stat FN(UNION,transform_entry)(void **entry, void *user)
 {
 	S(UNION,transform_data) *data = (S(UNION,transform_data) *)user;
+	PART *part = *entry;
 
-	part = data->fn(part, data->user);
-	data->res = FN(FN(UNION,add),BASE)(data->res, part);
-	if (!data->res)
+	if (data->control->filter) {
+		isl_bool handle;
+
+		handle = data->control->filter(part);
+		if (handle < 0)
+			return isl_stat_error;
+		if (!handle)
+			return isl_stat_ok;
+	}
+
+	if (!data->control->inplace)
+		part = FN(PART,copy)(part);
+	part = data->control->fn(part, data->control->fn_user);
+	if (data->control->inplace)
+		*entry = part;
+	else
+		data->res = FN(FN(UNION,add),BASE)(data->res, part);
+	if (!part || !data->res)
 		return isl_stat_error;
 
 	return isl_stat_ok;
 }
 
-/* Return a UNION living in "space" that is obtained by applying "fn"
- * to each of the entries in "u".
+/* Return a UNION that is obtained by modifying "u" according to "control".
  */
-static __isl_give UNION *FN(UNION,transform_space)(__isl_take UNION *u,
-	isl_space *space,
-	__isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
+static __isl_give UNION *FN(UNION,transform)(__isl_take UNION *u,
+	S(UNION,transform_control) *control)
 {
-	S(UNION,transform_data) data = { fn, user };
+	S(UNION,transform_data) data = { control };
+	isl_space *space;
 
-	data.res = FN(UNION,alloc_same_size_on_space)(u, space);
-	if (FN(FN(UNION,foreach),BASE)(u,
-					&FN(UNION,transform_entry), &data) < 0)
+	if (control->inplace) {
+		data.res = u;
+	} else {
+		if (control->space)
+			space = isl_space_copy(control->space);
+		else
+			space = FN(UNION,get_space)(u);
+		data.res = FN(UNION,alloc_same_size_on_space)(u, space);
+	}
+	if (FN(UNION,foreach_inplace)(u, &FN(UNION,transform_entry), &data) < 0)
 		data.res = FN(UNION,free)(data.res);
-	FN(UNION,free)(u);
+	if (!control->inplace)
+		FN(UNION,free)(u);
 	return data.res;
 }
 
-/* Return a UNION that lives in the same space as "u" and that is obtained
- * by applying "fn" to each of the entries in "u".
- */
-static __isl_give UNION *FN(UNION,transform)(__isl_take UNION *u,
-	__isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
-{
-	return FN(UNION,transform_space)(u, FN(UNION,get_space)(u), fn, user);
-}
-
-/* Apply data->fn to *part and store the result back into *part.
+/* Return a UNION living in "space" that is otherwise obtained by modifying "u"
+ * according to "control".
  */
-static isl_stat FN(UNION,transform_inplace_entry)(void **part, void *user)
+static __isl_give UNION *FN(UNION,transform_space)(__isl_take UNION *u,
+	__isl_take isl_space *space, S(UNION,transform_control) *control)
 {
-	S(UNION,transform_data) *data = (S(UNION,transform_data) *) user;
-
-	*part = data->fn(*part, data->user);
-	if (!*part)
-		return isl_stat_error;
-	return isl_stat_ok;
+	if (!space)
+		return FN(UNION,free)(u);
+	control->space = space;
+	u = FN(UNION,transform)(u, control);
+	isl_space_free(space);
+	return u;
 }
 
 /* Update "u" by applying "fn" to each entry.
@@ -323,19 +352,15 @@ static isl_stat FN(UNION,transform_inplace_entry)(void **part, void *user)
 static __isl_give UNION *FN(UNION,transform_inplace)(__isl_take UNION *u,
 	__isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
 {
+	S(UNION,transform_control) control = { .fn = fn, .fn_user = user };
 	isl_bool single_ref;
 
 	single_ref = FN(UNION,has_single_reference)(u);
 	if (single_ref < 0)
 		return FN(UNION,free)(u);
-	if (single_ref) {
-		S(UNION,transform_data) data = { fn, user };
-		if (FN(UNION,foreach_inplace)(u,
-				&FN(UNION,transform_inplace_entry), &data) < 0)
-			return FN(UNION,free)(u);
-		return u;
-	}
-	return FN(UNION,transform)(u, fn, user);
+	if (single_ref)
+		control.inplace = 1;
+	return FN(UNION,transform)(u, &control);
 }
 
 /* An isl_union_*_transform callback for use in isl_union_*_dup
@@ -348,8 +373,10 @@ static __isl_give PART *FN(UNION,copy_part)(__isl_take PART *part, void *user)
 
 __isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u)
 {
+	S(UNION,transform_control) control = { .fn = &FN(UNION,copy_part) };
+
 	u = FN(UNION,copy)(u);
-	return FN(UNION,transform)(u, &FN(UNION,copy_part), NULL);
+	return FN(UNION,transform)(u, &control);
 }
 
 __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
@@ -393,13 +420,17 @@ static __isl_give PART *FN(UNION,align_entry)(__isl_take PART *part, void *user)
 static __isl_give UNION *FN(UNION,realign_domain)(__isl_take UNION *u,
 	__isl_take isl_reordering *r)
 {
+	S(UNION,transform_control) control = {
+		.fn = &FN(UNION,align_entry),
+		.fn_user = r,
+	};
 	isl_space *space;
 
 	if (!u || !r)
 		goto error;
 
 	space = isl_reordering_get_space(r);
-	u = FN(UNION,transform_space)(u, space, &FN(UNION,align_entry), r);
+	u = FN(UNION,transform_space)(u, space, &control);
 	isl_reordering_free(r);
 	return u;
 error:
@@ -484,20 +515,18 @@ static __isl_give UNION *FN(UNION,union_add_)(__isl_take UNION *u1,
 
 __isl_give UNION *FN(FN(UNION,from),BASE)(__isl_take PART *part)
 {
-	isl_space *dim;
+	isl_space *space;
 	UNION *u;
 
 	if (!part)
 		return NULL;
 
-	dim = FN(PART,get_space)(part);
-	dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
-	dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
-#ifdef HAS_TYPE
-	u = FN(UNION,ZERO)(dim, part->type);
-#else
-	u = FN(UNION,ZERO)(dim);
-#endif
+	space = FN(PART,get_space)(part);
+	space = isl_space_drop_dims(space, isl_dim_in, 0,
+					isl_space_dim(space, isl_dim_in));
+	space = isl_space_drop_dims(space, isl_dim_out, 0,
+					isl_space_dim(space, isl_dim_out));
+	u = FN(UNION,ZERO)(space OPT_TYPE_ARG(part->));
 	u = FN(FN(UNION,add),BASE)(u, part);
 
 	return u;
@@ -631,6 +660,10 @@ static __isl_give UNION *FN(UNION,any_set_op)(__isl_take UNION *u,
 	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
 {
 	S(UNION,any_set_data) data = { NULL, fn };
+	S(UNION,transform_control) control = {
+		.fn = &FN(UNION,any_set_entry),
+		.fn_user = &data,
+	};
 
 	u = FN(UNION,align_params)(u, isl_set_get_space(set));
 	set = isl_set_align_params(set, FN(UNION,get_space)(u));
@@ -639,7 +672,7 @@ static __isl_give UNION *FN(UNION,any_set_op)(__isl_take UNION *u,
 		goto error;
 
 	data.set = set;
-	u = FN(UNION,transform)(u, &FN(UNION,any_set_entry), &data);
+	u = FN(UNION,transform)(u, &control);
 	isl_set_free(set);
 	return u;
 error:
@@ -665,18 +698,37 @@ __isl_give UNION *FN(UNION,gist_params)(__isl_take UNION *u,
 	return FN(UNION,any_set_op)(u, set, &FN(PW,gist_params));
 }
 
+/* Data structure that specifies how isl_union_*_match_domain_op
+ * should combine its arguments.
+ *
+ * If "filter" is not NULL, then only parts that pass the given
+ * filter are considered for matching.
+ * "fn" is applied to each part in the union and each corresponding
+ * set in the union set, i.e., such that the set lives in the same space
+ * as the domain of the part.
+ * If "match_space" is not NULL, then the set extracted from the union set
+ * does not live in the same space as the domain of the part,
+ * but rather in the space that results from calling "match_space"
+ * on this domain space.
+ */
+S(UNION,match_domain_control) {
+	isl_bool (*filter)(__isl_keep PART *part);
+	__isl_give isl_space *(*match_space)(__isl_take isl_space *space);
+	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
+};
+
 S(UNION,match_domain_data) {
 	isl_union_set *uset;
 	UNION *res;
-	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
+	S(UNION,match_domain_control) *control;
 };
 
-static int FN(UNION,set_has_dim)(const void *entry, const void *val)
+static isl_bool FN(UNION,set_has_space)(const void *entry, const void *val)
 {
 	isl_set *set = (isl_set *)entry;
-	isl_space *dim = (isl_space *)val;
+	isl_space *space = (isl_space *)val;
 
-	return isl_space_is_equal(set->dim, dim);
+	return isl_space_is_equal(set->dim, space);
 }
 
 /* Find the set in data->uset that lives in the same space as the domain
@@ -688,19 +740,31 @@ static isl_stat FN(UNION,match_domain_entry)(__isl_take PART *part, void *user)
 	S(UNION,match_domain_data) *data = user;
 	uint32_t hash;
 	struct isl_hash_table_entry *entry2;
-	isl_space *space;
+	isl_space *space, *uset_space;
+
+	if (data->control->filter) {
+		isl_bool pass = data->control->filter(part);
+		if (pass < 0 || !pass) {
+			FN(PART,free)(part);
+			return pass < 0 ? isl_stat_error : isl_stat_ok;
+		}
+	}
 
+	uset_space = isl_union_set_peek_space(data->uset);
 	space = FN(PART,get_domain_space)(part);
+	if (data->control->match_space)
+		space = data->control->match_space(space);
+	space = isl_space_replace_params(space, uset_space);
 	hash = isl_space_get_hash(space);
 	entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
-				     hash, &FN(UNION,set_has_dim), space, 0);
+				     hash, &FN(UNION,set_has_space), space, 0);
 	isl_space_free(space);
-	if (!entry2) {
+	if (!entry2 || entry2 == isl_hash_table_entry_none) {
 		FN(PART,free)(part);
-		return isl_stat_ok;
+		return isl_stat_non_null(entry2);
 	}
 
-	part = data->fn(part, isl_set_copy(entry2->data));
+	part = data->control->fn(part, isl_set_copy(entry2->data));
 
 	data->res = FN(FN(UNION,add),BASE)(data->res, part);
 	if (!data->res)
@@ -709,18 +773,13 @@ static isl_stat FN(UNION,match_domain_entry)(__isl_take PART *part, void *user)
 	return isl_stat_ok;
 }
 
-/* Apply fn to each pair of PW in u and set in uset such that
- * the set lives in the same space as the domain of PW
+/* Combine "u" and "uset" according to "control"
  * and collect the results.
  */
 static __isl_give UNION *FN(UNION,match_domain_op)(__isl_take UNION *u,
-	__isl_take isl_union_set *uset,
-	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
+	__isl_take isl_union_set *uset, S(UNION,match_domain_control) *control)
 {
-	S(UNION,match_domain_data) data = { NULL, NULL, fn };
-
-	u = FN(UNION,align_params)(u, isl_union_set_get_space(uset));
-	uset = isl_union_set_align_params(uset, FN(UNION,get_space)(u));
+	S(UNION,match_domain_data) data = { NULL, NULL, control };
 
 	if (!u || !uset)
 		goto error;
@@ -748,10 +807,51 @@ static __isl_give UNION *FN(UNION,match_domain_op)(__isl_take UNION *u,
 __isl_give UNION *FN(UNION,intersect_domain)(__isl_take UNION *u,
 	__isl_take isl_union_set *uset)
 {
+	S(UNION,match_domain_control) control = {
+		.fn = &FN(PW,intersect_domain),
+	};
+
 	if (isl_union_set_is_params(uset))
 		return FN(UNION,intersect_params)(u,
 						isl_set_from_union_set(uset));
-	return FN(UNION,match_domain_op)(u, uset, &FN(PW,intersect_domain));
+	return FN(UNION,match_domain_op)(u, uset, &control);
+}
+
+/* Is the domain of "pw" a wrapped relation?
+ */
+static isl_bool FN(PW,domain_is_wrapping)(__isl_keep PW *pw)
+{
+	return isl_space_domain_is_wrapping(FN(PW,peek_space)(pw));
+}
+
+/* Intersect the domain of the wrapped relation inside the domain of "u"
+ * with "uset".
+ */
+__isl_give UNION *FN(UNION,intersect_domain_wrapped_domain)(__isl_take UNION *u,
+	__isl_take isl_union_set *uset)
+{
+	S(UNION,match_domain_control) control = {
+		.filter = &FN(PART,domain_is_wrapping),
+		.match_space = &isl_space_factor_domain,
+		.fn = &FN(PW,intersect_domain_wrapped_domain),
+	};
+
+	return FN(UNION,match_domain_op)(u, uset, &control);
+}
+
+/* Intersect the range of the wrapped relation inside the domain of "u"
+ * with "uset".
+ */
+__isl_give UNION *FN(UNION,intersect_domain_wrapped_range)(__isl_take UNION *u,
+	__isl_take isl_union_set *uset)
+{
+	S(UNION,match_domain_control) control = {
+		.filter = &FN(PART,domain_is_wrapping),
+		.match_space = &isl_space_factor_range,
+		.fn = &FN(PW,intersect_domain_wrapped_range),
+	};
+
+	return FN(UNION,match_domain_op)(u, uset, &control);
 }
 
 /* Take the set (which may be empty) in data->uset that lives
@@ -770,12 +870,17 @@ static __isl_give PART *FN(UNION,subtract_domain_entry)(__isl_take PART *part,
 	return FN(PART,subtract_domain)(part, set);
 }
 
-/* Subtract "uset' from the domain of "u".
+/* Subtract "uset" from the domain of "u".
  */
 __isl_give UNION *FN(UNION,subtract_domain)(__isl_take UNION *u,
 	__isl_take isl_union_set *uset)
 {
-	u = FN(UNION,transform)(u, &FN(UNION,subtract_domain_entry), uset);
+	S(UNION,transform_control) control = {
+		.fn = &FN(UNION,subtract_domain_entry),
+		.fn_user = uset,
+	};
+
+	u = FN(UNION,transform)(u, &control);
 	isl_union_set_free(uset);
 	return u;
 }
@@ -783,9 +888,13 @@ __isl_give UNION *FN(UNION,subtract_domain)(__isl_take UNION *u,
 __isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
 	__isl_take isl_union_set *uset)
 {
+	S(UNION,match_domain_control) control = {
+		.fn = &FN(PW,gist),
+	};
+
 	if (isl_union_set_is_params(uset))
 		return FN(UNION,gist_params)(u, isl_set_from_union_set(uset));
-	return FN(UNION,match_domain_op)(u, uset, &FN(PW,gist));
+	return FN(UNION,match_domain_op)(u, uset, &control);
 }
 
 /* Coalesce an entry in a UNION.  Coalescing is performed in-place.
@@ -890,11 +999,7 @@ __isl_give UNION *FN(UNION,scale_val)(__isl_take UNION *u,
 	if (DEFAULT_IS_ZERO && u && isl_val_is_zero(v)) {
 		UNION *zero;
 		isl_space *space = FN(UNION,get_space)(u);
-#ifdef HAS_TYPE
-		zero = FN(UNION,ZERO)(space, u->type);
-#else
-		zero = FN(UNION,ZERO)(space);
-#endif
+		zero = FN(UNION,ZERO)(space OPT_TYPE_ARG(u->));
 		FN(UNION,free)(u);
 		isl_val_free(v);
 		return zero;
@@ -988,7 +1093,7 @@ static isl_stat FN(UNION,plain_is_equal_entry)(void **entry, void *user)
 isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
 {
 	S(UNION,plain_is_equal_data) data = { NULL, isl_bool_true };
-	int n1, n2;
+	isl_size n1, n2;
 
 	if (!u1 || !u2)
 		return isl_bool_error;
@@ -1086,6 +1191,10 @@ __isl_give UNION *FN(UNION,drop_dims)( __isl_take UNION *u,
 {
 	isl_space *space;
 	S(UNION,drop_dims_data) data = { type, first, n };
+	S(UNION,transform_control) control = {
+		.fn = &FN(UNION,drop_dims_entry),
+		.fn_user = &data,
+	};
 
 	if (!u)
 		return NULL;
@@ -1097,8 +1206,7 @@ __isl_give UNION *FN(UNION,drop_dims)( __isl_take UNION *u,
 
 	space = FN(UNION,get_space)(u);
 	space = isl_space_drop_dims(space, type, first, n);
-	return FN(UNION,transform_space)(u, space, &FN(UNION,drop_dims_entry),
-					&data);
+	return FN(UNION,transform_space)(u, space, &control);
 }
 
 /* Internal data structure for isl_union_*_set_dim_name.
@@ -1128,6 +1236,10 @@ __isl_give UNION *FN(UNION,set_dim_name)(__isl_take UNION *u,
 	enum isl_dim_type type, unsigned pos, const char *s)
 {
 	S(UNION,set_dim_name_data) data = { pos, s };
+	S(UNION,transform_control) control = {
+		.fn = &FN(UNION,set_dim_name_entry),
+		.fn_user = &data,
+	};
 	isl_space *space;
 
 	if (!u)
@@ -1140,8 +1252,7 @@ __isl_give UNION *FN(UNION,set_dim_name)(__isl_take UNION *u,
 
 	space = FN(UNION,get_space)(u);
 	space = isl_space_set_dim_name(space, type, pos, s);
-	return FN(UNION,transform_space)(u, space,
-					&FN(UNION,set_dim_name_entry), &data);
+	return FN(UNION,transform_space)(u, space, &control);
 }
 
 /* Reset the user pointer on all identifiers of parameters and tuples
@@ -1158,12 +1269,14 @@ static __isl_give PART *FN(UNION,reset_user_entry)(__isl_take PART *part,
  */
 __isl_give UNION *FN(UNION,reset_user)(__isl_take UNION *u)
 {
+	S(UNION,transform_control) control = {
+		.fn = &FN(UNION,reset_user_entry),
+	};
 	isl_space *space;
 
 	space = FN(UNION,get_space)(u);
 	space = isl_space_reset_user(space);
-	return FN(UNION,transform_space)(u, space, &FN(UNION,reset_user_entry),
-					NULL);
+	return FN(UNION,transform_space)(u, space, &control);
 }
 
 /* Add the base expression held by "entry" to "list".
@@ -1187,7 +1300,7 @@ static isl_stat FN(UNION,add_to_list)(void **entry, void *user)
  */
 __isl_give LIST(PART) *FN(FN(UNION,get),LIST(BASE))(__isl_keep UNION *u)
 {
-	int n;
+	isl_size n;
 	LIST(PART) *list;
 
 	if (!u)

diff  --git a/polly/lib/External/isl/isl_val.c b/polly/lib/External/isl/isl_val.c
index 06e2874c729a..f17dd6fb3b2e 100644
--- a/polly/lib/External/isl/isl_val.c
+++ b/polly/lib/External/isl/isl_val.c
@@ -11,8 +11,8 @@
 #include <isl_ctx_private.h>
 #include <isl_val_private.h>
 
-#undef BASE
-#define BASE val
+#undef EL_BASE
+#define EL_BASE val
 
 #include <isl_list_templ.c>
 
@@ -969,7 +969,7 @@ isl_bool isl_val_is_divisible_by(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 		isl_die(isl_val_get_ctx(v1), isl_error_invalid,
 			"expecting two integers", return isl_bool_error);
 
-	return isl_int_is_divisible_by(v1->n, v2->n);
+	return isl_bool_ok(isl_int_is_divisible_by(v1->n, v2->n));
 }
 
 /* Given two integer values "v1" and "v2", return the residue of "v1"
@@ -1142,7 +1142,7 @@ isl_bool isl_val_is_int(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_one(v->d);
+	return isl_bool_ok(isl_int_is_one(v->d));
 }
 
 /* Does "v" represent a rational value?
@@ -1152,7 +1152,7 @@ isl_bool isl_val_is_rat(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return !isl_int_is_zero(v->d);
+	return isl_bool_ok(!isl_int_is_zero(v->d));
 }
 
 /* Does "v" represent NaN?
@@ -1162,7 +1162,7 @@ isl_bool isl_val_is_nan(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_zero(v->n) && isl_int_is_zero(v->d);
+	return isl_bool_ok(isl_int_is_zero(v->n) && isl_int_is_zero(v->d));
 }
 
 /* Does "v" represent +infinity?
@@ -1172,7 +1172,7 @@ isl_bool isl_val_is_infty(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_pos(v->n) && isl_int_is_zero(v->d);
+	return isl_bool_ok(isl_int_is_pos(v->n) && isl_int_is_zero(v->d));
 }
 
 /* Does "v" represent -infinity?
@@ -1182,7 +1182,7 @@ isl_bool isl_val_is_neginfty(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_neg(v->n) && isl_int_is_zero(v->d);
+	return isl_bool_ok(isl_int_is_neg(v->n) && isl_int_is_zero(v->d));
 }
 
 /* Does "v" represent the integer zero?
@@ -1192,7 +1192,7 @@ isl_bool isl_val_is_zero(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_zero(v->n) && !isl_int_is_zero(v->d);
+	return isl_bool_ok(isl_int_is_zero(v->n) && !isl_int_is_zero(v->d));
 }
 
 /* Does "v" represent the integer one?
@@ -1205,7 +1205,7 @@ isl_bool isl_val_is_one(__isl_keep isl_val *v)
 	if (isl_val_is_nan(v))
 		return isl_bool_false;
 
-	return isl_int_eq(v->n, v->d);
+	return isl_bool_ok(isl_int_eq(v->n, v->d));
 }
 
 /* Does "v" represent the integer negative one?
@@ -1215,7 +1215,7 @@ isl_bool isl_val_is_negone(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_neg(v->n) && isl_int_abs_eq(v->n, v->d);
+	return isl_bool_ok(isl_int_is_neg(v->n) && isl_int_abs_eq(v->n, v->d));
 }
 
 /* Is "v" (strictly) positive?
@@ -1225,7 +1225,7 @@ isl_bool isl_val_is_pos(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_pos(v->n);
+	return isl_bool_ok(isl_int_is_pos(v->n));
 }
 
 /* Is "v" (strictly) negative?
@@ -1235,7 +1235,7 @@ isl_bool isl_val_is_neg(__isl_keep isl_val *v)
 	if (!v)
 		return isl_bool_error;
 
-	return isl_int_is_neg(v->n);
+	return isl_bool_ok(isl_int_is_neg(v->n));
 }
 
 /* Is "v" non-negative?
@@ -1248,7 +1248,7 @@ isl_bool isl_val_is_nonneg(__isl_keep isl_val *v)
 	if (isl_val_is_nan(v))
 		return isl_bool_false;
 
-	return isl_int_is_nonneg(v->n);
+	return isl_bool_ok(isl_int_is_nonneg(v->n));
 }
 
 /* Is "v" non-positive?
@@ -1261,7 +1261,7 @@ isl_bool isl_val_is_nonpos(__isl_keep isl_val *v)
 	if (isl_val_is_nan(v))
 		return isl_bool_false;
 
-	return isl_int_is_nonpos(v->n);
+	return isl_bool_ok(isl_int_is_nonpos(v->n));
 }
 
 /* Return the sign of "v".
@@ -1289,7 +1289,7 @@ isl_bool isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 	if (!v1 || !v2)
 		return isl_bool_error;
 	if (isl_val_is_int(v1) && isl_val_is_int(v2))
-		return isl_int_lt(v1->n, v2->n);
+		return isl_bool_ok(isl_int_lt(v1->n, v2->n));
 	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
 		return isl_bool_false;
 	if (isl_val_eq(v1, v2))
@@ -1306,7 +1306,7 @@ isl_bool isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 	isl_int_init(t);
 	isl_int_mul(t, v1->n, v2->d);
 	isl_int_submul(t, v2->n, v1->d);
-	lt = isl_int_is_neg(t);
+	lt = isl_bool_ok(isl_int_is_neg(t));
 	isl_int_clear(t);
 
 	return lt;
@@ -1329,7 +1329,7 @@ isl_bool isl_val_gt_si(__isl_keep isl_val *v, long i)
 	if (!v)
 		return isl_bool_error;
 	if (isl_val_is_int(v))
-		return isl_int_cmp_si(v->n, i) > 0;
+		return isl_bool_ok(isl_int_cmp_si(v->n, i) > 0);
 	if (isl_val_is_nan(v))
 		return isl_bool_false;
 	if (isl_val_is_infty(v))
@@ -1338,7 +1338,7 @@ isl_bool isl_val_gt_si(__isl_keep isl_val *v, long i)
 		return isl_bool_false;
 
 	vi = isl_val_int_from_si(isl_val_get_ctx(v), i);
-	res = isl_val_gt(v, vi);
+	res = isl_bool_ok(isl_val_gt(v, vi));
 	isl_val_free(vi);
 
 	return res;
@@ -1354,7 +1354,7 @@ isl_bool isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 	if (!v1 || !v2)
 		return isl_bool_error;
 	if (isl_val_is_int(v1) && isl_val_is_int(v2))
-		return isl_int_le(v1->n, v2->n);
+		return isl_bool_ok(isl_int_le(v1->n, v2->n));
 	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
 		return isl_bool_false;
 	if (isl_val_eq(v1, v2))
@@ -1371,7 +1371,7 @@ isl_bool isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 	isl_int_init(t);
 	isl_int_mul(t, v1->n, v2->d);
 	isl_int_submul(t, v2->n, v1->d);
-	le = isl_int_is_nonpos(t);
+	le = isl_bool_ok(isl_int_is_nonpos(t));
 	isl_int_clear(t);
 
 	return le;
@@ -1424,7 +1424,8 @@ isl_bool isl_val_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
 		return isl_bool_false;
 
-	return isl_int_eq(v1->n, v2->n) && isl_int_eq(v1->d, v2->d);
+	return isl_bool_ok(isl_int_eq(v1->n, v2->n) &&
+			   isl_int_eq(v1->d, v2->d));
 }
 
 /* Is "v1" equal to "v2" in absolute value?
@@ -1436,7 +1437,8 @@ isl_bool isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
 		return isl_bool_false;
 
-	return isl_int_abs_eq(v1->n, v2->n) && isl_int_eq(v1->d, v2->d);
+	return isl_bool_ok(isl_int_abs_eq(v1->n, v2->n) &&
+			   isl_int_eq(v1->d, v2->d));
 }
 
 /* Is "v1" 
diff erent from "v2"?
@@ -1448,7 +1450,8 @@ isl_bool isl_val_ne(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
 	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
 		return isl_bool_false;
 
-	return isl_int_ne(v1->n, v2->n) || isl_int_ne(v1->d, v2->d);
+	return isl_bool_ok(isl_int_ne(v1->n, v2->n) ||
+			   isl_int_ne(v1->d, v2->d));
 }
 
 /* Print a textual representation of "v" onto "p".
@@ -1487,7 +1490,8 @@ __isl_give isl_printer *isl_printer_print_val(__isl_take isl_printer *p,
  * This is a private copy of isl_val_eq for use in the generic
  * isl_multi_*_plain_is_equal instantiated for isl_val.
  */
-int isl_val_plain_is_equal(__isl_keep isl_val *val1, __isl_keep isl_val *val2)
+isl_bool isl_val_plain_is_equal(__isl_keep isl_val *val1,
+	__isl_keep isl_val *val2)
 {
 	return isl_val_eq(val1, val2);
 }
@@ -1522,19 +1526,6 @@ __isl_give isl_val *isl_val_insert_dims(__isl_take isl_val *v,
 	return v;
 }
 
-/* Drop the "n" first dimensions of type "type" at position "first".
- *
- * This function is only meant to be used in the generic isl_multi_*
- * functions which have to deal with base objects that have an associated
- * space.  Since an isl_val does not have an associated space, this function
- * does not do anything.
- */
-__isl_give isl_val *isl_val_drop_dims(__isl_take isl_val *v,
-	enum isl_dim_type type, unsigned first, unsigned n)
-{
-	return v;
-}
-
 /* Change the name of the dimension of type "type" at position "pos" to "s".
  *
  * This function is only meant to be used in the generic isl_multi_*
@@ -1548,73 +1539,6 @@ __isl_give isl_val *isl_val_set_dim_name(__isl_take isl_val *v,
 	return v;
 }
 
-/* Return the space of "v".
- *
- * This function is only meant to be used in the generic isl_multi_*
- * functions which have to deal with base objects that have an associated
- * space.  The conditions surrounding the call to this function make sure
- * that this function will never actually get called.  We return a valid
- * space anyway, just in case.
- */
-__isl_give isl_space *isl_val_get_space(__isl_keep isl_val *v)
-{
-	if (!v)
-		return NULL;
-
-	return isl_space_params_alloc(isl_val_get_ctx(v), 0);
-}
-
-/* Reset the domain space of "v" to "space".
- *
- * This function is only meant to be used in the generic isl_multi_*
- * functions which have to deal with base objects that have an associated
- * space.  Since an isl_val does not have an associated space, this function
- * does not do anything, apart from error handling and cleaning up memory.
- */
-__isl_give isl_val *isl_val_reset_domain_space(__isl_take isl_val *v,
-	__isl_take isl_space *space)
-{
-	if (!space)
-		return isl_val_free(v);
-	isl_space_free(space);
-	return v;
-}
-
-/* Align the parameters of "v" to those of "space".
- *
- * This function is only meant to be used in the generic isl_multi_*
- * functions which have to deal with base objects that have an associated
- * space.  Since an isl_val does not have an associated space, this function
- * does not do anything, apart from error handling and cleaning up memory.
- * Note that the conditions surrounding the call to this function make sure
- * that this function will never actually get called.
- */
-__isl_give isl_val *isl_val_align_params(__isl_take isl_val *v,
-	__isl_take isl_space *space)
-{
-	if (!space)
-		return isl_val_free(v);
-	isl_space_free(space);
-	return v;
-}
-
-/* Reorder the dimensions of the domain of "v" according
- * to the given reordering.
- *
- * This function is only meant to be used in the generic isl_multi_*
- * functions which have to deal with base objects that have an associated
- * space.  Since an isl_val does not have an associated space, this function
- * does not do anything, apart from error handling and cleaning up memory.
- */
-__isl_give isl_val *isl_val_realign_domain(__isl_take isl_val *v,
-	__isl_take isl_reordering *r)
-{
-	if (!r)
-		return isl_val_free(v);
-	isl_reordering_free(r);
-	return v;
-}
-
 /* Return an isl_val that is zero on "ls".
  *
  * This function is only meant to be used in the generic isl_multi_*
@@ -1633,48 +1557,29 @@ __isl_give isl_val *isl_val_zero_on_domain(__isl_take isl_local_space *ls)
 	return isl_val_zero(ctx);
 }
 
-/* Do the parameters of "v" match those of "space"?
- *
- * This function is only meant to be used in the generic isl_multi_*
- * functions which have to deal with base objects that have an associated
- * space.  Since an isl_val does not have an associated space, this function
- * simply returns true, except if "v" or "space" are NULL.
- */
-isl_bool isl_val_matching_params(__isl_keep isl_val *v,
-	__isl_keep isl_space *space)
-{
-	if (!v || !space)
-		return isl_bool_error;
-	return isl_bool_true;
-}
-
-/* Check that the domain space of "v" matches "space".
- *
- * This function is only meant to be used in the generic isl_multi_*
- * functions which have to deal with base objects that have an associated
- * space.  Since an isl_val does not have an associated space, this function
- * simply returns 0, except if "v" or "space" are NULL.
- */
-isl_stat isl_val_check_match_domain_space(__isl_keep isl_val *v,
-	__isl_keep isl_space *space)
-{
-	if (!v || !space)
-		return isl_stat_error;
-	return isl_stat_ok;
-}
-
 #define isl_val_involves_nan isl_val_is_nan
 
 #undef BASE
 #define BASE val
 
-#define NO_DOMAIN
-#define NO_IDENTITY
-#define NO_FROM_BASE
-#define NO_MOVE_DIMS
+#include <isl_multi_no_domain_templ.c>
 #include <isl_multi_no_explicit_domain.c>
 #include <isl_multi_templ.c>
+#include <isl_multi_arith_templ.c>
+#include <isl_multi_dim_id_templ.c>
 #include <isl_multi_dims.c>
+#include <isl_multi_nan_templ.c>
+#include <isl_multi_product_templ.c>
+#include <isl_multi_splice_templ.c>
+#include <isl_multi_tuple_id_templ.c>
+#include <isl_multi_zero_templ.c>
+
+/* Does "mv" consist of only zeros?
+ */
+isl_bool isl_multi_val_is_zero(__isl_keep isl_multi_val *mv)
+{
+	return isl_multi_val_every(mv, &isl_val_is_zero);
+}
 
 /* Apply "fn" to each of the elements of "mv" with as second argument "v".
  */

diff  --git a/polly/lib/External/isl/isl_val_gmp.c b/polly/lib/External/isl/isl_val_gmp.c
index 42e8d4446718..cd74709a0fcd 100644
--- a/polly/lib/External/isl/isl_val_gmp.c
+++ b/polly/lib/External/isl/isl_val_gmp.c
@@ -86,14 +86,14 @@ __isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
 /* Return the number of chunks of size "size" required to
  * store the absolute value of the numerator of "v".
  */
-size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
+isl_size isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
 {
 	if (!v)
-		return 0;
+		return isl_size_error;
 
 	if (!isl_val_is_rat(v))
 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational value", return 0);
+			"expecting rational value", return isl_size_error);
 
 	size *= 8;
 	return (mpz_sizeinbase(v->n, 2) + size - 1) / size;
@@ -110,19 +110,19 @@ size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
  * return one, while mpz_export will not fill in any chunks.  We therefore
  * do it ourselves.
  */
-int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
+isl_stat isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
 	void *chunks)
 {
 	if (!v || !chunks)
-		return -1;
+		return isl_stat_error;
 
 	if (!isl_val_is_rat(v))
 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational value", return -1);
+			"expecting rational value", return isl_stat_error);
 
 	mpz_export(chunks, NULL, -1, size, 0, 0, v->n);
 	if (isl_val_is_zero(v))
 		memset(chunks, 0, size);
 
-	return 0;
+	return isl_stat_ok;
 }

diff  --git a/polly/lib/External/isl/isl_val_imath.c b/polly/lib/External/isl/isl_val_imath.c
index 8f91700a895d..dc4acc1d8456 100644
--- a/polly/lib/External/isl/isl_val_imath.c
+++ b/polly/lib/External/isl/isl_val_imath.c
@@ -30,34 +30,34 @@ __isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
  * return one, while impz_export will not fill in any chunks.  We therefore
  * do it ourselves.
  */
-int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
+isl_stat isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
 	void *chunks)
 {
 	if (!v || !chunks)
-		return -1;
+		return isl_stat_error;
 
 	if (!isl_val_is_rat(v))
 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational value", return -1);
+			"expecting rational value", return isl_stat_error);
 
 	impz_export(chunks, NULL, -1, size, 0, 0, v->n);
 	if (isl_val_is_zero(v))
 		memset(chunks, 0, size);
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Return the number of chunks of size "size" required to
  * store the absolute value of the numerator of "v".
  */
-size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
+isl_size isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
 {
 	if (!v)
-		return 0;
+		return isl_size_error;
 
 	if (!isl_val_is_rat(v))
 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational value", return 0);
+			"expecting rational value", return isl_size_error);
 
 	size *= 8;
 	return (impz_sizeinbase(v->n, 2) + size - 1) / size;

diff  --git a/polly/lib/External/isl/isl_val_private.h b/polly/lib/External/isl/isl_val_private.h
index 1a4fa1986494..59d851990507 100644
--- a/polly/lib/External/isl/isl_val_private.h
+++ b/polly/lib/External/isl/isl_val_private.h
@@ -40,18 +40,8 @@ isl_bool isl_val_involves_dims(__isl_keep isl_val *v, enum isl_dim_type type,
 	unsigned first, unsigned n);
 __isl_give isl_val *isl_val_insert_dims(__isl_take isl_val *v,
 	enum isl_dim_type type, unsigned first, unsigned n);
-__isl_give isl_val *isl_val_drop_dims(__isl_take isl_val *v,
-	enum isl_dim_type type, unsigned first, unsigned n);
 __isl_give isl_val *isl_val_set_dim_name(__isl_take isl_val *v,
 	enum isl_dim_type type, unsigned pos, const char *s);
-__isl_give isl_space *isl_val_get_space(__isl_keep isl_val *v);
-__isl_give isl_val *isl_val_reset_domain_space(__isl_take isl_val *v,
-	__isl_take isl_space *space);
-__isl_give isl_val *isl_val_align_params(__isl_take isl_val *v,
-	__isl_take isl_space *space);
-__isl_give isl_val *isl_val_realign_domain(__isl_take isl_val *v,
-	__isl_take isl_reordering *r);
-__isl_give isl_val *isl_val_zero_on_domain(__isl_take isl_local_space *ls);
 
 __isl_give isl_val *isl_val_scale_val(__isl_take isl_val *v1,
 	__isl_take isl_val *v2);
@@ -60,12 +50,8 @@ __isl_give isl_val *isl_val_scale_down_val(__isl_take isl_val *v1,
 __isl_give isl_val *isl_val_mod_val(__isl_take isl_val *v1,
 	__isl_take isl_val *v2);
 
-int isl_val_plain_is_equal(__isl_keep isl_val *val1, __isl_keep isl_val *val2);
-
-isl_bool isl_val_matching_params(__isl_keep isl_val *v,
-	__isl_keep isl_space *space);
-isl_stat isl_val_check_match_domain_space(__isl_keep isl_val *v,
-	__isl_keep isl_space *space);
+isl_bool isl_val_plain_is_equal(__isl_keep isl_val *val1,
+	__isl_keep isl_val *val2);
 
 #undef BASE
 #define BASE val

diff  --git a/polly/lib/External/isl/isl_val_sioimath.c b/polly/lib/External/isl/isl_val_sioimath.c
index 42f87e3c3bfe..9b9e73d817a6 100644
--- a/polly/lib/External/isl/isl_val_sioimath.c
+++ b/polly/lib/External/isl/isl_val_sioimath.c
@@ -31,37 +31,37 @@ __isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
  * return one, while impz_export will not fill in any chunks.  We therefore
  * do it ourselves.
  */
-int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
+isl_stat isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
 	void *chunks)
 {
 	isl_sioimath_scratchspace_t scratch;
 
 	if (!v || !chunks)
-		return -1;
+		return isl_stat_error;
 
 	if (!isl_val_is_rat(v))
 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational value", return -1);
+			"expecting rational value", return isl_stat_error);
 
 	impz_export(chunks, NULL, -1, size, 0, 0,
 	    isl_sioimath_bigarg_src(*v->n, &scratch));
 	if (isl_val_is_zero(v))
 		memset(chunks, 0, size);
 
-	return 0;
+	return isl_stat_ok;
 }
 
 /* Return the number of chunks of size "size" required to
  * store the absolute value of the numerator of "v".
  */
-size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
+isl_size isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
 {
 	if (!v)
-		return 0;
+		return isl_size_error;
 
 	if (!isl_val_is_rat(v))
 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
-			"expecting rational value", return 0);
+			"expecting rational value", return isl_size_error);
 
 	size *= 8;
 	return (isl_sioimath_sizeinbase(*v->n, 2) + size - 1) / size;

diff  --git a/polly/lib/External/isl/isl_vec.c b/polly/lib/External/isl/isl_vec.c
index 029162057b4a..da971c55f640 100644
--- a/polly/lib/External/isl/isl_vec.c
+++ b/polly/lib/External/isl/isl_vec.c
@@ -245,9 +245,9 @@ __isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec)
 	return NULL;
 }
 
-int isl_vec_size(__isl_keep isl_vec *vec)
+isl_size isl_vec_size(__isl_keep isl_vec *vec)
 {
-	return vec ? vec->size : -1;
+	return vec ? vec->size : isl_size_error;
 }
 
 /* Extract the element at position "pos" of "vec".
@@ -334,7 +334,7 @@ isl_bool isl_vec_is_zero(__isl_keep isl_vec *vec)
 {
 	if (!vec)
 		return isl_bool_error;
-	return isl_seq_first_non_zero(vec->el, vec->size) < 0;
+	return isl_bool_ok(isl_seq_first_non_zero(vec->el, vec->size) < 0);
 }
 
 isl_bool isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2)
@@ -345,7 +345,7 @@ isl_bool isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2)
 	if (vec1->size != vec2->size)
 		return isl_bool_false;
 
-	return isl_seq_eq(vec1->el, vec2->el, vec1->size);
+	return isl_bool_ok(isl_seq_eq(vec1->el, vec2->el, vec1->size));
 }
 
 __isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer,

diff  --git a/polly/lib/External/isl/isl_vertices.c b/polly/lib/External/isl/isl_vertices.c
index 90355451da21..120deab4ba78 100644
--- a/polly/lib/External/isl/isl_vertices.c
+++ b/polly/lib/External/isl/isl_vertices.c
@@ -122,13 +122,15 @@ static __isl_give isl_vertices *vertices_from_list(__isl_keep isl_basic_set *bse
 static isl_bool add_vertex(struct isl_vertex_list **list,
 	__isl_keep isl_basic_set *bset, struct isl_tab *tab)
 {
-	unsigned nvar;
+	isl_size nvar;
 	struct isl_vertex_list *v = NULL;
 
 	if (isl_tab_detect_implicit_equalities(tab) < 0)
 		return isl_bool_error;
 
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0)
+		return isl_bool_error;
 
 	v = isl_calloc_type(tab->mat->ctx, struct isl_vertex_list);
 	if (!v)
@@ -232,20 +234,20 @@ static __isl_give isl_vertices *vertices_0D(__isl_keep isl_basic_set *bset)
 /* Is the row pointed to by "f" linearly independent of the "n" first
  * rows in "facets"?
  */
-static int is_independent(__isl_keep isl_mat *facets, int n, isl_int *f)
+static isl_bool is_independent(__isl_keep isl_mat *facets, int n, isl_int *f)
 {
-	int rank;
+	isl_size rank;
 
 	if (isl_seq_first_non_zero(f, facets->n_col) < 0)
-		return 0;
+		return isl_bool_false;
 
 	isl_seq_cpy(facets->row[n], f, facets->n_col);
 	facets->n_row = n + 1;
 	rank = isl_mat_rank(facets);
 	if (rank < 0)
-		return -1;
+		return isl_bool_error;
 
-	return rank == n + 1;
+	return isl_bool_ok(rank == n + 1);
 }
 
 /* Check whether we can select constraint "level", given the current selection
@@ -263,34 +265,32 @@ static int is_independent(__isl_keep isl_mat *facets, int n, isl_int *f)
  * deselected constraints turning into equalities, then the corresponding
  * vertices have already been generated, so the constraint cannot be selected.
  */
-static int can_select(__isl_keep isl_basic_set *bset, int level,
+static isl_bool can_select(__isl_keep isl_basic_set *bset, int level,
 	struct isl_tab *tab, __isl_keep isl_mat *facets, int selected,
 	int *selection)
 {
 	int i;
-	int indep;
+	isl_bool indep;
 	unsigned ovar;
 	struct isl_tab_undo *snap;
 
 	if (isl_tab_is_redundant(tab, level))
-		return 0;
+		return isl_bool_false;
 
 	ovar = isl_space_offset(bset->dim, isl_dim_set);
 
 	indep = is_independent(facets, selected, bset->ineq[level] + 1 + ovar);
-	if (indep < 0)
-		return -1;
-	if (!indep)
-		return 0;
+	if (indep < 0 || !indep)
+		return indep;
 
 	snap = isl_tab_snap(tab);
 	if (isl_tab_select_facet(tab, level) < 0)
-		return -1;
+		return isl_bool_error;
 
 	if (tab->empty) {
 		if (isl_tab_rollback(tab, snap) < 0)
-			return -1;
-		return 0;
+			return isl_bool_error;
+		return isl_bool_false;
 	}
 
 	for (i = 0; i < level; ++i) {
@@ -306,15 +306,15 @@ static int can_select(__isl_keep isl_basic_set *bset, int level,
 		else
 			sgn = isl_tab_sign_of_max(tab, i);
 		if (sgn < -1)
-			return -1;
+			return isl_bool_error;
 		if (sgn <= 0) {
 			if (isl_tab_rollback(tab, snap) < 0)
-				return -1;
-			return 0;
+				return isl_bool_error;
+			return isl_bool_false;
 		}
 	}
 
-	return 1;
+	return isl_bool_true;
 }
 
 /* Compute the parametric vertices and the chamber decomposition
@@ -378,7 +378,7 @@ __isl_give isl_vertices *isl_basic_set_compute_vertices(
 	struct isl_tab *tab;
 	int level;
 	int init;
-	unsigned nvar;
+	isl_size nvar;
 	int *selection = NULL;
 	int selected;
 	struct isl_tab_undo **snap = NULL;
@@ -396,13 +396,14 @@ __isl_give isl_vertices *isl_basic_set_compute_vertices(
 	if (bset->n_eq != 0)
 		return lower_dim_vertices(bset);
 
-	isl_assert(bset->ctx, isl_basic_set_dim(bset, isl_dim_div) == 0,
-		return NULL);
-
-	if (isl_basic_set_dim(bset, isl_dim_set) == 0)
-		return vertices_0D(bset);
+	if (isl_basic_set_check_no_locals(bset) < 0)
+		return NULL;
 
 	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar < 0)
+		return NULL;
+	if (nvar == 0)
+		return vertices_0D(bset);
 
 	bset = isl_basic_set_copy(bset);
 	bset = isl_basic_set_set_rational(bset);
@@ -439,7 +440,7 @@ __isl_give isl_vertices *isl_basic_set_compute_vertices(
 			continue;
 		}
 		if (init) {
-			int ok;
+			isl_bool ok;
 			snap[level] = isl_tab_snap(tab);
 			ok = can_select(bset, level, tab, facets, selected,
 					selection);
@@ -580,7 +581,12 @@ static isl_bool can_intersect(struct isl_tab *tab,
 	snap = isl_tab_snap(tab);
 
 	for (i = 0; i < bset->n_ineq; ++i) {
-		if (isl_tab_ineq_type(tab, bset->ineq[i]) == isl_ineq_redundant)
+		enum isl_ineq_type type;
+
+		type = isl_tab_ineq_type(tab, bset->ineq[i]);
+		if (type < 0)
+			return isl_bool_error;
+		if (type == isl_ineq_redundant)
 			continue;
 		if (isl_tab_add_ineq(tab, bset->ineq[i]) < 0)
 			return isl_bool_error;
@@ -710,7 +716,7 @@ static struct isl_facet_todo *create_todo(struct isl_tab *tab, int con)
 	todo->bset = isl_basic_set_sort_constraints(todo->bset);
 	if (!todo->bset)
 		goto error;
-	ISL_F_SET(todo->bset, ISL_BASIC_SET_NORMALIZED);
+	ISL_F_SET(todo->bset, ISL_BASIC_SET_NO_REDUNDANT);
 	todo->tab = isl_tab_dup(tab);
 	if (!todo->tab)
 		goto error;
@@ -976,9 +982,9 @@ isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex)
 	return vertex ? isl_vertices_get_ctx(vertex->vertices) : NULL;
 }
 
-int isl_vertex_get_id(__isl_keep isl_vertex *vertex)
+isl_size isl_vertex_get_id(__isl_keep isl_vertex *vertex)
 {
-	return vertex ? vertex->id : -1;
+	return vertex ? vertex->id : isl_size_error;
 }
 
 /* Return the activity domain of the vertex "vertex".
@@ -1040,12 +1046,14 @@ static __isl_give isl_vertex *isl_vertex_alloc(__isl_take isl_vertices *vertices
 	return NULL;
 }
 
-void isl_vertex_free(__isl_take isl_vertex *vertex)
+__isl_null isl_vertex *isl_vertex_free(__isl_take isl_vertex *vertex)
 {
 	if (!vertex)
-		return;
+		return NULL;
 	isl_vertices_free(vertex->vertices);
 	free(vertex);
+
+	return NULL;
 }
 
 isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell)
@@ -1088,15 +1096,17 @@ static __isl_give isl_cell *isl_cell_alloc(__isl_take isl_vertices *vertices,
 	return NULL;
 }
 
-void isl_cell_free(__isl_take isl_cell *cell)
+__isl_null isl_cell *isl_cell_free(__isl_take isl_cell *cell)
 {
 	if (!cell)
-		return;
+		return NULL;
 
 	isl_vertices_free(cell->vertices);
 	free(cell->ids);
 	isl_basic_set_free(cell->dom);
 	free(cell);
+
+	return NULL;
 }
 
 /* Create a tableau of the cone obtained by first homogenizing the given
@@ -1108,11 +1118,13 @@ static struct isl_tab *tab_for_shifted_cone(__isl_keep isl_basic_set *bset)
 	int i;
 	isl_vec *c = NULL;
 	struct isl_tab *tab;
+	isl_size total;
 
-	if (!bset)
+	total = isl_basic_set_dim(bset, isl_dim_all);
+	if (total < 0)
 		return NULL;
 	tab = isl_tab_alloc(bset->ctx, bset->n_eq + bset->n_ineq + 1,
-			    1 + isl_basic_set_total_dim(bset), 0);
+			    1 + total, 0);
 	if (!tab)
 		return NULL;
 	tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL);
@@ -1122,7 +1134,7 @@ static struct isl_tab *tab_for_shifted_cone(__isl_keep isl_basic_set *bset)
 		return tab;
 	}
 
-	c = isl_vec_alloc(bset->ctx, 1 + 1 + isl_basic_set_total_dim(bset));
+	c = isl_vec_alloc(bset->ctx, 1 + 1 + total);
 	if (!c)
 		goto error;
 
@@ -1323,9 +1335,9 @@ isl_ctx *isl_vertices_get_ctx(__isl_keep isl_vertices *vertices)
 	return vertices ? vertices->bset->ctx : NULL;
 }
 
-int isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices)
+isl_size isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices)
 {
-	return vertices ? vertices->n_vertices : -1;
+	return vertices ? vertices->n_vertices : isl_size_error;
 }
 
 __isl_give isl_vertices *isl_morph_vertices(__isl_take isl_morph *morph,
@@ -1452,7 +1464,7 @@ static isl_stat triangulate(__isl_keep isl_cell *cell, __isl_keep isl_vec *v,
 	isl_stat (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
 {
 	int i, j, k;
-	int d, nparam;
+	isl_size d, nparam;
 	int *ids;
 	isl_ctx *ctx;
 	isl_basic_set *vertex;
@@ -1461,6 +1473,8 @@ static isl_stat triangulate(__isl_keep isl_cell *cell, __isl_keep isl_vec *v,
 	ctx = isl_cell_get_ctx(cell);
 	d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set);
 	nparam = isl_basic_set_dim(cell->vertices->bset, isl_dim_param);
+	if (d < 0 || nparam < 0)
+		return isl_stat_error;
 
 	if (n_simplex + n_other == d + 1)
 		return call_on_simplex(cell, simplex_ids, n_simplex,
@@ -1506,7 +1520,7 @@ static isl_stat triangulate(__isl_keep isl_cell *cell, __isl_keep isl_vec *v,
 isl_stat isl_cell_foreach_simplex(__isl_take isl_cell *cell,
 	isl_stat (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
 {
-	int d, total;
+	isl_size d, total;
 	isl_stat r;
 	isl_ctx *ctx;
 	isl_vec *v = NULL;
@@ -1516,7 +1530,9 @@ isl_stat isl_cell_foreach_simplex(__isl_take isl_cell *cell,
 		return isl_stat_error;
 
 	d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set);
-	total = isl_basic_set_total_dim(cell->vertices->bset);
+	total = isl_basic_set_dim(cell->vertices->bset, isl_dim_all);
+	if (d < 0 || total < 0)
+		return isl_stat_error;
 
 	if (cell->n_vertices == d + 1)
 		return fn(cell, user);

diff  --git a/polly/lib/External/isl/m4/ax_cxx_compile_stdcxx_11_no_override.m4 b/polly/lib/External/isl/m4/ax_cxx_compile_stdcxx_11_no_override.m4
new file mode 100644
index 000000000000..d8235f735841
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_cxx_compile_stdcxx_11_no_override.m4
@@ -0,0 +1,37 @@
+# Check if $CXX does or can be made to support C++11 by adding switches.
+# If $CXX explicitly selects a language standard, then
+# refrain from overriding this choice.
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11_NO_OVERRIDE], [dnl
+	AC_PROG_GREP
+	echo $CXX | $GREP -e "-std=" > /dev/null 2> /dev/null
+	if test $? -eq 0; then
+		_AX_CXX_COMPILE_STDCXX_11_DEFAULT
+	else
+		AX_CXX_COMPILE_STDCXX_11([noext], [optional])
+	fi
+])
+
+# Check if $CXX supports C++11 by default (without adding switches).
+# This is a trimmed down version of AX_CXX_COMPILE_STDCXX_11
+# that reuses its _AX_CXX_COMPILE_STDCXX_testbody_11.
+AC_DEFUN([_AX_CXX_COMPILE_STDCXX_11_DEFAULT], [dnl
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+  AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
+  ax_cv_cxx_compile_cxx11,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_11])],
+    [ax_cv_cxx_compile_cxx11=yes],
+    [ax_cv_cxx_compile_cxx11=no])])
+  if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+    ac_success=yes
+  fi
+  AC_LANG_POP([C++])
+  if test x$ac_success = xno; then
+    HAVE_CXX11=0
+  else
+    HAVE_CXX11=1
+    AC_DEFINE(HAVE_CXX11,1,
+              [define if the compiler supports basic C++11 syntax])
+  fi
+  AC_SUBST(HAVE_CXX11)
+])

diff  --git a/polly/lib/External/isl/m4/ax_detect_clang.m4 b/polly/lib/External/isl/m4/ax_detect_clang.m4
index fc16d72d7a47..1dfc5d857da1 100644
--- a/polly/lib/External/isl/m4/ax_detect_clang.m4
+++ b/polly/lib/External/isl/m4/ax_detect_clang.m4
@@ -1,35 +1,35 @@
 AC_DEFUN([AX_DETECT_CLANG], [
 AC_SUBST(CLANG_CXXFLAGS)
 AC_SUBST(CLANG_LDFLAGS)
+AC_SUBST(CLANG_RFLAG)
 AC_SUBST(CLANG_LIBS)
 AC_PROG_GREP
 AC_PROG_SED
-llvm_config="llvm-config"
-AC_CHECK_PROG([llvm_config_found], ["$llvm_config"], [yes])
 if test "x$with_clang_prefix" != "x"; then
-	llvm_config="$with_clang_prefix/bin/llvm-config"
-	if test -x "$llvm_config"; then
-		llvm_config_found=yes
-	fi
+	LLVM_CONFIG="$with_clang_prefix/bin/llvm-config"
 fi
-if test "$llvm_config_found" != yes; then
+AC_PATH_PROG([LLVM_CONFIG], ["llvm-config"])
+if test -z "$LLVM_CONFIG" || test ! -x "$LLVM_CONFIG"; then
 	AC_MSG_ERROR([llvm-config not found])
 fi
-CLANG_CXXFLAGS=`$llvm_config --cxxflags | \
+CLANG_CXXFLAGS=`$LLVM_CONFIG --cxxflags | \
 	$SED -e 's/-Wcovered-switch-default//;s/-gsplit-dwarf//'`
-CLANG_LDFLAGS=`$llvm_config --ldflags`
-targets=`$llvm_config --targets-built`
+CLANG_LDFLAGS=`$LLVM_CONFIG --ldflags`
+# Construct a -R argument for libtool.
+# This is needed in case some of the clang libraries are shared libraries.
+CLANG_RFLAG=`echo "$CLANG_LDFLAGS" | $SED -e 's/-L/-R/g'`
+targets=`$LLVM_CONFIG --targets-built`
 components="$targets asmparser bitreader support mc"
-$llvm_config --components | $GREP option > /dev/null 2> /dev/null
+$LLVM_CONFIG --components | $GREP option > /dev/null 2> /dev/null
 if test $? -eq 0; then
 	components="$components option"
 fi
-CLANG_LIBS=`$llvm_config --libs $components`
-systemlibs=`$llvm_config --system-libs 2> /dev/null | tail -1`
+CLANG_LIBS=`$LLVM_CONFIG --libs $components`
+systemlibs=`$LLVM_CONFIG --system-libs 2> /dev/null | tail -1`
 if test $? -eq 0; then
 	CLANG_LIBS="$CLANG_LIBS $systemlibs"
 fi
-CLANG_PREFIX=`$llvm_config --prefix`
+CLANG_PREFIX=`$LLVM_CONFIG --prefix`
 AC_DEFINE_UNQUOTED(CLANG_PREFIX, ["$CLANG_PREFIX"], [Clang installation prefix])
 
 SAVE_CPPFLAGS="$CPPFLAGS"
@@ -54,7 +54,14 @@ AC_EGREP_HEADER([DiagnosticsEngine], [clang/Basic/Diagnostic.h], [],
 	[Define to Diagnostic for older versions of clang])])
 AC_EGREP_HEADER([ArrayRef], [clang/Driver/Driver.h],
 	[AC_DEFINE([USE_ARRAYREF], [],
-		[Define if Driver::BuildCompilation takes ArrayRef])])
+		[Define if Driver::BuildCompilation takes ArrayRef])
+	AC_EGREP_HEADER([ArrayRef.*CommandLineArgs],
+		[clang/Frontend/CompilerInvocation.h],
+		[AC_DEFINE([CREATE_FROM_ARGS_TAKES_ARRAYREF], [],
+			[Define if CompilerInvocation::CreateFromArgs takes
+			 ArrayRef])
+		])
+	])
 AC_EGREP_HEADER([CXXIsProduction], [clang/Driver/Driver.h],
 	[AC_DEFINE([HAVE_CXXISPRODUCTION], [],
 		[Define if Driver constructor takes CXXIsProduction argument])])
@@ -137,8 +144,11 @@ AC_EGREP_HEADER([initializeBuiltins],
 	[AC_DEFINE([initializeBuiltins], [InitializeBuiltins],
 		[Define to InitializeBuiltins for older versions of clang])])
 AC_EGREP_HEADER([IK_C], [clang/Frontend/FrontendOptions.h], [],
-	 [AC_DEFINE([IK_C], [InputKind::C],
-	    [Define to InputKind::C for newer versions of clang])])
+	[AC_CHECK_HEADER([clang/Basic/LangStandard.h],
+		[IK_C=Language::C], [IK_C=InputKind::C])
+	 AC_DEFINE_UNQUOTED([IK_C], [$IK_C],
+	 [Define to Language::C or InputKind::C for newer versions of clang])
+	])
 AC_TRY_COMPILE([
 	#include <clang/Basic/TargetOptions.h>
 	#include <clang/Lex/PreprocessorOptions.h>
@@ -163,6 +173,9 @@ AC_TRY_COMPILE([
 	Clang->setInvocation(std::make_shared<CompilerInvocation>(*invocation));
 ], [AC_DEFINE([SETINVOCATION_TAKES_SHARED_PTR], [],
 	[Defined if CompilerInstance::setInvocation takes a shared_ptr])])
+AC_CHECK_HEADER([llvm/Option/Arg.h],
+	[AC_DEFINE([HAVE_LLVM_OPTION_ARG_H], [],
+		   [Define if llvm/Option/Arg.h exists])])
 AC_LANG_POP
 CPPFLAGS="$SAVE_CPPFLAGS"
 

diff  --git a/polly/lib/External/isl/opt_type.h b/polly/lib/External/isl/opt_type.h
new file mode 100644
index 000000000000..9505e72c20bf
--- /dev/null
+++ b/polly/lib/External/isl/opt_type.h
@@ -0,0 +1,16 @@
+#define NO_LOC
+#ifdef HAS_TYPE
+#define OPT_TYPE_PARAM			, enum isl_fold type
+#define OPT_TYPE_PARAM_FIRST		enum isl_fold type,
+#define OPT_TYPE_ARG(loc)		, loc type
+#define OPT_TYPE_ARG_FIRST(loc)		loc type,
+#define OPT_SET_TYPE(loc,val)		loc type = (val);
+#define OPT_EQUAL_TYPES(loc1, loc2)	((loc1 type) == (loc2 type))
+#else
+#define OPT_TYPE_PARAM
+#define OPT_TYPE_PARAM_FIRST
+#define OPT_TYPE_ARG(loc)
+#define OPT_TYPE_ARG_FIRST(loc)
+#define OPT_SET_TYPE(loc,val)
+#define OPT_EQUAL_TYPES(loc1, loc2)	1
+#endif

diff  --git a/polly/lib/External/isl/pip.c b/polly/lib/External/isl/pip.c
index 002bc704b7d1..9e6c1ec011da 100644
--- a/polly/lib/External/isl/pip.c
+++ b/polly/lib/External/isl/pip.c
@@ -65,12 +65,14 @@ ISL_ARG_DEF(options, struct options, options_args)
 
 static __isl_give isl_basic_set *set_bounds(__isl_take isl_basic_set *bset)
 {
-	unsigned nparam;
+	isl_size nparam;
 	int i, r;
 	isl_point *pt, *pt2;
 	isl_basic_set *box;
 
 	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	if (nparam < 0)
+		return isl_basic_set_free(bset);
 	r = nparam >= 8 ? 4 : nparam >= 5 ? 6 : 30;
 
 	pt = isl_basic_set_sample_point(isl_basic_set_copy(bset));
@@ -86,14 +88,42 @@ static __isl_give isl_basic_set *set_bounds(__isl_take isl_basic_set *bset)
 	return isl_basic_set_intersect(bset, box);
 }
 
-static struct isl_basic_set *to_parameter_domain(struct isl_basic_set *context)
+static __isl_give isl_basic_set *to_parameter_domain(
+	__isl_take isl_basic_set *context)
 {
+	isl_size dim;
+
+	dim = isl_basic_set_dim(context, isl_dim_set);
+	if (dim < 0)
+		return isl_basic_set_free(context);
 	context = isl_basic_set_move_dims(context, isl_dim_param, 0,
-		    isl_dim_set, 0, isl_basic_set_dim(context, isl_dim_set));
+		    isl_dim_set, 0, dim);
 	context = isl_basic_set_params(context);
 	return context;
 }
 
+/* If "context" has more parameters than "bset", then reinterpret
+ * the last dimensions of "bset" as parameters.
+ */
+static __isl_give isl_basic_set *move_parameters(__isl_take isl_basic_set *bset,
+	__isl_keep isl_basic_set *context)
+{
+	isl_size nparam, nparam_bset, dim;
+
+	nparam = isl_basic_set_dim(context, isl_dim_param);
+	nparam_bset = isl_basic_set_dim(bset, isl_dim_param);
+	if (nparam < 0 | nparam_bset < 0)
+		return isl_basic_set_free(bset);
+	if (nparam == nparam_bset)
+		return bset;
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		return isl_basic_set_free(bset);
+	bset = isl_basic_set_move_dims(bset, isl_dim_param, 0,
+					    isl_dim_set, dim - nparam, nparam);
+	return bset;
+}
+
 /* Plug in the initial values of "params" for the parameters in "bset" and
  * return the result.  The remaining entries in "params", if any,
  * correspond to the existentially quantified variables in the description
@@ -102,9 +132,12 @@ static struct isl_basic_set *to_parameter_domain(struct isl_basic_set *context)
 static __isl_give isl_basic_set *plug_in_parameters(
 	__isl_take isl_basic_set *bset, __isl_take isl_vec *params)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_basic_set_dim(bset, isl_dim_param);
+	if (n < 0)
+		bset = isl_basic_set_free(bset);
 	for (i = 0; i < n; ++i)
 		bset = isl_basic_set_fix(bset,
 					 isl_dim_param, i, params->el[1 + i]);
@@ -124,9 +157,12 @@ static __isl_give isl_basic_set *plug_in_parameters(
 static __isl_give isl_set *set_plug_in_parameters(__isl_take isl_set *set,
 	__isl_take isl_vec *params)
 {
-	int i, n;
+	int i;
+	isl_size n;
 
 	n = isl_set_dim(set, isl_dim_param);
+	if (n < 0)
+		set = isl_set_free(set);
 	for (i = 0; i < n; ++i)
 		set = isl_set_fix(set, isl_dim_param, i, params->el[1 + i]);
 
@@ -144,13 +180,15 @@ static __isl_give isl_set *set_plug_in_parameters(__isl_take isl_set *set,
 static __isl_give isl_vec *opt_at(__isl_take isl_basic_set *bset,
 	__isl_take isl_vec *params, int max)
 {
-	unsigned dim;
+	isl_size dim;
 	isl_ctx *ctx;
 	struct isl_vec *opt;
 	struct isl_vec *obj;
 	int i;
 
 	dim = isl_basic_set_dim(bset, isl_dim_set);
+	if (dim < 0)
+		goto error;
 
 	bset = plug_in_parameters(bset, params);
 
@@ -187,6 +225,10 @@ static __isl_give isl_vec *opt_at(__isl_take isl_basic_set *bset,
 	isl_vec_free(obj);
 
 	return opt;
+error:
+	isl_basic_set_free(bset);
+	isl_vec_free(params);
+	return NULL;
 empty:
 	isl_vec_free(opt);
 	opt = isl_vec_alloc(ctx, 0);
@@ -305,7 +347,6 @@ int main(int argc, char **argv)
 	int max = 0;
 	int rational = 0;
 	int n;
-	int nparam;
 	struct options *options;
 
 	options = options_new_with_defaults();
@@ -337,12 +378,7 @@ int main(int argc, char **argv)
 		context = isl_basic_set_intersect(context,
 		isl_basic_set_positive_orthant(isl_basic_set_get_space(context)));
 	context = to_parameter_domain(context);
-	nparam = isl_basic_set_dim(context, isl_dim_param);
-	if (nparam != isl_basic_set_dim(bset, isl_dim_param)) {
-		int dim = isl_basic_set_dim(bset, isl_dim_set);
-		bset = isl_basic_set_move_dims(bset, isl_dim_param, 0,
-					    isl_dim_set, dim - nparam, nparam);
-	}
+	bset = move_parameters(bset, context);
 	if (!urs_unknowns)
 		bset = isl_basic_set_intersect(bset,
 		isl_basic_set_positive_orthant(isl_basic_set_get_space(bset)));

diff  --git a/polly/lib/External/isl/polyhedron_minimize.c b/polly/lib/External/isl/polyhedron_minimize.c
index 526b37368f2a..87f683794d82 100644
--- a/polly/lib/External/isl/polyhedron_minimize.c
+++ b/polly/lib/External/isl/polyhedron_minimize.c
@@ -61,16 +61,16 @@ int main(int argc, char **argv)
 	struct isl_vec *obj;
 	struct isl_vec *sol;
 	isl_int opt;
-	unsigned dim;
+	isl_size dim;
 	enum isl_lp_result res;
 	isl_printer *p;
 
 	isl_int_init(opt);
 	bset = isl_basic_set_read_from_file(ctx, stdin);
-	assert(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	assert(dim >= 0);
 	obj = isl_vec_read_from_file(ctx, stdin);
 	assert(obj);
-	dim = isl_basic_set_total_dim(bset);
 	assert(obj->size >= dim && obj->size <= dim + 1);
 	if (obj->size != dim + 1)
 		obj = isl_vec_lin_to_aff(obj);

diff  --git a/polly/lib/External/isl/polytope_scan.c b/polly/lib/External/isl/polytope_scan.c
index c78743252fbd..129a20d7d67b 100644
--- a/polly/lib/External/isl/polytope_scan.c
+++ b/polly/lib/External/isl/polytope_scan.c
@@ -48,14 +48,17 @@ static isl_stat scan_samples_add_sample(struct isl_scan_callback *cb,
 	return isl_stat_error;
 }
 
-static struct isl_mat *isl_basic_set_scan_samples(struct isl_basic_set *bset)
+static __isl_give isl_mat *isl_basic_set_scan_samples(
+	__isl_take isl_basic_set *bset)
 {
 	isl_ctx *ctx;
-	unsigned dim;
+	isl_size dim;
 	struct scan_samples ss;
 
 	ctx = isl_basic_set_get_ctx(bset);
-	dim = isl_basic_set_total_dim(bset);
+	dim = isl_basic_set_dim(bset, isl_dim_all);
+	if (dim < 0)
+		goto error;
 	ss.callback.add = scan_samples_add_sample;
 	ss.samples = isl_mat_alloc(ctx, 0, 1 + dim);
 	if (!ss.samples)

diff  --git a/polly/lib/External/isl/print.c b/polly/lib/External/isl/print.c
index 44855a2e990a..a87f9221a379 100644
--- a/polly/lib/External/isl/print.c
+++ b/polly/lib/External/isl/print.c
@@ -17,6 +17,9 @@
 #define BASE id
 #include <print_templ.c>
 #undef BASE
+#define BASE multi_id
+#include <print_templ.c>
+#undef BASE
 #define BASE val
 #include <print_templ.c>
 #undef BASE

diff  --git a/polly/lib/External/isl/print_templ.c b/polly/lib/External/isl/print_templ.c
index d6b0db76bd14..9ed93f143853 100644
--- a/polly/lib/External/isl/print_templ.c
+++ b/polly/lib/External/isl/print_templ.c
@@ -7,6 +7,10 @@
 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
 #define FN(TYPE,NAME) xFN(TYPE,NAME)
 
+#ifndef PRINT_DUMP_DEFAULT
+#define PRINT_DUMP_DEFAULT	1
+#endif
+
 void FN(TYPE,dump)(__isl_keep TYPE *obj)
 {
 	isl_printer *p;
@@ -14,12 +18,14 @@ void FN(TYPE,dump)(__isl_keep TYPE *obj)
 	if (!obj)
 		return;
 	p = isl_printer_to_file(FN(TYPE,get_ctx)(obj), stderr);
-	p = isl_printer_set_dump(p, 1);
+	p = isl_printer_set_dump(p, PRINT_DUMP_DEFAULT);
 	p = FN(isl_printer_print,BASE)(p, obj);
 	p = isl_printer_end_line(p);
 	isl_printer_free(p);
 }
 
+#undef PRINT_DUMP_DEFAULT
+
 __isl_give char *FN(TYPE,to_str)(__isl_keep TYPE *obj)
 {
 	isl_printer *p;

diff  --git a/polly/lib/External/isl/print_yaml_field_templ.c b/polly/lib/External/isl/print_yaml_field_templ.c
new file mode 100644
index 000000000000..088e701d9694
--- /dev/null
+++ b/polly/lib/External/isl/print_yaml_field_templ.c
@@ -0,0 +1,22 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef TYPE
+#define TYPE CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Print a key-value pair of a YAML mapping to "p",
+ * with key "name" and value "val".
+ */
+static __isl_give isl_printer *FN(print_yaml_field,BASE)(
+	__isl_take isl_printer *p, const char *name, __isl_keep TYPE *val)
+{
+	p = isl_printer_print_str(p, name);
+	p = isl_printer_yaml_next(p);
+	p = isl_printer_print_str(p, "\"");
+	p = FN(isl_printer_print,BASE)(p, val);
+	p = isl_printer_print_str(p, "\"");
+	p = isl_printer_yaml_next(p);
+
+	return p;
+}

diff  --git a/polly/lib/External/isl/py-compile b/polly/lib/External/isl/py-compile
new file mode 100644
index 000000000000..3693d96b0a61
--- /dev/null
+++ b/polly/lib/External/isl/py-compile
@@ -0,0 +1,170 @@
+#!/bin/sh
+# py-compile - Compile a Python program
+
+scriptversion=2016-01-11.22; # UTC
+
+# Copyright (C) 2000-2017 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+if [ -z "$PYTHON" ]; then
+  PYTHON=python
+fi
+
+me=py-compile
+
+usage_error ()
+{
+  echo "$me: $*" >&2
+  echo "Try '$me --help' for more information." >&2
+  exit 1
+}
+
+basedir=
+destdir=
+while test $# -ne 0; do
+  case "$1" in
+    --basedir)
+      if test $# -lt 2; then
+        usage_error "option '--basedir' requires an argument"
+      else
+        basedir=$2
+      fi
+      shift
+      ;;
+    --destdir)
+      if test $# -lt 2; then
+        usage_error "option '--destdir' requires an argument"
+      else
+        destdir=$2
+      fi
+      shift
+      ;;
+    -h|--help)
+      cat <<\EOF
+Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..."
+
+Byte compile some python scripts FILES.  Use --destdir to specify any
+leading directory path to the FILES that you don't want to include in the
+byte compiled file.  Specify --basedir for any additional path information you
+do want to be shown in the byte compiled file.
+
+Example:
+  py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py
+
+Report bugs to <bug-automake at gnu.org>.
+EOF
+      exit $?
+      ;;
+    -v|--version)
+      echo "$me $scriptversion"
+      exit $?
+      ;;
+    --)
+      shift
+      break
+      ;;
+    -*)
+      usage_error "unrecognized option '$1'"
+      ;;
+    *)
+      break
+      ;;
+  esac
+  shift
+done
+
+files=$*
+if test -z "$files"; then
+    usage_error "no files given"
+fi
+
+# if basedir was given, then it should be prepended to filenames before
+# byte compilation.
+if [ -z "$basedir" ]; then
+    pathtrans="path = file"
+else
+    pathtrans="path = os.path.join('$basedir', file)"
+fi
+
+# if destdir was given, then it needs to be prepended to the filename to
+# byte compile but not go into the compiled file.
+if [ -z "$destdir" ]; then
+    filetrans="filepath = path"
+else
+    filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
+fi
+
+$PYTHON -c "
+import sys, os, py_compile, imp
+
+files = '''$files'''
+
+sys.stdout.write('Byte-compiling python modules...\n')
+for file in files.split():
+    $pathtrans
+    $filetrans
+    if not os.path.exists(filepath) or not (len(filepath) >= 3
+                                            and filepath[-3:] == '.py'):
+	    continue
+    sys.stdout.write(file)
+    sys.stdout.flush()
+    if hasattr(imp, 'get_tag'):
+        py_compile.compile(filepath, imp.cache_from_source(filepath), path)
+    else:
+        py_compile.compile(filepath, filepath + 'c', path)
+sys.stdout.write('\n')" || exit $?
+
+# this will fail for python < 1.5, but that doesn't matter ...
+$PYTHON -O -c "
+import sys, os, py_compile, imp
+
+# pypy does not use .pyo optimization
+if hasattr(sys, 'pypy_translation_info'):
+    sys.exit(0)
+
+files = '''$files'''
+sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n')
+for file in files.split():
+    $pathtrans
+    $filetrans
+    if not os.path.exists(filepath) or not (len(filepath) >= 3
+                                            and filepath[-3:] == '.py'):
+	    continue
+    sys.stdout.write(file)
+    sys.stdout.flush()
+    if hasattr(imp, 'get_tag'):
+        py_compile.compile(filepath, imp.cache_from_source(filepath, False), path)
+    else:
+        py_compile.compile(filepath, filepath + 'o', path)
+sys.stdout.write('\n')" 2>/dev/null || :
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:

diff  --git a/polly/lib/External/isl/python/isl.py.top b/polly/lib/External/isl/python/isl.py.top
index 71c2b0d356b9..5c858c95608a 100644
--- a/polly/lib/External/isl/python/isl.py.top
+++ b/polly/lib/External/isl/python/isl.py.top
@@ -1,7 +1,15 @@
+import os
 from ctypes import *
-
-isl = cdll.LoadLibrary("libisl.so")
-libc = cdll.LoadLibrary("libc.so.6")
+from ctypes.util import find_library
+
+isl_dyld_library_path = os.environ.get('ISL_DYLD_LIBRARY_PATH')
+if isl_dyld_library_path != None:
+    os.environ['DYLD_LIBRARY_PATH'] =  isl_dyld_library_path
+try:
+    isl = cdll.LoadLibrary(isl_dlname)
+except:
+    isl = cdll.LoadLibrary(find_library("isl"))
+libc = cdll.LoadLibrary(find_library("c"))
 
 class Error(Exception):
     pass

diff  --git a/polly/lib/External/isl/test_inputs/codegen/bilinear.c b/polly/lib/External/isl/test_inputs/codegen/bilinear.c
new file mode 100644
index 000000000000..8b123e1c1d00
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/bilinear.c
@@ -0,0 +1,9 @@
+if (d <= -1) {
+  for (int c0 = 0; c0 < -(-d % 2) - d + w; c0 += 1) {
+    A(c0);
+    B(c0);
+  }
+} else {
+  for (int c0 = 0; c0 < (d % 2) - d + w; c0 += 1)
+    A(c0);
+}

diff  --git a/polly/lib/External/isl/test_inputs/codegen/bilinear.st b/polly/lib/External/isl/test_inputs/codegen/bilinear.st
new file mode 100644
index 000000000000..00704b5e92dc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/bilinear.st
@@ -0,0 +1,9 @@
+# Check that the generated code does not contain a loop upper bound
+# that depends on the loop iterator.
+domain: "[d, w] -> { A[i0] : i0 >= 0 and ((d < 0 and 2*floor((1 + d)/2) < w - i0) or (d >= 0 and 2*floor((d)/2) < w - i0)); B[i0] : i0 >= 0 and d < 0 and 2*floor((d)/2) > 2d - w + i0 }"
+child:
+  schedule: "[d, w] -> [{ A[i0] -> [(i0)]; B[i0] -> [(i0)] }]"
+  child:
+    sequence:
+    - filter: "{ A[x] }"
+    - filter: "{ B[x] }"

diff  --git a/polly/lib/External/isl/test_inputs/codegen/group.c b/polly/lib/External/isl/test_inputs/codegen/group.c
new file mode 100644
index 000000000000..ff65b13c89a9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/group.c
@@ -0,0 +1,7 @@
+{
+  if (N == 0) {
+    C();
+    A();
+  }
+  B();
+}

diff  --git a/polly/lib/External/isl/test_inputs/codegen/group.st b/polly/lib/External/isl/test_inputs/codegen/group.st
new file mode 100644
index 000000000000..04d8ad7e6a7d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/group.st
@@ -0,0 +1,2 @@
+# Check that the condition "N == 0" is only generated once.
+domain: "[N] -> { A[] : N = 0; B[]; C[] : N = 0 }"

diff  --git a/polly/lib/External/isl/test_inputs/codegen/unroll4.c b/polly/lib/External/isl/test_inputs/codegen/unroll4.c
index 6d4c3411f4da..1e7eccccf312 100644
--- a/polly/lib/External/isl/test_inputs/codegen/unroll4.c
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll4.c
@@ -2,14 +2,14 @@
   write_shared_A(3, ((t1 + 3) % 4) + 1, ((t2 + 31) % 32) + 1);
   if (t2 >= 1 && t2 <= 2 && t1 % 3 == 0)
     write_shared_A(3, (-t1 / 3) + 4, t2 + 32);
-  if (((-((t1 + 3) % 4) + t2 + 30) % 32) + t1 >= ((t1 + 3) % 4) + ((t2 + 1) % 2) - 4 * ((-t1 + 4) / 4) + 1)
+  if (((t1 + 3) % 4) + 1 >= t2 || t2 >= ((t1 + 3) % 4) + ((t2 + 1) % 2) + 2)
     write_shared_A(3, ((t1 + 3) % 4) + 5, -((((t1 + 3) % 4) - t2 + 33) % 32) + t1 + 4 * ((-t1 + 4) / 4) + 32);
   if (t1 >= 1 && t2 >= t1 + 1 && t2 <= 4)
     write_shared_A(3, t1 + 4, t2 + 32);
   write_shared_A(4, ((t1 + 3) % 4) + 1, ((t2 + 31) % 32) + 1);
   if (t2 >= 1 && t2 <= 2 && t1 % 3 == 0)
     write_shared_A(4, (-t1 / 3) + 4, t2 + 32);
-  if (((-((t1 + 3) % 4) + t2 + 30) % 32) + t1 >= ((t1 + 3) % 4) + ((t2 + 1) % 2) - 4 * ((-t1 + 4) / 4) + 1)
+  if (((t1 + 3) % 4) + 1 >= t2 || t2 >= ((t1 + 3) % 4) + ((t2 + 1) % 2) + 2)
     write_shared_A(4, ((t1 + 3) % 4) + 5, -((((t1 + 3) % 4) - t2 + 33) % 32) + t1 + 4 * ((-t1 + 4) / 4) + 32);
   if (t1 >= 1 && t2 >= t1 + 1 && t2 <= 4)
     write_shared_A(4, t1 + 4, t2 + 32);

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat1.sc b/polly/lib/External/isl/test_inputs/schedule/flat1.sc
new file mode 100644
index 000000000000..f3cb57f1f68a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat1.sc
@@ -0,0 +1,3 @@
+# Check that a fixed value of one dimension in terms of the others
+# does not cause loop coalescing avoidance to break down.
+domain: [M] -> { S[a, b] : 0 <= a <= 99 and M <= 2b <= 1 + M }

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat1.st b/polly/lib/External/isl/test_inputs/schedule/flat1.st
new file mode 100644
index 000000000000..6b0b54f263c9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat1.st
@@ -0,0 +1,5 @@
+domain: "[M] -> { S[a, b] : 0 <= a <= 99 and M <= 2b <= 1 + M }"
+child:
+  schedule: "[M] -> [{ S[a, b] -> [(a)] }]"
+  permutable: 1
+  coincident: [ 1 ]

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat2.sc b/polly/lib/External/isl/test_inputs/schedule/flat2.sc
new file mode 100644
index 000000000000..bf5042cfb4e2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat2.sc
@@ -0,0 +1,3 @@
+# Check that a fixed value of one dimension in terms of the others
+# does not cause loop coalescing avoidance to break down.
+domain: { S[a, floor(a/2)] : 0 <= a <= 9 }

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat2.st b/polly/lib/External/isl/test_inputs/schedule/flat2.st
new file mode 100644
index 000000000000..83f0838d44a4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat2.st
@@ -0,0 +1,5 @@
+domain: "{ S[a, i1] : 0 <= a <= 9 and -1 + a <= 2i1 <= a }"
+child:
+  schedule: "[{ S[a, i1] -> [(a)] }]"
+  permutable: 1
+  coincident: [ 1 ]

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat3.sc b/polly/lib/External/isl/test_inputs/schedule/flat3.sc
new file mode 100644
index 000000000000..86e296ef7863
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat3.sc
@@ -0,0 +1,3 @@
+# Check that a fixed value of one dimension in terms of the others
+# does not cause loop coalescing avoidance to break down.
+domain: { S[a, floor(a/2), floor(a/4)] : 0 <= a <= 9 }

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat3.st b/polly/lib/External/isl/test_inputs/schedule/flat3.st
new file mode 100644
index 000000000000..eea2ea4dc017
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat3.st
@@ -0,0 +1,5 @@
+domain: "{ S[a, i1, i2] : 0 <= a <= 9 and -1 + a <= 2i1 <= a and -3 + a <= 4i2 <= a }"
+child:
+  schedule: "[{ S[a, i1, i2] -> [(a)] }]"
+  permutable: 1
+  coincident: [ 1 ]

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat4.sc b/polly/lib/External/isl/test_inputs/schedule/flat4.sc
new file mode 100644
index 000000000000..3c094b06b4e2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat4.sc
@@ -0,0 +1,3 @@
+# Check that a fixed value of one dimension in terms of the others
+# does not cause loop coalescing avoidance to break down.
+domain: { S[0, a, floor(a/2), floor(a/4)] : 0 <= a <= 9 }

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat4.st b/polly/lib/External/isl/test_inputs/schedule/flat4.st
new file mode 100644
index 000000000000..bef33ca20058
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat4.st
@@ -0,0 +1,5 @@
+domain: "{ S[0, a, i2, i3] : 0 <= a <= 9 and -1 + a <= 2i2 <= a and -3 + a <= 4i3 <= a }"
+child:
+  schedule: "[{ S[i0, a, i2, i3] -> [(a)] }]"
+  permutable: 1
+  coincident: [ 1 ]

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat5.sc b/polly/lib/External/isl/test_inputs/schedule/flat5.sc
new file mode 100644
index 000000000000..fdee69a46d72
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat5.sc
@@ -0,0 +1,3 @@
+# Check that a fixed value of one dimension in terms of the others
+# does not cause loop coalescing avoidance to break down.
+domain: { S[a, b] : b >= 0 and a -10b >= 0 and -a + b + 9 >= 0 }

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat5.st b/polly/lib/External/isl/test_inputs/schedule/flat5.st
new file mode 100644
index 000000000000..de01551c3ed1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat5.st
@@ -0,0 +1,5 @@
+domain: "{ S[a, b] : b >= -9 + a and b >= 0 and 10b <= a }"
+child:
+  schedule: "[{ S[a, b] -> [(a)] }]"
+  permutable: 1
+  coincident: [ 1 ]

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat6.sc b/polly/lib/External/isl/test_inputs/schedule/flat6.sc
new file mode 100644
index 000000000000..c78919c7f02a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat6.sc
@@ -0,0 +1,3 @@
+# Check that a fixed value of one dimension in terms of the others
+# does not cause loop coalescing avoidance to break down.
+domain: { S[a, b] : -b >= 0 and a + 10b >= 0 and -a - b + 9 >= 0 }

diff  --git a/polly/lib/External/isl/test_inputs/schedule/flat6.st b/polly/lib/External/isl/test_inputs/schedule/flat6.st
new file mode 100644
index 000000000000..9ee10273ca6b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/flat6.st
@@ -0,0 +1,5 @@
+domain: "{ S[a, b] : b <= 9 - a and b <= 0 and 10b >= -a }"
+child:
+  schedule: "[{ S[a, b] -> [(a)] }]"
+  permutable: 1
+  coincident: [ 1 ]

diff  --git a/polly/lib/External/isl/test_inputs/schedule/poliwoda.sc b/polly/lib/External/isl/test_inputs/schedule/poliwoda.sc
new file mode 100644
index 000000000000..cd669fa247d1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/poliwoda.sc
@@ -0,0 +1,47 @@
+# In earlier versions of isl, this test case would cause
+# the loop coalescing avoidance to break down because one of the dimensions
+# (Id2 in S_1) has a fixed value in terms of the other dimensions.
+# Check that this no longer happens.
+# The actual schedule that is produced is not that important,
+# but it is 
diff erent depending on whether the whole-component scheduler
+# is being used, so pick a particular setting.
+# OPTIONS: --schedule-whole-component
+domain: [_PB_M, _PB_N] -> { S_0[Id1, Id2, Id3] : _PB_M >= 2 and Id1 >=
+0 and 4Id1 < _PB_N and 2Id2 >= -_PB_M and 4Id2 <= -_PB_M and Id3 <=
+0 and 4Id3 >= -3 + _PB_M + 4Id2 and 4Id3 >= -1 - _PB_M; S_1[Id1, Id2,
+Id3] : _PB_M >= 2 and Id1 >= 0 and 4Id1 < _PB_N and -_PB_M <= 2Id2 <=
+1 - _PB_M and Id3 <= 0 and 4Id3 >= -1 - _PB_M }
+validity: [_PB_M, _PB_N] -> { S_0[Id1, Id2, Id3] -> S_0[Id1' = Id1, Id2',
+Id3'] : Id1 >= 0 and 4Id1 < _PB_N and Id3 <= 0 and 4Id3 >= -3 + _PB_M +
+4Id2 and Id2' <= Id2 and 2Id2' >= -_PB_M and Id3' < 0 and Id3' <= Id3
+and Id3' < Id2 + Id3 - Id2' and 4Id3' >= -4 + _PB_M + 4Id2 and 4Id3' >=
+-3 + _PB_M + 3Id2 + Id2' and -1 - _PB_M <= 4Id3' <= 2 + _PB_M + 4Id2;
+S_0[Id1, Id2, Id3] -> S_0[Id1' = Id1, Id2', Id3' = Id3] : Id1 >= 0 and
+4Id1 < _PB_N and 4Id2 <= -_PB_M and Id3 <= 0 and 4Id3 >= -3 + _PB_M +
+4Id2 and Id2' < Id2 and 2Id2' >= -_PB_M; S_0[Id1, Id2, Id3] -> S_1[Id1'
+= Id1, Id2', Id3'] : Id1 >= 0 and 4Id1 < _PB_N and Id3 <= 0 and 4Id3 >=
+-3 + _PB_M + 4Id2 and Id2' < Id2 and -_PB_M <= 2Id2' <= 1 - _PB_M and
+Id3' < 0 and Id3' <= Id3 and -4 + _PB_M + 4Id2 <= 4Id3' <= 2 + _PB_M +
+4Id2; S_0[Id1, Id2, Id3] -> S_1[Id1' = Id1, Id2' = Id2, Id3'] : Id1 >=
+0 and 4Id1 < _PB_N and -_PB_M <= 2Id2 <= 1 - _PB_M and Id3 <= 0 and Id3'
+< Id3 and -1 - _PB_M <= 4Id3' <= 2 + _PB_M + 4Id2; S_0[Id1, Id2, Id3]
+-> S_1[Id1' = Id1, Id2', Id3' = Id3] : Id1 >= 0 and 4Id1 < _PB_N and
+4Id2 <= -_PB_M and Id3 <= 0 and 4Id3 >= -3 + _PB_M + 4Id2 and Id2' <
+Id2 and -_PB_M <= 2Id2' <= 1 - _PB_M }
+proximity: [_PB_M, _PB_N] -> { S_0[Id1, Id2, Id3] -> S_0[Id1' = Id1, Id2',
+Id3'] : Id1 >= 0 and 4Id1 < _PB_N and Id3 <= 0 and 4Id3 >= -3 + _PB_M +
+4Id2 and Id2' <= Id2 and 2Id2' >= -_PB_M and Id3' < 0 and Id3' <= Id3
+and Id3' < Id2 + Id3 - Id2' and 4Id3' >= -4 + _PB_M + 4Id2 and 4Id3' >=
+-3 + _PB_M + 3Id2 + Id2' and -1 - _PB_M <= 4Id3' <= 2 + _PB_M + 4Id2;
+S_0[Id1, Id2, Id3] -> S_0[Id1' = Id1, Id2', Id3' = Id3] : Id1 >= 0 and
+4Id1 < _PB_N and 4Id2 <= -_PB_M and Id3 <= 0 and 4Id3 >= -3 + _PB_M +
+4Id2 and Id2' < Id2 and 2Id2' >= -_PB_M; S_0[Id1, Id2, Id3] -> S_1[Id1'
+= Id1, Id2', Id3'] : Id1 >= 0 and 4Id1 < _PB_N and Id3 <= 0 and 4Id3 >=
+-3 + _PB_M + 4Id2 and Id2' < Id2 and -_PB_M <= 2Id2' <= 1 - _PB_M and
+Id3' < 0 and Id3' <= Id3 and -4 + _PB_M + 4Id2 <= 4Id3' <= 2 + _PB_M +
+4Id2; S_0[Id1, Id2, Id3] -> S_1[Id1' = Id1, Id2' = Id2, Id3'] : Id1 >=
+0 and 4Id1 < _PB_N and -_PB_M <= 2Id2 <= 1 - _PB_M and Id3 <= 0 and Id3'
+< Id3 and -1 - _PB_M <= 4Id3' <= 2 + _PB_M + 4Id2; S_0[Id1, Id2, Id3]
+-> S_1[Id1' = Id1, Id2', Id3' = Id3] : Id1 >= 0 and 4Id1 < _PB_N and
+4Id2 <= -_PB_M and Id3 <= 0 and 4Id3 >= -3 + _PB_M + 4Id2 and Id2' <
+Id2 and -_PB_M <= 2Id2' <= 1 - _PB_M }

diff  --git a/polly/lib/External/isl/test_inputs/schedule/poliwoda.st b/polly/lib/External/isl/test_inputs/schedule/poliwoda.st
new file mode 100644
index 000000000000..d9a07a61e167
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/schedule/poliwoda.st
@@ -0,0 +1,5 @@
+domain: "[_PB_M, _PB_N] -> { S_0[Id1, Id2, Id3] : _PB_M >= 2 and Id1 >= 0 and 4Id1 < _PB_N and 2Id2 >= -_PB_M and 4Id2 <= -_PB_M and Id3 <= 0 and 4Id3 >= -3 + _PB_M + 4Id2 and 4Id3 >= -1 - _PB_M; S_1[Id1, Id2, Id3] : _PB_M >= 2 and Id1 >= 0 and 4Id1 < _PB_N and -_PB_M <= 2Id2 <= 1 - _PB_M and Id3 <= 0 and 4Id3 >= -1 - _PB_M }"
+child:
+  schedule: "[_PB_M, _PB_N] -> [{ S_0[Id1, Id2, Id3] -> [(Id1)]; S_1[Id1, Id2, Id3] -> [(Id1)] }, { S_0[Id1, Id2, Id3] -> [(-Id2)]; S_1[Id1, Id2, Id3] -> [(_PB_M)] }, { S_0[Id1, Id2, Id3] -> [(-Id3)]; S_1[Id1, Id2, Id3] -> [(-Id3)] }]"
+  permutable: 1
+  coincident: [ 1, 1, 1 ]

diff  --git a/polly/lib/Transform/ForwardOpTree.cpp b/polly/lib/Transform/ForwardOpTree.cpp
index 1cb904b742d9..a373a4e49b78 100644
--- a/polly/lib/Transform/ForwardOpTree.cpp
+++ b/polly/lib/Transform/ForwardOpTree.cpp
@@ -861,8 +861,10 @@ class ForwardOpTreeImpl : ZoneAlgorithm {
       }
     }
 
-    if (Modified)
+    if (Modified) {
       ScopsModified++;
+      S->realignParams();
+    }
     return Modified;
   }
 

diff  --git a/polly/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll b/polly/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll
index ccf0b854f65d..1f298ce45995 100644
--- a/polly/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll
+++ b/polly/test/ScopInfo/aliasing_many_parameters_not_all_involved.ll
@@ -1,5 +1,5 @@
-; RUN: opt %loadPolly -polly-scops -polly-rtc-max-parameters=8 -analyze < %s | FileCheck %s --check-prefix=MAX8
-; RUN: opt %loadPolly -polly-scops -polly-rtc-max-parameters=7 -analyze < %s | FileCheck %s --check-prefix=MAX7
+; RUN: opt %loadPolly -polly-analysis-computeout=0 -polly-scops -polly-rtc-max-parameters=8 -analyze < %s | FileCheck %s --check-prefix=MAX8
+; RUN: opt %loadPolly -polly-analysis-computeout=0 -polly-scops -polly-rtc-max-parameters=7 -analyze < %s | FileCheck %s --check-prefix=MAX7
 ;
 ; Check that we allow this SCoP even though it has 10 parameters involved in posisbly aliasing accesses.
 ; However, only 7 are involved in accesses through B, 8 through C and none in accesses through A.


        


More information about the llvm-commits mailing list