Update to isl-0.20-65-gb822a210

This update fixes https://https:/llvm.org/PR38348. Thanks Michael for
reporting the issue to isl and Sven for fixing the issue.

git-svn-id: https://llvm.org/svn/llvm-project/polly/trunk@339311 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/External/isl/GIT_HEAD_ID b/lib/External/isl/GIT_HEAD_ID
index 0ad5ed4..c977f09 100644
--- a/lib/External/isl/GIT_HEAD_ID
+++ b/lib/External/isl/GIT_HEAD_ID
@@ -1 +1 @@
-isl-0.20-48-g13eba5b5
+isl-0.20-65-gb822a210
diff --git a/lib/External/isl/doc/user.pod b/lib/External/isl/doc/user.pod
index 18831d2..c8e57b5 100644
--- a/lib/External/isl/doc/user.pod
+++ b/lib/External/isl/doc/user.pod
@@ -795,6 +795,7 @@
 On integer values, we additionally have the following operations.
 
 	#include <isl/val.h>
+	__isl_give isl_val *isl_val_pow2(__isl_take isl_val *v);
 	__isl_give isl_val *isl_val_2exp(__isl_take isl_val *v);
 	__isl_give isl_val *isl_val_mod(__isl_take isl_val *v1,
 		__isl_take isl_val *v2);
@@ -804,6 +805,7 @@
 		__isl_take isl_val *v2, __isl_give isl_val **x,
 		__isl_give isl_val **y);
 
+C<isl_val_2exp> is an alternative name for C<isl_val_pow2>.
 The function C<isl_val_gcdext> returns the greatest common divisor g
 of C<v1> and C<v2> as well as two integers C<*x> and C<*y> such
 that C<*x> * C<v1> + C<*y> * C<v2> = g.
@@ -5128,6 +5130,17 @@
 	int isl_options_get_coalesce_bounded_wrapping(
 		isl_ctx *ctx);
 
+One of the other methods tries to combine pairs of basic sets
+with different local variables, treating them as existentially
+quantified variables even if they have known (but different)
+integer division expressions.  The result may then also have
+existentially quantified variables.  Turning on the following
+option prevents this from happening.
+
+	isl_stat isl_options_set_coalesce_preserve_locals(
+		isl_ctx *ctx, int val);
+	int isl_options_get_coalesce_preserve_locals(isl_ctx *ctx);
+
 =item * Detecting equalities
 
 	__isl_give isl_basic_set *isl_basic_set_detect_equalities(
diff --git a/lib/External/isl/include/isl/cpp-checked.h b/lib/External/isl/include/isl/cpp-checked.h
index aaa51a2..1cd0506 100644
--- a/lib/External/isl/include/isl/cpp-checked.h
+++ b/lib/External/isl/include/isl/cpp-checked.h
@@ -1200,6 +1200,7 @@
   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;
@@ -4852,6 +4853,12 @@
   return manage(res);
 }
 
+val val::pow2() const
+{
+  auto res = isl_val_pow2(copy());
+  return manage(res);
+}
+
 int val::sgn() const
 {
   auto res = isl_val_sgn(get());
diff --git a/lib/External/isl/include/isl/cpp.h b/lib/External/isl/include/isl/cpp.h
index 3062d0f..de0da10 100644
--- a/lib/External/isl/include/isl/cpp.h
+++ b/lib/External/isl/include/isl/cpp.h
@@ -1322,6 +1322,7 @@
   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;
@@ -1356,7 +1357,7 @@
   auto ctx = isl_aff_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -1636,7 +1637,7 @@
   auto ctx = isl_ast_build_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -1808,7 +1809,7 @@
   auto ctx = isl_ast_expr_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -1888,7 +1889,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -1968,7 +1969,7 @@
   auto ctx = isl_basic_map_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -2284,7 +2285,7 @@
   auto ctx = isl_basic_set_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -2575,7 +2576,7 @@
   auto ctx = isl_map_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -2779,7 +2780,7 @@
     std::rethrow_exception(fn_data.eptr);
   if (res < 0)
     exception::throw_last_error(ctx);
-  return void(res);
+  return;
 }
 
 map map::gist(map context) const
@@ -3074,7 +3075,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -3221,7 +3222,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -3414,7 +3415,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -3572,7 +3573,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -3688,7 +3689,7 @@
   auto ctx = isl_point_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -3757,7 +3758,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -4144,7 +4145,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -4326,7 +4327,7 @@
   auto ctx = isl_schedule_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -4438,7 +4439,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -4682,7 +4683,7 @@
   auto ctx = isl_schedule_node_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -4846,7 +4847,7 @@
   auto ctx = isl_set_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -5013,7 +5014,7 @@
     std::rethrow_exception(fn_data.eptr);
   if (res < 0)
     exception::throw_last_error(ctx);
