rewrite computation of iteration domains
authorAditya Kumar <aditya.k7@samsung.com>
Thu, 21 Jan 2016 02:13:33 +0000 (02:13 +0000)
committerSebastian Pop <spop@gcc.gnu.org>
Thu, 21 Jan 2016 02:13:33 +0000 (02:13 +0000)
        * graphite-sese-to-poly.c (set_scop_parameter_dim): Remove.
        (cleanup_loop_iter_dom): Remove.
        (build_loop_iteration_domains): Remove.
        (build_scop_context): Remove.
        (build_scop_iteration_domain): Remove.
        (add_loop_constraints): New.
        (build_iteration_domains): New.
        (build_poly_scop): Call build_iteration_domains.

Co-Authored-By: Sebastian Pop <s.pop@samsung.com>
From-SVN: r232656

gcc/ChangeLog
gcc/graphite-sese-to-poly.c

index 3d9efe2679f95a51604ec6bd911041ddf0284c14..4b593a8cc65fc651e89d46e397ab6c7eb5600c9c 100644 (file)
@@ -1,3 +1,15 @@
+2016-01-21  Aditya Kumar  <aditya.k7@samsung.com>
+           Sebastian Pop  <s.pop@samsung.com>
+
+        * graphite-sese-to-poly.c (set_scop_parameter_dim): Remove.
+        (cleanup_loop_iter_dom): Remove.
+        (build_loop_iteration_domains): Remove.
+        (build_scop_context): Remove.
+        (build_scop_iteration_domain): Remove.
+        (add_loop_constraints): New.
+        (build_iteration_domains): New.
+        (build_poly_scop): Call build_iteration_domains.
+
 2016-01-21  Aditya Kumar  <aditya.k7@samsung.com>
            Sebastian Pop  <s.pop@samsung.com>
 
index 3803d5842cffc0ce730cd5a7169e53f03995ca5a..92ab2f97cff46daf60ce1f8c8d7182974457bde1 100644 (file)
@@ -431,159 +431,6 @@ extract_affine (scop_p s, tree e, __isl_take isl_space *space)
   return res;
 }
 
