From aa7b5cfe601366e53f9bc5e19c4f61badb557f8d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 29 Mar 2013 14:53:13 +0100 Subject: [PATCH] isl_ast_node_print: avoid duplicate declarations in printed code If a loop has only one iteration but if the expression for this single iteration is too complicated to be substituted into the AST, then the expression is assigned to a variable corresponding to the loop iterator. If two such loops occur in the same block, then we would end up with two declarations of the same variable. Avoid this problem by introducing a block around the declaration if it appears in a sequence of statements. Reported-by: Tobias Grosser Signed-off-by: Sven Verdoolaege --- isl_ast.c | 31 ++++++++++++++++++++----------- test_inputs/codegen/unroll4.c | 22 ++++++++++++++++++++++ test_inputs/codegen/unroll4.in | 5 +++++ 3 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 test_inputs/codegen/unroll4.c create mode 100644 test_inputs/codegen/unroll4.in diff --git a/isl_ast.c b/isl_ast.c index 3094bab5..05a79a45 100644 --- a/isl_ast.c +++ b/isl_ast.c @@ -1315,7 +1315,7 @@ static int need_block(__isl_keep isl_ast_node *node) static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p, __isl_keep isl_ast_node *node, - __isl_keep isl_ast_print_options *options, int in_block); + __isl_keep isl_ast_print_options *options, int in_block, int in_list); static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p, __isl_keep isl_ast_node *node, __isl_keep isl_ast_print_options *options, int new_line); @@ -1355,7 +1355,7 @@ static __isl_give isl_printer *print_body_c(__isl_take isl_printer *p, p = isl_printer_print_str(p, " {"); p = isl_printer_end_line(p); p = isl_printer_indent(p, 2); - p = print_ast_node_c(p, node, options, 1); + p = print_ast_node_c(p, node, options, 1, 0); p = isl_printer_indent(p, -2); p = isl_printer_start_line(p); p = isl_printer_print_str(p, "}"); @@ -1410,12 +1410,15 @@ static __isl_give isl_printer *end_block(__isl_take isl_printer *p) * body * * "in_block" is set if we are currently inside a block. - * We simply pass it along to print_ast_node_c in case of a degenerate - * for loop. + * "in_list" is set if the current node is not alone in the block. + * If we are not in a block or if the current not is not alone in the block + * then we print a block around a degenerate for loop such that the variable + * declaration will not conflict with any potential other declaration + * of the same variable. */ static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p, __isl_keep isl_ast_node *node, - __isl_keep isl_ast_print_options *options, int in_block) + __isl_keep isl_ast_print_options *options, int in_block, int in_list) { isl_id *id; const char *name; @@ -1445,6 +1448,8 @@ static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p, id = isl_ast_expr_get_id(node->u.f.iterator); name = isl_id_get_name(id); isl_id_free(id); + if (!in_block || in_list) + p = start_block(p); p = isl_printer_start_line(p); p = isl_printer_print_str(p, type); p = isl_printer_print_str(p, " "); @@ -1453,7 +1458,9 @@ static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p, p = isl_printer_print_ast_expr(p, node->u.f.init); p = isl_printer_print_str(p, ";"); p = isl_printer_end_line(p); - p = print_ast_node_c(p, node->u.f.body, options, in_block); + p = print_ast_node_c(p, node->u.f.body, options, 1, 0); + if (!in_block || in_list) + p = end_block(p); } return p; @@ -1482,10 +1489,12 @@ static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p, * If so, we do not print a block around the children of a block node. * We do this to avoid an extra block around the body of a degenerate * for node. + * + * "in_list" is set if the current node is not alone in the block. */ static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p, __isl_keep isl_ast_node *node, - __isl_keep isl_ast_print_options *options, int in_block) + __isl_keep isl_ast_print_options *options, int in_block, int in_list) { switch (node->type) { case isl_ast_node_for: @@ -1493,7 +1502,7 @@ static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p, return options->print_for(p, isl_ast_print_options_copy(options), node, options->print_for_user); - p = print_for_c(p, node, options, in_block); + p = print_for_c(p, node, options, in_block, in_list); break; case isl_ast_node_if: p = print_if_c(p, node, options, 1); @@ -1531,7 +1540,7 @@ __isl_give isl_printer *isl_ast_node_for_print(__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", goto error); - p = print_for_c(p, node, options, 0); + p = print_for_c(p, node, options, 0, 0); isl_ast_print_options_free(options); return p; error: @@ -1566,7 +1575,7 @@ __isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node, { if (!options || !node) goto error; - p = print_ast_node_c(p, node, options, 0); + p = print_ast_node_c(p, node, options, 0, 0); isl_ast_print_options_free(options); return p; error: @@ -1616,7 +1625,7 @@ __isl_give isl_printer *isl_ast_node_list_print( return isl_printer_free(p); for (i = 0; i < list->n; ++i) - p = print_ast_node_c(p, list->p[i], options, 1); + p = print_ast_node_c(p, list->p[i], options, 1, 1); return p; } diff --git a/test_inputs/codegen/unroll4.c b/test_inputs/codegen/unroll4.c new file mode 100644 index 00000000..9bf18843 --- /dev/null +++ b/test_inputs/codegen/unroll4.c @@ -0,0 +1,22 @@ +{ + write_shared_A(3, ((t1 + 3) % 4) + 1, ((t2 + 31) % 32) + 1); + if (t1 % 3 == 0 && t2 >= 1 && t2 <= 2) + write_shared_A(3, (-t1 + 12) / 3, t2 + 32); + { + int c3 = t2 <= 1 || (t2 >= 2 && ((3 * t1 + t2 + 3) % 4) + 1 >= t2) ? t2 + 32 : t2; + if (c3 == t2 + 32 || (c3 == t2 && t1 + 4 * floord(-((t2 + 1) % 2) - t1 + t2 + 3, 4) >= 5 && t1 + 4 * floord(-((t2 + 1) % 2) - t1 + t2 + 3, 4) <= 8)) + write_shared_A(3, ((t1 + 3) % 4) + 5, c3); + } + if (t2 >= t1 + 1 && t2 <= 4 && t1 >= 1) + write_shared_A(3, t1 + 4, t2 + 32); + write_shared_A(4, ((t1 + 3) % 4) + 1, ((t2 + 31) % 32) + 1); + if (t1 % 3 == 0 && t2 >= 1 && t2 <= 2) + write_shared_A(4, (-t1 + 12) / 3, t2 + 32); + { + int c3 = t2 <= 1 || (t2 >= 2 && ((3 * t1 + t2 + 3) % 4) + 1 >= t2) ? t2 + 32 : t2; + if (c3 == t2 + 32 || (c3 == t2 && t1 + 4 * floord(-((t2 + 1) % 2) - t1 + t2 + 3, 4) >= 5 && t1 + 4 * floord(-((t2 + 1) % 2) - t1 + t2 + 3, 4) <= 8)) + write_shared_A(4, ((t1 + 3) % 4) + 5, c3); + } + if (t2 >= t1 + 1 && t2 <= 4 && t1 >= 1) + write_shared_A(4, t1 + 4, t2 + 32); +} diff --git a/test_inputs/codegen/unroll4.in b/test_inputs/codegen/unroll4.in new file mode 100644 index 00000000..d8be866f --- /dev/null +++ b/test_inputs/codegen/unroll4.in @@ -0,0 +1,5 @@ +# Check that the generated code does not contain two declarations +# of the same variable in the same scope. +[t1, t2, g] -> { write_shared_A[a, b, c] -> [0, a, b, c] : exists (e0, e1 = [(-t1 + b)/4], e2 = [(-t2 + c)/32]: 4e1 = -t1 + b and 32e2 = -t2 + c and e0 <= 2 + 3g and e0 >= 3g and a <= 4 and a >= 3 and t2 >= 0 and t1 <= 3 and 2e0 >= 5 - c + 6g and 2e0 <= 36 - c + 6g and 2e0 >= 5 - b + 6g and 2e0 <= 8 - b + 6g and 2e0 <= 638 - c and 2e0 <= 638 - b and 2e0 >= 2 - a + 6g and 2e0 >= -8 + a + 6g and 2e0 <= 1 + a + 6g and 2e0 <= 11 - a + 6g and e0 >= 0 and e0 <= 254 and t1 >= 0 and t2 <= 31 and b >= 1 and b <= 126 and c >= 1 and c <= 126 and g <= 3 and g >= 0) } +[t1, t2, g] -> { : g <= 3 and g >= 0 and t1 >= 0 and t1 <= 3 and t2 >= 0 and t2 <= 5 } +[t1, t2] -> { [i0, i1, i2, i3] -> unroll[x] } -- 2.11.4.GIT