-  return void(res);
+  return;
 }
 
 val set::get_stride(int pos) const
@@ -5296,7 +5297,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -5447,7 +5448,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -5587,7 +5588,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -5886,7 +5887,7 @@
     std::rethrow_exception(fn_data.eptr);
   if (res < 0)
     exception::throw_last_error(ctx);
-  return void(res);
+  return;
 }
 
 union_map union_map::from(union_pw_multi_aff upma)
@@ -6361,7 +6362,7 @@
   auto ctx = isl_union_pw_aff_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -6484,7 +6485,7 @@
   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 (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -6630,7 +6631,7 @@
   auto ctx = isl_union_set_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -6796,7 +6797,7 @@
     std::rethrow_exception(fn_data.eptr);
   if (res < 0)
     exception::throw_last_error(ctx);
-  return void(res);
+  return;
 }
 
 void union_set::foreach_set(const std::function<void(set)> &fn) const
@@ -6824,7 +6825,7 @@
     std::rethrow_exception(fn_data.eptr);
   if (res < 0)
     exception::throw_last_error(ctx);
-  return void(res);
+  return;
 }
 
 union_set union_set::gist(union_set context) const
@@ -7083,7 +7084,7 @@
   auto ctx = isl_val_get_ctx(obj.ptr);
   options_scoped_set_on_error saved_on_error(ctx, exception::on_error);
   ptr = obj.copy();
-  if (obj.ptr && !ptr)
+  if (!ptr)
     exception::throw_last_error(ctx);
 }
 
@@ -7578,6 +7579,18 @@
   return manage(res);
 }
 
+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);
+  auto res = isl_val_pow2(copy());
+  if (!res)
+    exception::throw_last_error(ctx);
+  return manage(res);
+}
+
 int val::sgn() const
 {
   if (!ptr)
diff --git a/lib/External/isl/include/isl/options.h b/lib/External/isl/include/isl/options.h
index c09dee6..1738155 100644
--- a/lib/External/isl/include/isl/options.h
+++ b/lib/External/isl/include/isl/options.h
@@ -46,6 +46,9 @@
 isl_stat isl_options_set_coalesce_bounded_wrapping(isl_ctx *ctx, int val);
 int isl_options_get_coalesce_bounded_wrapping(isl_ctx *ctx);
 
+isl_stat isl_options_set_coalesce_preserve_locals(isl_ctx *ctx, int val);
+int isl_options_get_coalesce_preserve_locals(isl_ctx *ctx);
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/lib/External/isl/include/isl/space.h b/lib/External/isl/include/isl/space.h
index deb592b..40a333e 100644
--- a/lib/External/isl/include/isl/space.h
+++ b/lib/External/isl/include/isl/space.h
@@ -79,7 +79,7 @@
 __isl_give isl_space *isl_space_move_dims(__isl_take isl_space *space,
 	enum isl_dim_type dst_type, unsigned dst_pos,
 	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
-__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *space,
 	enum isl_dim_type type, unsigned pos, unsigned n);
 __isl_give isl_space *isl_space_join(__isl_take isl_space *left,
 	__isl_take isl_space *right);
diff --git a/lib/External/isl/include/isl/val.h b/lib/External/isl/include/isl/val.h
index aacad39..faf3e15 100644
--- a/lib/External/isl/include/isl/val.h
+++ b/lib/External/isl/include/isl/val.h
@@ -64,6 +64,8 @@
 __isl_give isl_val *isl_val_trunc(__isl_take isl_val *v);
 __isl_give isl_val *isl_val_2exp(__isl_take isl_val *v);
 __isl_export
+__isl_give isl_val *isl_val_pow2(__isl_take isl_val *v);
+__isl_export
 __isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2);
 __isl_export
 __isl_give isl_val *isl_val_max(__isl_take isl_val *v1, __isl_take isl_val *v2);
diff --git a/lib/External/isl/interface/cpp.cc b/lib/External/isl/interface/cpp.cc
index 67deece..a52e6fe 100644
--- a/lib/External/isl/interface/cpp.cc
+++ b/lib/External/isl/interface/cpp.cc
@@ -448,6 +448,50 @@
 	osprintf(os, "    exception::throw_NULL_input(__FILE__, __LINE__);\n");
 }
 
