isl_ast_build_ast_from_schedule: avoid introducing iterator in hoisted condition
authorSven Verdoolaege <skimo@kotnet.org>
Sat, 9 Mar 2013 20:19:13 +0000 (21:19 +0100)
committerSven Verdoolaege <skimo@kotnet.org>
Sun, 10 Mar 2013 15:43:03 +0000 (16:43 +0100)
ast_graft_list_fuse was being passed the build of the inner level from
create_node_scaled, which could result in the current loop iterator
getting introduced in the hoisted condition.
Since we need the inner build for simplifying the expressions generated
from the conditions that are not hoisted out, we now pass two builds
to ast_graft_list_fuse.

Reported-by: Tobias Grosser <tobias@grosser.es>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
isl_ast_codegen.c
isl_ast_graft.c
isl_ast_graft_private.h
test_inputs/codegen/hoist2.c [new file with mode: 0644]
test_inputs/codegen/hoist2.in [new file with mode: 0644]

index c524768..9d94bce 100644 (file)
@@ -1303,7 +1303,7 @@ static __isl_give isl_ast_graft *create_node_scaled(
        children = generate_next_level(executed,
                                    isl_ast_build_copy(body_build));
 
-       graft = isl_ast_graft_alloc_level(children, sub_build);
+       graft = isl_ast_graft_alloc_level(children, build, sub_build);
        if (!eliminated)
                graft = isl_ast_graft_insert_for(graft, node);
        if (eliminated)
index 627393b..8173433 100644 (file)
@@ -679,11 +679,15 @@ static __isl_give isl_ast_graft_list *gist_guards(
 /* Combine the grafts in the list into a single graft.
  *
  * If "up" is set then the resulting graft will be used at an outer level.
+ * In this case, "build" refers to the outer level, while "sub_build"
+ * refers to the inner level.  If "up" is not set, then the same build
+ * should be passed to both arguments.
  *
  * The guard is initialized to the shared guard of the list elements (if any),
  * provided it does not depend on the current dimension.
  * The guards in the elements are then simplified with respect to the
- * hoisted guard and materialized as if nodes around the contained AST nodes.
+ * hoisted guard and materialized as if nodes around the contained AST nodes
+ * in the context of "sub_build".
  *
  * The enforced set is initialized to the simple hull of the enforced sets
  * of the elements, provided the ast_build_exploit_nested_bounds option is set
@@ -693,8 +697,8 @@ static __isl_give isl_ast_graft_list *gist_guards(
  * or, if there is only a single element, the node of that element.
  */
 static __isl_give isl_ast_graft *ast_graft_list_fuse(
-       __isl_take isl_ast_graft_list *list,
-       __isl_keep isl_ast_build *build, int up)
+       __isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build,
+       __isl_keep isl_ast_build *sub_build, int up)
 {
        isl_ctx *ctx;
        isl_ast_node *node;
@@ -708,7 +712,7 @@ static __isl_give isl_ast_graft *ast_graft_list_fuse(
        ctx = isl_ast_build_get_ctx(build);
        guard = extract_hoistable_guard(list, build);
        list = gist_guards(list, guard);
-       list = insert_pending_guard_nodes(list, build);
+       list = insert_pending_guard_nodes(list, sub_build);
 
        node_list = extract_node_list(list);
        node = isl_ast_node_from_ast_node_list(node_list);
@@ -741,7 +745,7 @@ __isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
                return NULL;
        if (isl_ast_graft_list_n_ast_graft(list) <= 1)
                return list;
-       graft = ast_graft_list_fuse(list, build, 0);
+       graft = ast_graft_list_fuse(list, build, build, 0);
        return isl_ast_graft_list_from_ast_graft(graft);
 }
 
@@ -761,11 +765,13 @@ static __isl_give isl_ast_graft *isl_ast_graft_fuse(
        list = isl_ast_graft_list_add(list, graft1);
        list = isl_ast_graft_list_add(list, graft2);
 
-       return ast_graft_list_fuse(list, build, 0);
+       return ast_graft_list_fuse(list, build, build, 0);
 }
 
 /* Allocate a graft for the current level based on the list of grafts
  * of the inner level.
+ * "build" represents the context of the current level.
+ * "sub_build" represents the context of the inner level.
  *
  * The node is initialized to either a block containing the nodes of "children"
  * or, if there is only a single child, the node of that child.
@@ -774,9 +780,9 @@ static __isl_give isl_ast_graft *isl_ast_graft_fuse(
  */
 __isl_give isl_ast_graft *isl_ast_graft_alloc_level(
        __isl_take isl_ast_graft_list *children,
-       __isl_keep isl_ast_build *build)
+       __isl_keep isl_ast_build *build, __isl_keep isl_ast_build *sub_build)
 {
-       return ast_graft_list_fuse(children, build, 1);
+       return ast_graft_list_fuse(children, build, sub_build, 1);
 }
 
 /* Insert a for node enclosing the current graft->node.
index 93e2f24..7bd54bc 100644 (file)
@@ -46,7 +46,7 @@ __isl_give isl_ast_graft *isl_ast_graft_alloc(
        __isl_take isl_ast_node *node, __isl_keep isl_ast_build *build);
 __isl_give isl_ast_graft *isl_ast_graft_alloc_level(
        __isl_take isl_ast_graft_list *children,
-       __isl_keep isl_ast_build *build);
+       __isl_keep isl_ast_build *build, __isl_keep isl_ast_build *sub_build);
 __isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
        __isl_take isl_ast_graft_list *children,
        __isl_keep isl_ast_build *build);
diff --git a/test_inputs/codegen/hoist2.c b/test_inputs/codegen/hoist2.c
new file mode 100644 (file)
index 0000000..26fba66
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 5; c0 += 1)
+  if (c0 <= 2 || (t1 + c0 >= 8 && c0 >= 2 && c0 <= 3) || (b == 1 && t1 + c0 >= 10 && c0 >= 3) || (b == 1 && t1 <= 6 && t1 + c0 <= 9))
+    for (int c1 = max(t1, t1 - 64 * b + 64); c1 <= min(70, -((c0 + 1) % 2) - c0 + 73); c1 += 64)
+      if ((c0 <= 2 && c0 >= 1 && c0 + c1 <= 71 && c1 >= 7) || (c1 == t1 + 64 && c0 <= 3 && c0 >= 2 && t1 + c0 >= 8) || (c1 == t1 && b == 1 && c0 >= 3 && t1 + c0 >= 10) || (c1 == t1 && b == 1 && t1 <= 6 && t1 + c0 <= 9))
+        A(c0, 64 * b + c1 - 8);
diff --git a/test_inputs/codegen/hoist2.in b/test_inputs/codegen/hoist2.in
new file mode 100644 (file)
index 0000000..6a29a02
--- /dev/null
@@ -0,0 +1,5 @@
+# Check that the constraints hoisted from the inner loop
+# do not end up involving the inner loop iterator.
+[t1, b] -> { A[i1, i2] -> [i1, 8 - 64b + i2] : exists (e0, e1 = [(-8 + t1 - i2)/64]: 64e1 = -8 + t1 - i2 and i2 >= 1 and i2 <= 127 and 2e0 >= -3 + i1 and 2e0 >= -1 - i1 and 2e0 <= 8 - i1 and 2e0 <= 6 + i1 and 2e0 >= -65 - 64b + i2 and 2e0 >= -1 + 64b - i2 and e0 <= 1 and e0 >= 0 and 2e0 <= 62 + 64b - i2 and b <= 1 and b >= 0 and i1 >= 1 and i1 <= 2046 and t1 >= 5 and t1 <= 8) }
+[t1, b] -> { : b >= 0 and b <= 1 and t1 >= 5 and t1 <= 8 }
+[t1] -> { [i0, i1, i5, a] -> atomic[x]}