On 25/05/2014 13:12, Roman Gareev wrote:
Hi Tobias,

I tried to incorporate all your comments in the following patch. It
also contains traversing of ISL AST and its dump to a file. You can
find out more about this at the following link
http://romangareev.blogspot.ru/2014/05/gsoc-report-i.html

Hi Roman,

thanks for this update (and expecially the nice blog post).
Also the size of the patch is great. Small enough to be easy to review
and still adding good features.

diff --git a/gcc/common.opt b/gcc/common.opt
index 5c3f834..005042d 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1250,6 +1250,10 @@ fgraphite-identity
 Common Report Var(flag_graphite_identity) Optimization
 Enable Graphite Identity transformation

+fgraphite-isl-code-gen
+Common Report Var(flag_graphite_isl_code_gen) Optimization
+Enable isl code generator in Graphite

Can we use something like:

-fgraphite-code-generator=[isl|cloog]

This allows us to start with cloog as default and then flip the switch
as soon as we are confident enough.

diff --git a/gcc/graphite-clast-to-gimple.c b/gcc/graphite-clast-to-gimple.c
index 9ac9b67..d16439d 100644
--- a/gcc/graphite-clast-to-gimple.c
+++ b/gcc/graphite-clast-to-gimple.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include <isl/constraint.h>
 #include <isl/ilp.h>
 #include <isl/aff.h>
+#include <isl/ast_build.h>

Can we put this into a new file? clast stands for CLOOG-AST. I would
prefer to have a new file ala graphite-isl-ast-to-gimple.c or
graphite-ast-generation.c


 #include <cloog/cloog.h>
 #include <cloog/isl/domain.h>
 #endif
@@ -1657,6 +1658,221 @@ debug_generated_program (scop_p scop)
   print_generated_program (stderr, scop);
 }

+
+/* Integration of ISL code generator. */
+
+/* TODO: eliminate this function as soon as possible */
+
+void
+print_indent (int indent, isl_printer *prn)
+{
+  int i;
+  for (i = 0; i < indent; i++)
+    {
+      prn = isl_printer_print_str (prn, " ");
+    }
+}

Why is this function necessary in the first place? Are you aware of
isl_printer_set_indent() and isl_printer_set_indent_prefix()?