+/* Print code that checks that "ptr" is not NULL at input.
+ *
+ * Omit the check if checked C++ bindings are being generated.
+ */
+void cpp_generator::print_check_ptr(ostream &os, const char *ptr)
+{
+	if (checked)
+		return;
+
+	osprintf(os, "  if (!%s)\n", ptr);
+	print_throw_NULL_input(os);
+}
+
+/* Print code that checks that "ptr" is not NULL at input and
+ * that saves a copy of the isl_ctx of "ptr" for a later check.
+ *
+ * Omit the check if checked C++ bindings are being generated.
+ */
+void cpp_generator::print_check_ptr_start(ostream &os, const isl_class &clazz,
+	const char *ptr)
+{
+	if (checked)
+		return;
+
+	print_check_ptr(os, ptr);
+	osprintf(os, "  auto ctx = %s_get_ctx(%s);\n", clazz.name.c_str(), ptr);
+	print_on_error_continue(os);
+}
+
+/* Print code that checks that "ptr" is not NULL at the end.
+ * A copy of the isl_ctx is expected to have been saved by
+ * code generated by print_check_ptr_start.
+ *
+ * Omit the check if checked C++ bindings are being generated.
+ */
+void cpp_generator::print_check_ptr_end(ostream &os, const char *ptr)
+{
+	if (checked)
+		return;
+
+	osprintf(os, "  if (!%s)\n", ptr);
+	print_throw_last_error(os);
+}
+
 /* Print implementation of global factory functions to "os".
  *
  * Each class has two global factory functions:
@@ -470,26 +514,15 @@
 	const char *cppname = cppstring.c_str();
 
 	osprintf(os, "%s manage(__isl_take %s *ptr) {\n", cppname, name);
-	if (!checked) {
-		osprintf(os, "  if (!ptr)\n");
-		print_throw_NULL_input(os);
-	}
+	print_check_ptr(os, "ptr");
 	osprintf(os, "  return %s(ptr);\n", cppname);
 	osprintf(os, "}\n");
 
 	osprintf(os, "%s manage_copy(__isl_keep %s *ptr) {\n", cppname,
 		name);
-	if (!checked) {
-		osprintf(os, "  if (!ptr)\n");
-		print_throw_NULL_input(os);
-		osprintf(os, "  auto ctx = %s_get_ctx(ptr);\n", name);
-		print_on_error_continue(os);
-	}
+	print_check_ptr_start(os, clazz, "ptr");
 	osprintf(os, "  ptr = %s_copy(ptr);\n", name);
-	if (!checked) {
-		osprintf(os, "  if (!ptr)\n");
-		print_throw_last_error(os);
-	}
+	print_check_ptr_end(os, "ptr");
 	osprintf(os, "  return %s(ptr);\n", cppname);
 	osprintf(os, "}\n");
 }
@@ -519,7 +552,6 @@
 void cpp_generator::print_public_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();
 
@@ -527,17 +559,9 @@
 	osprintf(os, "%s::%s(const %s &obj)\n    : ptr(nullptr)\n",
 		 cppname, cppname, cppname);
 	osprintf(os, "{\n");
-	if (!checked) {
-		osprintf(os, "  if (!obj.ptr)\n");
-		print_throw_NULL_input(os);
-		osprintf(os, "  auto ctx = %s_get_ctx(obj.ptr);\n", name);
-		print_on_error_continue(os);
-	}
+	print_check_ptr_start(os, clazz, "obj.ptr");
 	osprintf(os, "  ptr = obj.copy();\n");
-	if (!checked) {
-		osprintf(os, "  if (obj.ptr && !ptr)\n");
-		print_throw_last_error(os);
-	}
+	print_check_ptr_end(os, "ptr");
 	osprintf(os, "}\n");
 }
 
@@ -879,16 +903,10 @@
 	print_throw_last_error(os);
 }
 
-/* Print definition for "method" in class "clazz" to "os".
+/* Print the return statement of the C++ method corresponding
+ * to the C function "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. The result of the isl function is returned as a new
+ * The result of the isl function is returned as a new
  * object if the underlying isl function returns an isl_* ptr, as a bool
  * if the isl function returns an isl_bool, as void if the isl functions
  * returns an isl_stat,
@@ -898,6 +916,38 @@
  * 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.
+ */
+void cpp_generator::print_method_return(ostream &os, const isl_class &clazz,
+	FunctionDecl *method)
+{
+	QualType return_type = method->getReturnType();
+
+	if (is_isl_type(return_type) ||
+		    (checked &&
+		     (is_isl_bool(return_type) || is_isl_stat(return_type)))) {
+		osprintf(os, "  return manage(res);\n");
+	} else if (is_isl_stat(return_type)) {
+		osprintf(os, "  return;\n");
+	} else if (is_string(return_type)) {
+		osprintf(os, "  std::string tmp(res);\n");
+		if (gives(method))
+			osprintf(os, "  free(res);\n");
+		osprintf(os, "  return tmp;\n");
+	} else {
+		osprintf(os, "  return res;\n");
+	}
+}
+
+/* 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
@@ -925,9 +975,6 @@
 {
 	string methodname = method->getName();
 	int num_params = method->getNumParams();
-	QualType return_type = method->getReturnType();
-	string rettype_str = type2cpp(return_type);
-	bool has_callback = false;
 
 	print_method_header(os, clazz, method, false, kind);
 	osprintf(os, "{\n");
@@ -938,7 +985,6 @@
 	for (int i = 0; i < num_params; ++i) {
 		ParmVarDecl *param = method->getParamDecl(i);
 		if (is_callback(param->getType())) {
-			has_callback = true;
 			num_params -= 1;
 			print_callback_local(os, param);
 		}
@@ -963,19 +1009,8 @@
 	print_exceptional_execution_check(os, method);
 	if (kind == function_kind_constructor) {
 		osprintf(os, "  ptr = res;\n");
-	} else if (is_isl_type(return_type) ||
-		    (checked &&
-		     (is_isl_bool(return_type) || is_isl_stat(return_type)))) {
-		osprintf(os, "  return manage(res);\n");
-	} else if (has_callback) {
-		osprintf(os, "  return %s(res);\n", rettype_str.c_str());
-	} else if (is_string(return_type)) {
-		osprintf(os, "  std::string tmp(res);\n");
-		if (gives(method))
-			osprintf(os, "  free(res);\n");
-		osprintf(os, "  return tmp;\n");
 	} else {
-		osprintf(os, "  return res;\n");
+		print_method_return(os, clazz, method);
 	}
 
 	osprintf(os, "}\n");
@@ -1109,7 +1144,7 @@
 	const FunctionProtoType *callback;
 	int num_params;
 
-	callback = type->getPointeeType()->getAs<FunctionProtoType>();
+	callback = extract_prototype(type);
 	num_params = callback->getNumArgs();
 	if (cpp)
 		num_params--;
@@ -1145,7 +1180,7 @@
 string cpp_generator::generate_callback_type(QualType type)
 {
 	std::string type_str;
-	const FunctionProtoType *callback = type->getPointeeType()->getAs<FunctionProtoType>();
+	const FunctionProtoType *callback = extract_prototype(type);
 	QualType return_type = callback->getReturnType();
 	string rettype_str = type2cpp(return_type);
 
@@ -1271,7 +1306,7 @@
 	c_args = generate_callback_args(ptype, false);
 	cpp_args = generate_callback_type(ptype);
 
-	callback = ptype->getPointeeType()->getAs<FunctionProtoType>();
+	callback = extract_prototype(ptype);
 	rettype = callback->getReturnType().getAsString();
 	num_params = callback->getNumArgs();
 
diff --git a/lib/External/isl/interface/cpp.h b/lib/External/isl/interface/cpp.h
index b46d37f..0e97c71 100644
--- a/lib/External/isl/interface/cpp.h
+++ b/lib/External/isl/interface/cpp.h
@@ -50,6 +50,10 @@
 		FunctionDecl *method, function_kind kind);
 	void print_implementations(ostream &os);
 	void print_class_impl(ostream &os, const isl_class &clazz);
+	void print_check_ptr(ostream &os, const char *ptr);
+	void print_check_ptr_start(ostream &os, const isl_class &clazz,
+		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,
 		const isl_class &clazz);
@@ -70,6 +74,8 @@
 	void print_on_error_continue(ostream &os);
 	void print_exceptional_execution_check(ostream &os,
 		FunctionDecl *method);
+	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_method_param_use(ostream &os, ParmVarDecl *param,
diff --git a/lib/External/isl/interface/generator.cc b/lib/External/isl/interface/generator.cc
index c357285..fee2347 100644
--- a/lib/External/isl/interface/generator.cc
+++ b/lib/External/isl/interface/generator.cc
@@ -110,13 +110,14 @@
 
 	for (in = exported_functions.begin(); in != exported_functions.end();
 	     ++in) {
-		isl_class *c = method2class(*in);
+		FunctionDecl *method = *in;
+		isl_class *c = method2class(method);
+
 		if (!c)
 			continue;
-		if (is_constructor(*in)) {
-			c->constructors.insert(*in);
+		if (is_constructor(method)) {
+			c->constructors.insert(method);
 		} else {
-			FunctionDecl *method = *in;
 			string fullname = c->name_without_type_suffix(method);
 			c->methods[fullname].insert(method);
 		}
@@ -412,6 +413,14 @@
 	die("Cannot extract type from non-pointer type");
 }
 
+/* Given the type of a function pointer, return the corresponding
+ * function prototype.
+ */
+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.
  * Otherwise, simply return the name of the function.