-/* Assign dimension for each parameter in SCOP.  */
-
-static void
-set_scop_parameter_dim (scop_p scop)
-{
-  sese_info_p region = scop->scop_info;
-  unsigned nbp = sese_nb_params (region);
-  isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
-
-  unsigned i;
-  tree e;
-  FOR_EACH_VEC_ELT (region->params, i, e)
-    space = isl_space_set_dim_id (space, isl_dim_param, i,
-                                  isl_id_for_ssa_name (scop, e));
-
-  scop->param_context = isl_set_universe (space);
-}
-
-static inline bool
-cleanup_loop_iter_dom (isl_set *inner, isl_set *outer, isl_space *space, mpz_t g)
-{
-  isl_set_free (inner);
-  isl_set_free (outer);
-  isl_space_free (space);
-  mpz_clear (g);
-  return false;
-}
-
-/* Builds the constraint polyhedra for LOOP in SCOP.  OUTER_PH gives
-   the constraints for the surrounding loops.  */
-
-static bool
-build_loop_iteration_domains (scop_p scop, struct loop *loop,
-                              int nb,
-                             isl_set *outer, isl_set **doms)
-{
-
-  tree nb_iters = number_of_latch_executions (loop);
-  const sese_l& region = scop->scop_info->region;
-  gcc_assert (loop_in_sese_p (loop, region));
-
-  isl_set *inner = isl_set_copy (outer);
-  int pos = isl_set_dim (outer, isl_dim_set);
-  isl_val *v;
-  mpz_t g;
-
-  mpz_init (g);
-
-  inner = isl_set_add_dims (inner, isl_dim_set, 1);
-  isl_space *space = isl_set_get_space (inner);
-
-  /* 0 <= loop_i */
-  isl_constraint *c = isl_inequality_alloc
-      (isl_local_space_from_space (isl_space_copy (space)));
-  c = isl_constraint_set_coefficient_si (c, isl_dim_set, pos, 1);
-  inner = isl_set_coalesce (isl_set_add_constraint (inner, c));
-
-  /* loop_i <= cst_nb_iters */
-  if (TREE_CODE (nb_iters) == INTEGER_CST)
-    {
-      c = isl_inequality_alloc
-         (isl_local_space_from_space (isl_space_copy (space)));
-      c = isl_constraint_set_coefficient_si (c, isl_dim_set, pos, -1);
-      tree_int_to_gmp (nb_iters, g);
-      v = isl_val_int_from_gmp (scop->isl_context, g);
-      c = isl_constraint_set_constant_val (c, v);
-      inner = isl_set_add_constraint (inner, c);
-    }
-
-  /* loop_i <= expr_nb_iters */
-  else if (!chrec_contains_undetermined (nb_iters))
-    {
-      isl_pw_aff *aff;
-
-      nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
-
-      /* Bail out as we do not know the scev.  */
-      if (chrec_contains_undetermined (nb_iters))
-       return cleanup_loop_iter_dom (inner, outer, space, g);
-
-      aff = extract_affine (scop, nb_iters, isl_set_get_space (inner));
-      isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff));
-      valid = isl_set_project_out (valid, isl_dim_set, 0,
-                                  isl_set_dim (valid, isl_dim_set));
-
-      if (valid)
-       scop->param_context = isl_set_coalesce
-         (isl_set_intersect (scop->param_context, valid));
-
-      isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
-      isl_aff *al = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
-                                               isl_dim_in, pos, 1);
-      isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (al),
-                                      isl_pw_aff_copy (aff));
-      inner = isl_set_intersect (inner, le);
-
-      widest_int nit;
-      if (max_stmt_executions (loop, &nit))
-       {
-         /* Insert in the context the constraints from the
-            estimation of the number of iterations NIT and the
-            symbolic number of iterations (involving parameter
-            names) NB_ITERS.  First, build the affine expression
-            "NIT - NB_ITERS" and then say that it is positive,
-            i.e., NIT approximates NB_ITERS: "NIT >= NB_ITERS".  */
-         mpz_t g;
-         mpz_init (g);
-         wi::to_mpz (nit, g, SIGNED);
-         mpz_sub_ui (g, g, 1);
-
-         isl_pw_aff *approx
-           = extract_affine_gmp (g, isl_set_get_space (inner));
-         isl_set *x = isl_pw_aff_ge_set (approx, aff);
-         x = isl_set_project_out (x, isl_dim_set, 0,
-                                  isl_set_dim (x, isl_dim_set));
-         scop->param_context = isl_set_coalesce
-           (isl_set_intersect (scop->param_context, x));
-
-         isl_constraint *c = isl_inequality_alloc
-             (isl_local_space_from_space (isl_space_copy (space)));
-         c = isl_constraint_set_coefficient_si (c, isl_dim_set, pos, -1);
-         v = isl_val_int_from_gmp (scop->isl_context, g);
-         mpz_clear (g);
-         c = isl_constraint_set_constant_val (c, v);
-         inner = isl_set_add_constraint (inner, c);
-       }
-      else
-       isl_pw_aff_free (aff);
-    }
-  else
-    gcc_unreachable ();
-
-  inner = isl_set_coalesce (inner);
-  if (loop->inner
-      && !build_loop_iteration_domains (scop, loop->inner, nb + 1,
-                                       isl_set_copy (inner), doms))
-    return cleanup_loop_iter_dom (inner, outer, space, g);
-
-  if (nb != 0
-      && loop->next
-      && loop_in_sese_p (loop->next, region)
-      && !build_loop_iteration_domains (scop, loop->next, nb,
-                                       isl_set_copy (outer), doms))
-    return cleanup_loop_iter_dom (inner, outer, space, g);
-
-  doms[loop->num] = inner;
-
-  isl_set_free (outer);
-  isl_space_free (space);
-  mpz_clear (g);
-  return true;
-}
-
 /* Returns a linear expression for tree T evaluated in PBB.  */
 
 static isl_pw_aff *
@@ -781,64 +628,6 @@ add_param_constraints (scop_p scop, graphite_dim_t p)
     }
 }
 