+static void
+translate_isl_ast (int indent, __isl_keep isl_ast_node *node,
+                  isl_printer *prn);
+
+/* Translates a isl_ast_node_for STMT to gimple.
+   TODO: replace output to FILE with translation
+   to GCC representation. */
+
+static void
+translate_isl_ast_node_for (int indent, __isl_keep isl_ast_node *node_for,
+                           isl_printer *prn)
+{
+  isl_id *id;
+  const char *name;
+  const char *type;
+  type = isl_options_get_ast_iterator_type (isl_printer_get_ctx (prn));
+  isl_ast_expr *for_iterator = isl_ast_node_for_get_iterator (node_for);
+  isl_ast_expr_free (for_iterator);
+  id = isl_ast_expr_get_id (for_iterator);
+  name = isl_id_get_name (id);
+  isl_id_free (id);
+  prn = isl_printer_print_str (prn, "\n");
+  print_indent (indent, prn);
+  prn = isl_printer_print_str (prn, "for (");
+  prn = isl_printer_print_str (prn, type);
+  prn = isl_printer_print_str (prn, " ");
+  prn = isl_printer_print_str (prn, name);
+  prn = isl_printer_print_str (prn, " = ");
+  isl_ast_expr *for_init = isl_ast_node_for_get_init (node_for);
+  prn = isl_printer_print_ast_expr (prn, for_init);
+  isl_ast_expr_free (for_init);
+  prn = isl_printer_print_str (prn, "; ");
+  isl_ast_expr *for_cond = isl_ast_node_for_get_cond (node_for);
+  prn = isl_printer_print_ast_expr (prn, for_cond);
+  isl_ast_expr_free (for_cond);
+  prn = isl_printer_print_str (prn, "; ");
+  prn = isl_printer_print_str (prn, name);
+  prn = isl_printer_print_str (prn, " += ");
+  isl_ast_expr *for_inc = isl_ast_node_for_get_inc (node_for);
+  prn = isl_printer_print_ast_expr (prn, for_inc);
+  isl_ast_expr_free (for_inc);
+  prn = isl_printer_print_str (prn, ")");
+  isl_ast_node *for_body = isl_ast_node_for_get_body (node_for);
+  translate_isl_ast (indent + 2, for_body, prn);
+  isl_ast_node_free (for_body);
+}
+
+/* Translates a clast guard statement STMT to gimple.
+   TODO: replace output to FILE with translation
+   to GCC representation. */
+
+static void
+translate_isl_ast_node_if (int indent, __isl_keep isl_ast_node *node_if,
+                          isl_printer *prn)
+{
+  prn = isl_printer_print_str (prn, "\n");
+  print_indent (indent, prn);
+  prn = isl_printer_print_str (prn, "if (");
+  isl_ast_expr *if_cond = isl_ast_node_if_get_cond (node_if);
+  prn = isl_printer_print_ast_expr (prn, if_cond);
+  isl_ast_expr_free (if_cond);
+  prn = isl_printer_print_str (prn, ")");
+  isl_ast_node *if_then = isl_ast_node_if_get_then (node_if);
+  translate_isl_ast (indent + 2, if_then, prn);
+  isl_ast_node_free (if_then);
+  if (isl_ast_node_if_has_else (node_if))
+    {
+      prn = isl_printer_print_str (prn, "else");
+      isl_ast_node *if_else = isl_ast_node_if_get_else(node_if);
+      translate_isl_ast (indent + 2, if_else, prn);
+      isl_ast_node_free (if_else);
+    }
+}
+
+/* Translates a clast guard statement STMT to gimple.
+   TODO: replace output to FILE with translation
+   to GCC representation. */
+
+static void
+translate_isl_ast_node_user (int indent, __isl_keep isl_ast_node *node_user,
+                            isl_printer *prn)
+{
+  prn = isl_printer_print_str (prn, "\n");
+  prn = isl_printer_set_indent (prn, indent);
+  prn = isl_printer_print_ast_node (prn, node_user);
+}
+
+/* Translates a clast guard statement STMT to gimple.
+   TODO: replace output to FILE with translation
+   to GCC representation. */
+
+static void
+translate_isl_ast_node_block (int indent, __isl_keep isl_ast_node *node_block,
+                             isl_printer *prn)
+{
+  isl_ast_node_list *node_list = isl_ast_node_block_get_children (node_block);
+  int i;
+  for (i = 0; i < isl_ast_node_list_n_ast_node (node_list); i++)
+    {
+      translate_isl_ast (indent + 2,
+                        isl_ast_node_list_get_ast_node (node_list, i), prn);
+    }
+  isl_ast_node_list_free (node_list);
+}
+
+/* Translates a ISL AST node NODE to GCC representation in the
+   context of a SESE.
+   TODO: replace output to FILE with translation
+   to GCC representation. */
+
+static void
+translate_isl_ast (int indent, __isl_keep isl_ast_node *node, isl_printer *prn)
+{
+  switch (isl_ast_node_get_type (node))
+    {
+    case isl_ast_node_error:
+      gcc_unreachable ();
+
+    case isl_ast_node_for:
+      translate_isl_ast_node_for (indent, node, prn);
+      return;
+
+    case isl_ast_node_if:
+      translate_isl_ast_node_if (indent, node, prn);
+      return;
+
+    case isl_ast_node_user:
+      translate_isl_ast_node_user (indent, node, prn);
+      return;
+
+    case isl_ast_node_block:
+      translate_isl_ast_node_block (indent, node, prn);
+      return;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Prints NODE to FILE.  */
+
+void
+print_isl_ast_node (FILE *file, __isl_keep isl_ast_node *node,
+                   __isl_keep isl_ctx *ctx)
+{
+  isl_printer *prn = isl_printer_to_file (ctx, file);
+  prn = isl_printer_set_output_format (prn, ISL_FORMAT_C);
+  prn = isl_printer_print_ast_node (prn, node);
+  isl_printer_free (prn);
+}



+
+/* Generates a build, which specifies the constraints on the parameters. */
+
+static isl_ast_build *
+generate_isl_context (scop_p scop)
+{
+  isl_set * context_isl = isl_set_params (isl_set_copy (scop->context));
+  return isl_ast_build_from_context (context_isl);
+}
+
+/* Generates a schedule, which specifies an order used to
+   visit elements in a domain. */
+
+static isl_union_map *
+generate_isl_schedule (scop_p scop)
+{
+  int i;
+  poly_bb_p pbb;
+  isl_union_map *schedule_isl =
+    isl_union_map_empty (isl_set_get_space (scop->context));
+
+  FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb)
+    {
+      /* Dead code elimination: when the domain of a PBB is empty,
+        don't generate code for the PBB.  */
+      if (isl_set_is_empty (pbb->domain))
+       continue;
+
+      isl_map *bb_schedule = isl_map_copy (pbb->transformed);
+      bb_schedule = isl_map_intersect_domain (bb_schedule,
+                                             isl_set_copy (pbb->domain));
+      schedule_isl =
+        isl_union_map_union (schedule_isl,
+                            isl_union_map_from_map (bb_schedule));
+    }
+  return schedule_isl;
+}
+
+static isl_ast_node *
+scop_to_isl_ast (scop_p scop)
+{
+  isl_union_map *schedule_isl = generate_isl_schedule (scop);
+  isl_ast_build *context_isl = generate_isl_context (scop);
+  isl_ast_node *ast_isl = isl_ast_build_ast_from_schedule (context_isl,
+                                                          schedule_isl);
+  isl_ast_build_free (context_isl);
+  return ast_isl;
+}
+

Allright. It seems you understood the tree traversel. For the actual
patch that we want to commit, let's leave it out for now.  Instead,
let's try to get a minimal patch that only adds the flag and the new
file for the isl_ast stuff. In case the isl is choosen as code
generation option, the cloog pass is disabled (they would otherwise get
into their way later) and we dump the ast. We also need a simple test case
that checks that the dump is generated.

 /* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
    the given SCOP.  Return true if code generation succeeded.
    BB_PBB_MAPPING is a basic_block and it's related poly_bb_p mapping.
@@ -1680,6 +1896,24 @@ gloog (scop_p scop, bb_pbb_htab_type bb_pbb_mapping)

   clast = scop_to_clast (scop, params_index);

+  if (flag_graphite_isl_code_gen)
+    {
+      isl_ast_node *root_node = scop_to_isl_ast (scop);
+      if (dump_file && (dump_flags & TDF_DETAILS))
+        {
+          fprintf (dump_file, "\nISL AST generated by ISL: \n");
+          print_isl_ast_node (dump_file, root_node, scop->ctx);
+          fprintf (dump_file, "\nISL AST dumped by traversing: ");
+          isl_printer *prn = isl_printer_to_file (scop->ctx, dump_file);
+          prn = isl_printer_set_output_format (prn, ISL_FORMAT_C);
+          translate_isl_ast (0, root_node, prn);
+          isl_printer_free (prn);
+          fflush (dump_file);
+          fprintf (dump_file, "\n");
+        }
+      isl_ast_node_free (root_node);
+    }
+
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "\nCLAST generated by CLooG: \n");

Instead of adding this functionality to gloog() I would create a
semilar function that provides the functionality gloog has for the isl
codegen counterpart. -fgraphite-code-generator switches then between
these two functions. To start with the isl counterpart is almost empty.
It just contains the parts of this patch needed for printing. When we
add more functionality and we encounter reuse opportunities, we can move
parts of graphite-clast-to-gimple.c into a generic codegen file.

What do you think?

Cheers,
Tobias

Reply via email to