diff --git a/lib/External/isl/interface/generator.h b/lib/External/isl/interface/generator.h
index 8195a36..2f8d88d 100644
--- a/lib/External/isl/interface/generator.h
+++ b/lib/External/isl/interface/generator.h
@@ -75,6 +75,7 @@
 	static bool is_string(QualType type);
 	static bool is_static(const isl_class &clazz, FunctionDecl *method);
 	static string extract_type(QualType type);
+	static const FunctionProtoType *extract_prototype(QualType type);
 };
 
 #endif /* ISL_INTERFACE_GENERATOR_H */
diff --git a/lib/External/isl/interface/isl.py b/lib/External/isl/interface/isl.py
index e6bdc75..11c18b5 100644
--- a/lib/External/isl/interface/isl.py
+++ b/lib/External/isl/interface/isl.py
@@ -5523,6 +5523,15 @@
         ctx = Context.getDefaultInstance()
         res = isl.isl_val_one(ctx)
         return val(ctx=ctx, ptr=res)
+    def pow2(arg0):
+        try:
+            if not arg0.__class__ is val:
+                arg0 = val(arg0)
+        except:
+            raise
+        ctx = arg0.ctx
+        res = isl.isl_val_pow2(isl.isl_val_copy(arg0.ptr))
+        return val(ctx=ctx, ptr=res)
     def sgn(arg0):
         try:
             if not arg0.__class__ is val:
@@ -5640,6 +5649,8 @@
 isl.isl_val_negone.argtypes = [Context]
 isl.isl_val_one.restype = c_void_p
 isl.isl_val_one.argtypes = [Context]
+isl.isl_val_pow2.restype = c_void_p
+isl.isl_val_pow2.argtypes = [c_void_p]
 isl.isl_val_sgn.argtypes = [c_void_p]
 isl.isl_val_sub.restype = c_void_p
 isl.isl_val_sub.argtypes = [c_void_p, c_void_p]
diff --git a/lib/External/isl/interface/python.cc b/lib/External/isl/interface/python.cc
index 33a96c2..7e6fd18 100644
--- a/lib/External/isl/interface/python.cc
+++ b/lib/External/isl/interface/python.cc
@@ -126,8 +126,8 @@
  */
 void python_generator::print_callback(ParmVarDecl *param, int arg)
 {
-	QualType type = param->getOriginalType()->getPointeeType();
-	const FunctionProtoType *fn = type->getAs<FunctionProtoType>();
+	QualType type = param->getOriginalType();
+	const FunctionProtoType *fn = extract_prototype(type);
 	unsigned n_arg = fn->getNumArgs();
 
 	printf("        exc_info = [None]\n");
diff --git a/lib/External/isl/isl_ast_codegen.c b/lib/External/isl/isl_ast_codegen.c
index 5175b89..1dcc9f2 100644
--- a/lib/External/isl/isl_ast_codegen.c
+++ b/lib/External/isl/isl_ast_codegen.c
@@ -21,6 +21,7 @@
 #include <isl/union_set.h>
 #include <isl/union_map.h>
 #include <isl/schedule_node.h>
+#include <isl/options.h>
 #include <isl_sort.h>
 #include <isl_tarjan.h>
 #include <isl_ast_private.h>
@@ -28,6 +29,25 @@
 #include <isl_ast_build_private.h>
 #include <isl_ast_graft_private.h>
 
+/* Try and reduce the number of disjuncts in the representation of "set",
+ * without dropping explicit representations of local variables.
+ */
+static __isl_give isl_set *isl_set_coalesce_preserve(__isl_take isl_set *set)
+{
+	isl_ctx *ctx;
+	int save_preserve;
+
+	if (!set)
+		return NULL;
+
+	ctx = isl_set_get_ctx(set);
+	save_preserve = isl_options_get_coalesce_preserve_locals(ctx);
+	isl_options_set_coalesce_preserve_locals(ctx, 1);
+	set = isl_set_coalesce(set);
+	isl_options_set_coalesce_preserve_locals(ctx, save_preserve);
+	return set;
+}
+
 /* Data used in generate_domain.
  *
  * "build" is the input build.
@@ -144,7 +164,7 @@
 
 	guard = isl_map_domain(isl_map_copy(map));
 	guard = isl_set_compute_divs(guard);
-	guard = isl_set_coalesce(guard);
+	guard = isl_set_coalesce_preserve(guard);
 	guard = isl_set_gist(guard, isl_ast_build_get_generated(build));
 	guard = isl_ast_build_specialize(build, guard);
 
@@ -2841,7 +2861,7 @@
 	}
 
 	domain = isl_ast_build_eliminate(domains->build, domain);
-	domain = isl_set_coalesce(domain);
+	domain = isl_set_coalesce_preserve(domain);
 	bset = isl_set_unshifted_simple_hull(domain);
 	domain = isl_set_from_basic_set(bset);
 	atomic_domain = isl_set_copy(domain);
@@ -2959,7 +2979,7 @@
 	domain = isl_ast_build_eliminate(domains->build, domain);
 	domain = isl_set_intersect(domain, isl_set_copy(class_domain));
 
-	domain = isl_set_coalesce(domain);
+	domain = isl_set_coalesce_preserve(domain);
 	domain = isl_set_make_disjoint(domain);
 
 	list = isl_basic_set_list_from_set(domain);
@@ -3316,7 +3336,7 @@
 								build);
 
 	domain = isl_ast_build_eliminate(build, domain);
-	domain = isl_set_coalesce(domain);
+	domain = isl_set_coalesce_preserve(domain);
 
 	outer_disjunction = has_pure_outer_disjunction(domain, build);
 	if (outer_disjunction < 0)
diff --git a/lib/External/isl/isl_coalesce.c b/lib/External/isl/isl_coalesce.c
index 922c47f..1f96b7b 100644
--- a/lib/External/isl/isl_coalesce.c
+++ b/lib/External/isl/isl_coalesce.c
@@ -3684,12 +3684,20 @@
  * an obvious subset of the other or if the extra integer divisions
  * of one basic map can be simplified away using the extra equalities
  * of the other basic map.
+ *
+ * Note that trying to coalesce pairs of disjuncts with the same
+ * number, but different local variables may drop the explicit
+ * representation of some of these local variables.
+ * This operation is therefore not performed when
+ * the "coalesce_preserve_locals" option is set.
  */
 static enum isl_change coalesce_pair(int i, int j,
 	struct isl_coalesce_info *info)
 {
+	int preserve;
 	isl_bool same;
 	enum isl_change change;
+	isl_ctx *ctx;
 
 	if (harmonize_divs(&info[i], &info[j]) < 0)
 		return isl_change_error;
@@ -3699,7 +3707,9 @@
 	if (same)
 		return coalesce_local_pair(i, j, info);
 
-	if (info[i].bmap->n_div == info[j].bmap->n_div) {
+	ctx = isl_basic_map_get_ctx(info[i].bmap);
+	preserve = isl_options_get_coalesce_preserve_locals(ctx);
+	if (!preserve && info[i].bmap->n_div == info[j].bmap->n_div) {
 		change = coalesce_local_pair(i, j, info);
 		if (change != isl_change_none)
 			return change;
diff --git a/lib/External/isl/isl_map.c b/lib/External/isl/isl_map.c
index 40718b1..592a20b 100644
--- a/lib/External/isl/isl_map.c
+++ b/lib/External/isl/isl_map.c
@@ -3878,7 +3878,7 @@
 	unsigned pos, unsigned n)
 {
 	isl_bool rational;
-	isl_space *res_dim;
+	isl_space *res_space;
 	struct isl_basic_map *res;
 	struct isl_dim_map *dim_map;
 	unsigned total, off;
@@ -3887,10 +3887,10 @@
 	if (n == 0)
 		return basic_map_space_reset(bmap, type);
 
-	if (!bmap)
-		return NULL;
-
-	res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n);
+	res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
+					type, pos, n);
+	if (!res_space)
+		return isl_basic_map_free(bmap);
 
 	total = isl_basic_map_total_dim(bmap) + n;
 	dim_map = isl_dim_map_alloc(bmap->ctx, total);
@@ -3905,11 +3905,11 @@
 			isl_dim_map_dim_range(dim_map, bmap->dim, t,
 						pos, size - pos, off + pos + n);
 		}
-		off += isl_space_dim(res_dim, t);
+		off += isl_space_dim(res_space, t);
 	}
 	isl_dim_map_div(dim_map, bmap, off);
 