-/* Build the context of the SCOP.  The context usually contains extra
-   constraints that are added to the iteration domains that constrain
-   some parameters.  */
-
-static void
-build_scop_context (scop_p scop)
-{
-  graphite_dim_t p, n = scop_nb_params (scop);
-
-  for (p = 0; p < n; p++)
-    add_param_constraints (scop, p);
-}
-
-/* Build the iteration domains: the loops belonging to the current
-   SCOP, and that vary for the execution of the current basic block.
-   Returns false if there is no loop in SCOP.  */
-
-static bool
-build_scop_iteration_domain (scop_p scop)
-{
-  sese_info_p region = scop->scop_info;
-  int nb_loops = number_of_loops (cfun);
-  isl_set **doms = XCNEWVEC (isl_set *, nb_loops);
-  bool res = true;
-  int i;
-  struct loop *loop;
-  FOR_EACH_VEC_ELT (region->loop_nest, i, loop)
-    if (!loop_in_sese_p (loop_outer (loop), region->region)
-       && !build_loop_iteration_domains (scop, loop, 0,
-                                         isl_set_copy (scop->param_context), doms))
-      {
-       res = false;
-       goto cleanup;
-      }
-
-  poly_bb_p pbb;
-  FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
-    {
-      loop = pbb_loop (pbb);
-
-      if (doms[loop->num])
-       pbb->domain = isl_set_copy (doms[loop->num]);
-      else
-       pbb->domain = isl_set_copy (scop->param_context);
-
-      pbb->domain = isl_set_set_tuple_id (pbb->domain,
-                                         isl_id_for_pbb (scop, pbb));
-    }
-
- cleanup:
-  for (int i = 0; i < nb_loops; i++)
-    if (doms[i])
-      isl_set_free (doms[i]);
-
-  free (doms);
-  return res;
-}
-
 /* Add a constrain to the ACCESSES polyhedron for the alias set of
    data reference DR.  ACCESSP_NB_DIMS is the dimension of the
    ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
@@ -1109,17 +898,205 @@ build_scop_drs (scop_p scop)
     build_poly_sr (pbb);
 }
 
+/* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT.  */
+
+static isl_set *
+add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
+                     loop_p context)
+{
+  if (loop == context)
+    return domain;
+  const sese_l &region = scop->scop_info->region;
+  if (!loop_in_sese_p (loop, region))
+    return domain;
+
+  /* Recursion all the way up to the context loop.  */
+  domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
+
+  /* Then, build constraints over the loop in post-order: outer to inner.  */
+
+  int loop_index = isl_set_dim (domain, isl_dim_set);
+  if (dump_file)
+    fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the "
+            "domain for loop_%d.\n", loop->num);
+  domain = isl_set_add_dims (domain, isl_dim_set, 1);
+  isl_space *space = isl_set_get_space (domain);
+
+  /* 0 <= loop_i */
+  isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
+  isl_constraint *c = isl_inequality_alloc (ls);
+  c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
+  if (dump_file)
+    {
+      fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
+      print_isl_constraint (dump_file, c);
+    }
+  domain = isl_set_add_constraint (domain, c);
+
+  tree nb_iters = number_of_latch_executions (loop);
+  if (TREE_CODE (nb_iters) == INTEGER_CST)
+    {
+      /* loop_i <= cst_nb_iters */
+      isl_local_space *ls = isl_local_space_from_space (space);
+      isl_constraint *c = isl_inequality_alloc (ls);
+      c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
+      mpz_t g;
+      mpz_init (g);
+      tree_int_to_gmp (nb_iters, g);
+      isl_val *v = isl_val_int_from_gmp (scop->isl_context, g);
+      mpz_clear (g);
+      c = isl_constraint_set_constant_val (c, v);
+      return isl_set_add_constraint (domain, c);
+    }
+  /* loop_i <= expr_nb_iters */
+  gcc_assert (!chrec_contains_undetermined (nb_iters));
+  nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
+  gcc_assert (!chrec_contains_undetermined (nb_iters));
+
+  isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
+                                            isl_space_copy (space));
+  isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters));
+  valid = isl_set_project_out (valid, isl_dim_set, 0,
+                              isl_set_dim (valid, isl_dim_set));
+
+  if (valid)
+    scop->param_context = isl_set_intersect (scop->param_context, valid);
+
+  ls = isl_local_space_from_space (isl_space_copy (space));
+  isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
+                                               isl_dim_in, loop_index, 1);
+  isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i),
+                                  isl_pw_aff_copy (aff_nb_iters));
+  if (dump_file)
+    {
+      fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
+      print_isl_set (dump_file, le);
+    }
+  domain = isl_set_intersect (domain, le);
+
+  widest_int nit;
+  if (!max_stmt_executions (loop, &nit))
+    {
+      isl_pw_aff_free (aff_nb_iters);
+      isl_space_free (space);
+      return domain;
+    }
+
+  /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
+     do not know whether the loop executes at least once.  */
+  mpz_t g;
+  mpz_init (g);
+  wi::to_mpz (nit, g, SIGNED);
+  mpz_sub_ui (g, g, 1);
+
+  isl_pw_aff *approx = extract_affine_gmp (g, isl_space_copy (space));
+  isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters);
+  x = isl_set_project_out (x, isl_dim_set, 0,
+                          isl_set_dim (x, isl_dim_set));
+  scop->param_context = isl_set_intersect (scop->param_context, x);
+
+  ls = isl_local_space_from_space (space);
+  c = isl_inequality_alloc (ls);
+  c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
+  isl_val *v = isl_val_int_from_gmp (scop->isl_context, g);
+  mpz_clear (g);
+  c = isl_constraint_set_constant_val (c, v);
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
+      print_isl_constraint (dump_file, c);
+    }
+
+  return isl_set_add_constraint (domain, c);
+}
+
+/* Builds the original iteration domains for each pbb in the SCOP.  */
+
+static int
+build_iteration_domains (scop_p scop, __isl_keep isl_set *context, int index,
+                        loop_p context_loop)
+{
+  loop_p current = pbb_loop (scop->pbbs[index]);
+  isl_set *domain = isl_set_copy (context);
+  domain = add_loop_constraints (scop, domain, current, context_loop);
+  const sese_l &region = scop->scop_info->region;
+
+  int i;
+  poly_bb_p pbb;
+  FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
+    {
+      loop_p loop = pbb_loop (pbb);
+      if (current == loop)
+       {
+         pbb->domain = isl_set_copy (domain);
+         pbb->domain = isl_set_set_tuple_id (pbb->domain,
+                                             isl_id_for_pbb (scop, pbb));
+         if (dump_file)
+           {
+             fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
+                      pbb_index (pbb));
+             print_isl_set (dump_file, domain);
+           }
+         continue;
+       }
+
+      while (loop_in_sese_p (loop, region)
+            && current != loop)
+       loop = loop_outer (loop);
+
+      if (current != loop)
+       {
+         /* A statement in a different loop nest than CURRENT loop.  */
+         isl_set_free (domain);
+         return i;
+       }
+
+      /* A statement nested in the CURRENT loop.  */
+      i = build_iteration_domains (scop, domain, i, current);
+      i--;
+    }
+
+  isl_set_free (domain);
+  return i;
+}
+
+
+/* Assign dimension for each parameter in SCOP and add constraints for the
+   parameters.  */
+
+static void
+build_scop_context (scop_p scop)
+{
+  sese_info_p region = scop->scop_info;
+  unsigned nbp = sese_nb_params (region);
+  isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
+
+  unsigned i;
+  tree e;
+  FOR_EACH_VEC_ELT (region->params, i, e)
+    space = isl_space_set_dim_id (space, isl_dim_param, i,
+                                  isl_id_for_ssa_name (scop, e));
+
+  scop->param_context = isl_set_universe (space);
+
+  graphite_dim_t p;
+  for (p = 0; p < nbp; p++)
+    add_param_constraints (scop, p);
+}
+
 /* Builds the polyhedral representation for a SESE region.  */
 
 bool
 build_poly_scop (scop_p scop)
 {
-  set_scop_parameter_dim (scop);
-  if (!build_scop_iteration_domain (scop))
-    return false;
-
   build_scop_context (scop);
 
+  unsigned i = 0;
+  unsigned n = scop->pbbs.length ();
+  while (i < n)
+    i = build_iteration_domains (scop, scop->param_context, i, NULL);
+
   if (!add_conditions_to_constraints (scop))
     return false;