isl_basic_map_set_to_empty: do not modify input if already marked empty
authorSven Verdoolaege <sven.verdoolaege@gmail.com>
Mon, 16 Mar 2020 21:33:00 +0000 (16 22:33 +0100)
committerSven Verdoolaege <sven.verdoolaege@gmail.com>
Mon, 23 Mar 2020 22:35:08 +0000 (23 23:35 +0100)
A basic map is usually marked empty by calling isl_basic_map_set_to_empty,
in which case it gets a canonical representation that is fairly
robust against changes.
There are, however, also two places where a basic map is directly
marked as empty, without modifying the internal representation.
It is then possible for all of these original constraints
to get removed through subsequent operations, resulting
in a basic map that is marked empty and that has no constraints.
If isl_basic_map_set_to_empty gets called on this basic map,
then it will fail since there may be no room to add the constraint
of the canonical representation.

This happens in particular in the new test case,
where inside map_subtract, the call to isl_map_is_disjoint
may cause basic maps to be marked empty and the subsequent
call to isl_map_compute_divs may then drop all constraints
inside extract_domain, resulting in the problem described above.

Signed-off-by: Sven Verdoolaege <sven.verdoolaege@gmail.com>
isl_map.c
isl_test.c

index acb35a2..7f283b8 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -2136,12 +2136,26 @@ error:
        return NULL;
 }
 
+/* The given basic map has turned out to be empty.
+ * Explicitly mark it as such and change the representation
+ * to a canonical representation of the empty basic map.
+ * Since the basic map has conflicting constraints,
+ * it must have at least one constraint, except perhaps
+ * if it was already explicitly marked as being empty.
+ * Do nothing in the latter case.
+ */
 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
        __isl_take isl_basic_map *bmap)
 {
        int i = 0;
+       isl_bool empty;
        isl_size total;
 
+       empty = isl_basic_map_plain_is_empty(bmap);
+       if (empty < 0)
+               return isl_basic_map_free(bmap);
+       if (empty)
+               return bmap;
        total = isl_basic_map_dim(bmap, isl_dim_all);
        if (total < 0)
                return isl_basic_map_free(bmap);
index 2914cdf..35f4bc6 100644 (file)
@@ -3852,6 +3852,26 @@ static int test_subset(isl_ctx *ctx)
        return 0;
 }
 
+/* Perform a set subtraction with a set that has a non-obviously empty disjunct.
+ * Older versions of isl would fail on such cases.
+ */
+static isl_stat test_subtract_empty(isl_ctx *ctx)
+{
+       const char *str;
+       isl_set *s1, *s2;
+
+       s1 = isl_set_read_from_str(ctx, "{ [0] }");
+       str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and "
+                       "1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and "
+                       "33e2 >= -a + 33e0 + 1056e1 and "
+                       "33e2 < -2a + 66e0 + 2112e1)) or a = 0 }";
+       s2 = isl_set_read_from_str(ctx, str);
+       s1 = isl_set_subtract(s1, s2);
+       isl_set_free(s1);
+
+       return isl_stat_non_null(s1);
+}
+
 struct {
        const char *minuend;
        const char *subtrahend;
@@ -3870,6 +3890,9 @@ static int test_subtract(isl_ctx *ctx)
        isl_union_set *uset;
        int equal;
 
+       if (test_subtract_empty(ctx) < 0)
+               return -1;
+
        for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
                umap1 = isl_union_map_read_from_str(ctx,
                                subtract_domain_tests[i].minuend);