-	res = isl_basic_map_alloc_space(res_dim,
+	res = isl_basic_map_alloc_space(res_space,
 			bmap->n_div, bmap->n_eq, bmap->n_ineq);
 	rational = isl_basic_map_is_rational(bmap);
 	if (rational < 0)
diff --git a/lib/External/isl/isl_map_simplify.c b/lib/External/isl/isl_map_simplify.c
index 06806d9..f794556 100644
--- a/lib/External/isl/isl_map_simplify.c
+++ b/lib/External/isl/isl_map_simplify.c
@@ -3057,10 +3057,10 @@
 
 	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;
 
-	context = isl_basic_map_align_divs(context, bmap);
 	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);
diff --git a/lib/External/isl/isl_options.c b/lib/External/isl/isl_options.c
index eb3dd02..ea8fe78 100644
--- a/lib/External/isl/isl_options.c
+++ b/lib/External/isl/isl_options.c
@@ -134,6 +134,9 @@
 	convex,	ISL_CONVEX_HULL_WRAP, "convex hull algorithm to use")
 ISL_ARG_BOOL(struct isl_options, coalesce_bounded_wrapping, 0,
 	"coalesce-bounded-wrapping", 1, "bound wrapping during coalescing")
+ISL_ARG_BOOL(struct isl_options, coalesce_preserve_locals, 0,
+	"coalesce-preserve-locals", 0,
+	"preserve local variables during coalescing")
 ISL_ARG_INT(struct isl_options, schedule_max_coefficient, 0,
 	"schedule-max-coefficient", "limit", -1, "Only consider schedules "
 	"where the coefficients of the variable and parameter dimensions "
@@ -242,6 +245,11 @@
 	coalesce_bounded_wrapping)
 
 ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+	coalesce_preserve_locals)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+	coalesce_preserve_locals)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
 	gbr_only_first)
 ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
 	gbr_only_first)
diff --git a/lib/External/isl/isl_options_private.h b/lib/External/isl/isl_options_private.h
index 13f21a7..3a59d2a 100644
--- a/lib/External/isl/isl_options_private.h
+++ b/lib/External/isl/isl_options_private.h
@@ -34,6 +34,7 @@
 	int			convex;
 
 	int			coalesce_bounded_wrapping;
+	int			coalesce_preserve_locals;
 
 	int			schedule_max_coefficient;
 	int			schedule_max_constant_term;
diff --git a/lib/External/isl/isl_space.c b/lib/External/isl/isl_space.c
index 2a83e80..3a6c2bd 100644
--- a/lib/External/isl/isl_space.c
+++ b/lib/External/isl/isl_space.c
@@ -1019,76 +1019,85 @@
  * If we are inserting parameters, then they are also inserted in
  * any nested spaces.
  */
-__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim,
+__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *space,
 	enum isl_dim_type type, unsigned pos, unsigned n)
 {
+	isl_ctx *ctx;
 	isl_id **ids = NULL;
+	unsigned total;
 
-	if (!dim)
+	if (!space)
 		return NULL;
 	if (n == 0)
-		return isl_space_reset(dim, type);
+		return isl_space_reset(space, type);
 
+	ctx = isl_space_get_ctx(space);
 	if (!valid_dim_type(type))
-		isl_die(dim->ctx, isl_error_invalid,
+		isl_die(ctx, isl_error_invalid,
 			"cannot insert dimensions of specified type",
 			goto error);
 
-	isl_assert(dim->ctx, pos <= isl_space_dim(dim, 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);
 
-	dim = isl_space_cow(dim);
-	if (!dim)
+	space = isl_space_cow(space);
+	if (!space)
 		return NULL;
 
-	if (dim->ids) {
+	if (space->ids) {
 		enum isl_dim_type t, o = isl_dim_param;
 		int off;
 		int s[3];
-		ids = isl_calloc_array(dim->ctx, isl_id *,
-				     dim->nparam + dim->n_in + dim->n_out + n);
+		ids = isl_calloc_array(ctx, isl_id *,
+			     space->nparam + space->n_in + space->n_out + n);
 		if (!ids)
 			goto error;
 		off = 0;
-		s[isl_dim_param - o] = dim->nparam;
-		s[isl_dim_in - o] = dim->n_in;
-		s[isl_dim_out - o] = dim->n_out;
+		s[isl_dim_param - o] = space->nparam;
+		s[isl_dim_in - o] = space->n_in;
+		s[isl_dim_out - o] = space->n_out;
 		for (t = isl_dim_param; t <= isl_dim_out; ++t) {
 			if (t != type) {
-				get_ids(dim, t, 0, s[t - o], ids + off);
+				get_ids(space, t, 0, s[t - o], ids + off);
 				off += s[t - o];
 			} else {
-				get_ids(dim, t, 0, pos, ids + off);
+				get_ids(space, t, 0, pos, ids + off);
 				off += pos + n;
-				get_ids(dim, t, pos, s[t - o] - pos, ids + off);
+				get_ids(space, t, pos, s[t - o] - pos,
+					ids + off);
 				off += s[t - o] - pos;
 			}
 		}
-		free(dim->ids);
-		dim->ids = ids;
-		dim->n_id = dim->nparam + dim->n_in + dim->n_out + n;
+		free(space->ids);
+		space->ids = ids;
+		space->n_id = space->nparam + space->n_in + space->n_out + n;
 	}
 	switch (type) {
-	case isl_dim_param:	dim->nparam += n; break;
-	case isl_dim_in:	dim->n_in += n; break;
-	case isl_dim_out:	dim->n_out += n; break;
+	case isl_dim_param:	space->nparam += n; break;
+	case isl_dim_in:	space->n_in += n; break;
+	case isl_dim_out:	space->n_out += n; 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_insert_dims(dim->nested[0],
+		if (space && space->nested[0] &&
+		    !(space->nested[0] = isl_space_insert_dims(space->nested[0],
 						    isl_dim_param, pos, n)))
 			goto error;
-		if (dim && dim->nested[1] &&
-		    !(dim->nested[1] = isl_space_insert_dims(dim->nested[1],
+		if (space && space->nested[1] &&
+		    !(space->nested[1] = isl_space_insert_dims(space->nested[1],
 						    isl_dim_param, pos, n)))
 			goto error;
 	}
 
-	return dim;
+	return space;
 error:
-	isl_space_free(dim);
+	isl_space_free(space);
 	return NULL;
 }
 
diff --git a/lib/External/isl/isl_test.c b/lib/External/isl/isl_test.c
index 5633620..d08870d 100644
--- a/lib/External/isl/isl_test.c
+++ b/lib/External/isl/isl_test.c
@@ -679,7 +679,7 @@
 } val_un_tests[] = {
 	{ &isl_val_neg, "0", "0" },
 	{ &isl_val_abs, "0", "0" },
-	{ &isl_val_2exp, "0", "1" },
+	{ &isl_val_pow2, "0", "1" },
 	{ &isl_val_floor, "0", "0" },
 	{ &isl_val_ceil, "0", "0" },
 	{ &isl_val_neg, "1", "-1" },
@@ -710,11 +710,11 @@
 	{ &isl_val_ceil, "infty", "infty" },
 	{ &isl_val_ceil, "-infty", "-infty" },
 	{ &isl_val_ceil, "NaN", "NaN" },
-	{ &isl_val_2exp, "-3", "1/8" },
-	{ &isl_val_2exp, "-1", "1/2" },
-	{ &isl_val_2exp, "1", "2" },
-	{ &isl_val_2exp, "2", "4" },
-	{ &isl_val_2exp, "3", "8" },
+	{ &isl_val_pow2, "-3", "1/8" },
+	{ &isl_val_pow2, "-1", "1/2" },
+	{ &isl_val_pow2, "1", "2" },
+	{ &isl_val_pow2, "2", "4" },
+	{ &isl_val_pow2, "3", "8" },
 	{ &isl_val_inv, "1", "1" },
 	{ &isl_val_inv, "2", "1/2" },
 	{ &isl_val_inv, "1/2", "2" },
@@ -1599,6 +1599,49 @@
 	return 0;
 }
 
+/* Inputs for isl_basic_set_gist tests that are expected to fail.
+ */
+struct {
+	const char *set;
+	const char *context;
+} gist_fail_tests[] = {
+	{ "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
+	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",
+	  "{ [i] : i >= 0 }" },
+};
+
+/* Check that isl_basic_set_gist fails (gracefully) when expected.
+ * In particular, the user should be able to recover from the failure.
+ */
+static isl_stat test_gist_fail(struct isl_ctx *ctx)
+{
+	int i, n;
+	int on_error;
+
+	on_error = isl_options_get_on_error(ctx);
+	isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
+	n = ARRAY_SIZE(gist_fail_tests);
+	for (i = 0; i < n; ++i) {
+		const char *str;
+		isl_basic_set *bset, *context;
+
+		bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);
+		str = gist_fail_tests[i].context;
+		context = isl_basic_set_read_from_str(ctx, str);
+		bset = isl_basic_set_gist(bset, context);
+		isl_basic_set_free(bset);
+		if (bset)
+			break;
+	}
+	isl_options_set_on_error(ctx, on_error);
+	if (i < n)
+		isl_die(ctx, isl_error_unknown,
+			"operation not expected to succeed",
+			return isl_stat_error);
+
+	return isl_stat_ok;
+}
+
 struct {
 	const char *set;
 	const char *context;
@@ -1724,6 +1767,9 @@
 				"inconsistent gist test case", return -1);
 	}
 
+	if (test_gist_fail(ctx) < 0)
+		return -1;
+
 	test_gist_case(ctx, "gist1");
 
 	str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
diff --git a/lib/External/isl/isl_val.c b/lib/External/isl/isl_val.c
index 7a37d18..06e2874 100644
--- a/lib/External/isl/isl_val.c
+++ b/lib/External/isl/isl_val.c
@@ -528,7 +528,7 @@
 
 /* Return 2^v, where v is an integer (that is not too large).
  */
-__isl_give isl_val *isl_val_2exp(__isl_take isl_val *v)
+__isl_give isl_val *isl_val_pow2(__isl_take isl_val *v)
 {
 	unsigned long exp;
 	int neg;
@@ -557,6 +557,13 @@
 	return v;
 }
 
+/* This is an alternative name for the function above.
+ */
+__isl_give isl_val *isl_val_2exp(__isl_take isl_val *v)
+{
+	return isl_val_pow2(v);
+}
+
 /* Return the minimum of "v1" and "v2".
  */
 __isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2)