aboutsummaryrefslogtreecommitdiff
path: root/gcc/graphite-dependences.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/graphite-dependences.c')
-rw-r--r--gcc/graphite-dependences.c692
1 files changed, 692 insertions, 0 deletions
diff --git a/gcc/graphite-dependences.c b/gcc/graphite-dependences.c
new file mode 100644
index 0000000..3cd41ed
--- /dev/null
+++ b/gcc/graphite-dependences.c
@@ -0,0 +1,692 @@
+/* Data dependence analysis for Graphite.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+ Contributed by Sebastian Pop <sebastian.pop@amd.com> and
+ Konrad Trifunovic <konrad.trifunovic@inria.fr>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "ggc.h"
+#include "tree.h"
+#include "rtl.h"
+#include "basic-block.h"
+#include "diagnostic.h"
+#include "tree-flow.h"
+#include "toplev.h"
+#include "tree-dump.h"
+#include "timevar.h"
+#include "cfgloop.h"
+#include "tree-chrec.h"
+#include "tree-data-ref.h"
+#include "tree-scalar-evolution.h"
+#include "tree-pass.h"
+#include "domwalk.h"
+#include "pointer-set.h"
+#include "gimple.h"
+
+#ifdef HAVE_cloog
+#include "cloog/cloog.h"
+#include "ppl_c.h"
+#include "sese.h"
+#include "graphite-ppl.h"
+#include "graphite.h"
+#include "graphite-poly.h"
+#include "graphite-dependences.h"
+
+/* Creates a new polyhedral data reference pair and
+ returns it. Parameter SOURCE denotes a source data reference
+ while parameter SINK denotes a sink data reference. Both
+ SOURCE and SINK define a pair of references, thus they
+ define an edge in DDG (Data Dependence Graph). */
+
+static poly_dr_pair_p
+new_poly_dr_pair (poly_dr_p source,
+ poly_dr_p sink,
+ ppl_Pointset_Powerset_C_Polyhedron_t ddp)
+{
+ poly_dr_pair_p pdrpp;
+
+ pdrpp = XNEW (struct poly_dr_pair);
+ pdrpp->source = source;
+ pdrpp->sink = sink;
+ pdrpp->ddp = ddp;
+
+ return pdrpp;
+}
+
+/* Comparison function for poly_dr_pair hash table. */
+
+int
+eq_poly_dr_pair_p (const void *pdrpp1, const void *pdrpp2)
+{
+ const struct poly_dr_pair *p1 = (const struct poly_dr_pair *) pdrpp1;
+ const struct poly_dr_pair *p2 = (const struct poly_dr_pair *) pdrpp2;
+
+ return (p1->source == p2->source
+ && p1->sink == p2->sink);
+}
+
+/* Hash function for poly_dr_pair hashtable. */
+
+hashval_t
+hash_poly_dr_pair_p (const void *pdrpp)
+{
+ const struct poly_dr_pair *p = (const struct poly_dr_pair *) pdrpp;
+
+ return (hashval_t) ((long) p->source + (long) p->sink);
+}
+
+/* Returns a polyhedron of dimension DIM.
+
+ Maps the dimensions [0, ..., cut - 1] of polyhedron P to OFFSET0
+ and the dimensions [cut, ..., nb_dim] to DIM - GDIM. */
+
+static ppl_Pointset_Powerset_C_Polyhedron_t
+map_into_dep_poly (graphite_dim_t dim, graphite_dim_t gdim,
+ ppl_Pointset_Powerset_C_Polyhedron_t p,
+ graphite_dim_t cut,
+ graphite_dim_t offset)
+{
+ ppl_Pointset_Powerset_C_Polyhedron_t res;
+
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
+ (&res, p);
+ ppl_insert_dimensions_pointset (res, 0, offset);
+ ppl_insert_dimensions_pointset (res, offset + cut,
+ dim - offset - cut - gdim);
+
+ return res;
+}
+
+/* Swap [cut0, ..., cut1] to the end of DR: "a CUT0 b CUT1 c" is
+ transformed into "a CUT0 c CUT1' b"
+
+ Add NB0 zeros before "a": "00...0 a CUT0 c CUT1' b"
+ Add NB1 zeros between "a" and "c": "00...0 a 00...0 c CUT1' b"
+ Add DIM - NB0 - NB1 - PDIM zeros between "c" and "b":
+ "00...0 a 00...0 c 00...0 b". */
+
+static ppl_Pointset_Powerset_C_Polyhedron_t
+map_dr_into_dep_poly (graphite_dim_t dim,
+ ppl_Pointset_Powerset_C_Polyhedron_t dr,
+ graphite_dim_t cut0, graphite_dim_t cut1,
+ graphite_dim_t nb0, graphite_dim_t nb1)
+{
+ ppl_dimension_type pdim;
+ ppl_dimension_type *map;
+ ppl_Pointset_Powerset_C_Polyhedron_t res;
+ ppl_dimension_type i;
+
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
+ (&res, dr);
+ ppl_Pointset_Powerset_C_Polyhedron_space_dimension (res, &pdim);
+
+ map = (ppl_dimension_type *) XNEWVEC (ppl_dimension_type, pdim);
+
+ /* First mapping: move 'g' vector to right position. */
+ for (i = 0; i < cut0; i++)
+ map[i] = i;
+
+ for (i = cut0; i < cut1; i++)
+ map[i] = pdim - cut1 + i;
+
+ for (i = cut1; i < pdim; i++)
+ map[i] = cut0 + i - cut1;
+
+ ppl_Pointset_Powerset_C_Polyhedron_map_space_dimensions (res, map, pdim);
+ free (map);
+
+ /* After swapping 's' and 'g' vectors, we have to update a new cut. */
+ cut1 = pdim - cut1 + cut0;
+
+ ppl_insert_dimensions_pointset (res, 0, nb0);
+ ppl_insert_dimensions_pointset (res, nb0 + cut0, nb1);
+ ppl_insert_dimensions_pointset (res, nb0 + nb1 + cut1,
+ dim - nb0 - nb1 - pdim);
+
+ return res;
+}
+
+/* Builds a constraints of the form "POS1 - POS2 CSTR_TYPE C" */
+
+static ppl_Constraint_t
+build_pairwise_constraint (graphite_dim_t dim,
+ graphite_dim_t pos1, graphite_dim_t pos2,
+ int c, enum ppl_enum_Constraint_Type cstr_type)
+{
+ ppl_Linear_Expression_t expr;
+ ppl_Constraint_t cstr;
+ ppl_Coefficient_t coef;
+ Value v, v_op, v_c;
+
+ value_init (v);
+ value_init (v_op);
+ value_init (v_c);
+
+ value_set_si (v, 1);
+ value_set_si (v_op, -1);
+ value_set_si (v_c, c);
+
+ ppl_new_Coefficient (&coef);
+ ppl_new_Linear_Expression_with_dimension (&expr, dim);
+
+ ppl_assign_Coefficient_from_mpz_t (coef, v);
+ ppl_Linear_Expression_add_to_coefficient (expr, pos1, coef);
+ ppl_assign_Coefficient_from_mpz_t (coef, v_op);
+ ppl_Linear_Expression_add_to_coefficient (expr, pos2, coef);
+ ppl_assign_Coefficient_from_mpz_t (coef, v_c);
+ ppl_Linear_Expression_add_to_inhomogeneous (expr, coef);
+
+ ppl_new_Constraint (&cstr, expr, cstr_type);
+
+ ppl_delete_Linear_Expression (expr);
+ ppl_delete_Coefficient (coef);
+ value_clear (v);
+ value_clear (v_op);
+ value_clear (v_c);
+
+ return cstr;
+}
+
+/* Builds subscript equality constraints. */
+
+static ppl_Pointset_Powerset_C_Polyhedron_t
+dr_equality_constraints (graphite_dim_t dim,
+ graphite_dim_t pos, graphite_dim_t nb_subscripts)
+{
+ ppl_Polyhedron_t subscript_equalities;
+ ppl_Pointset_Powerset_C_Polyhedron_t res;
+ Value v, v_op;
+ graphite_dim_t i;
+
+ value_init (v);
+ value_init (v_op);
+ value_set_si (v, 1);
+ value_set_si (v_op, -1);
+
+ ppl_new_C_Polyhedron_from_space_dimension (&subscript_equalities, dim, 0);
+ for (i = 0; i < nb_subscripts; i++)
+ {
+ ppl_Linear_Expression_t expr;
+ ppl_Constraint_t cstr;
+ ppl_Coefficient_t coef;
+
+ ppl_new_Coefficient (&coef);
+ ppl_new_Linear_Expression_with_dimension (&expr, dim);
+
+ ppl_assign_Coefficient_from_mpz_t (coef, v);
+ ppl_Linear_Expression_add_to_coefficient (expr, pos + i, coef);
+ ppl_assign_Coefficient_from_mpz_t (coef, v_op);
+ ppl_Linear_Expression_add_to_coefficient (expr, pos + i + nb_subscripts,
+ coef);
+
+ ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_EQUAL);
+ ppl_Polyhedron_add_constraint (subscript_equalities, cstr);
+
+ ppl_delete_Linear_Expression (expr);
+ ppl_delete_Constraint (cstr);
+ ppl_delete_Coefficient (coef);
+ }
+
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron
+ (&res, subscript_equalities);
+ value_clear (v);
+ value_clear (v_op);
+ ppl_delete_Polyhedron (subscript_equalities);
+
+ return res;
+}
+
+/* Builds scheduling equality constraints. */
+
+static ppl_Pointset_Powerset_C_Polyhedron_t
+build_pairwise_scheduling_equality (graphite_dim_t dim,
+ graphite_dim_t pos, graphite_dim_t offset)
+{
+ ppl_Pointset_Powerset_C_Polyhedron_t res;
+ ppl_Polyhedron_t equalities;
+ ppl_Constraint_t cstr;
+
+ ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
+
+ cstr = build_pairwise_constraint (dim, pos, pos + offset, 0,
+ PPL_CONSTRAINT_TYPE_EQUAL);
+ ppl_Polyhedron_add_constraint (equalities, cstr);
+ ppl_delete_Constraint (cstr);
+
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
+ ppl_delete_Polyhedron (equalities);
+ return res;
+}
+
+/* Builds scheduling inequality constraints. */
+
+static ppl_Pointset_Powerset_C_Polyhedron_t
+build_pairwise_scheduling_inequality (graphite_dim_t dim,
+ graphite_dim_t pos,
+ graphite_dim_t offset,
+ bool direction)
+{
+ ppl_Pointset_Powerset_C_Polyhedron_t res;
+ ppl_Polyhedron_t equalities;
+ ppl_Constraint_t cstr;
+
+ ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
+
+ if (direction)
+ cstr = build_pairwise_constraint (dim, pos, pos + offset, -1,
+ PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL);
+ else
+ cstr = build_pairwise_constraint (dim, pos, pos + offset, 1,
+ PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL);
+
+ ppl_Polyhedron_add_constraint (equalities, cstr);
+ ppl_delete_Constraint (cstr);
+
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
+ ppl_delete_Polyhedron (equalities);
+ return res;
+}
+
+/* Returns true when adding the lexicographical constraints at level I
+ to the RES dependence polyhedron returns an empty polyhedron. */
+
+static bool
+lexicographically_gt_p (ppl_Pointset_Powerset_C_Polyhedron_t res,
+ graphite_dim_t dim,
+ graphite_dim_t offset,
+ bool direction, graphite_dim_t i)
+{
+ ppl_Pointset_Powerset_C_Polyhedron_t ineq;
+ bool empty_p;
+
+ ineq = build_pairwise_scheduling_inequality (dim, i, offset,
+ direction);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (ineq, res);
+ empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (ineq);
+ if (!empty_p)
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, ineq);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (ineq);
+
+ return !empty_p;
+}
+
+/* Build the precedence constraints for the lexicographical comparison
+ of time vectors RES following the lexicographical order. */
+
+static void
+build_lexicographically_gt_constraint (ppl_Pointset_Powerset_C_Polyhedron_t *res,
+ graphite_dim_t dim,
+ graphite_dim_t tdim1,
+ graphite_dim_t offset,
+ bool direction)
+{
+ graphite_dim_t i;
+
+ if (lexicographically_gt_p (*res, dim, offset, direction, 0))
+ return;
+
+ for (i = 0; i < tdim1 - 1; i++)
+ {
+ ppl_Pointset_Powerset_C_Polyhedron_t sceq;
+
+ sceq = build_pairwise_scheduling_equality (dim, i, offset);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (*res, sceq);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (sceq);
+
+ if (lexicographically_gt_p (*res, dim, offset, direction, i + 1))
+ return;
+ }
+
+ if (i == tdim1 - 1)
+ {
+ ppl_delete_Pointset_Powerset_C_Polyhedron (*res);
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (res, dim, 1);
+ }
+}
+
+/* Build the dependence polyhedron for data references PDR1 and PDR2. */
+
+static ppl_Pointset_Powerset_C_Polyhedron_t
+dependence_polyhedron_1 (poly_bb_p pbb1, poly_bb_p pbb2,
+ ppl_Pointset_Powerset_C_Polyhedron_t d1,
+ ppl_Pointset_Powerset_C_Polyhedron_t d2,
+ poly_dr_p pdr1, poly_dr_p pdr2,
+ ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
+ bool direction,
+ bool original_scattering_p)
+{
+ scop_p scop = PBB_SCOP (pbb1);
+ graphite_dim_t tdim1 = original_scattering_p ?
+ pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
+ graphite_dim_t tdim2 = original_scattering_p ?
+ pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
+ graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
+ graphite_dim_t ddim2 = pbb_dim_iter_domain (pbb2);
+ graphite_dim_t sdim1 = pdr_nb_subscripts (pdr1) + 1;
+ graphite_dim_t gdim = scop_nb_params (scop);
+ graphite_dim_t dim1 = pdr_dim (pdr1);
+ graphite_dim_t dim2 = pdr_dim (pdr2);
+ graphite_dim_t dim = tdim1 + tdim2 + dim1 + dim2;
+ ppl_Pointset_Powerset_C_Polyhedron_t res;
+ ppl_Pointset_Powerset_C_Polyhedron_t id1, id2, isc1, isc2, idr1, idr2;
+ ppl_Pointset_Powerset_C_Polyhedron_t sc1, sc2, dreq;
+
+ gcc_assert (PBB_SCOP (pbb1) == PBB_SCOP (pbb2));
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc1, s1);
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc2, s2);
+
+ id1 = map_into_dep_poly (dim, gdim, d1, ddim1, tdim1);
+ id2 = map_into_dep_poly (dim, gdim, d2, ddim2, tdim1 + ddim1 + tdim2);
+ isc1 = map_into_dep_poly (dim, gdim, sc1, ddim1 + tdim1, 0);
+ isc2 = map_into_dep_poly (dim, gdim, sc2, ddim2 + tdim2, tdim1 + ddim1);
+
+ idr1 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr1), ddim1, ddim1 + gdim,
+ tdim1, tdim2 + ddim2);
+ idr2 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr2), ddim2, ddim2 + gdim,
+ tdim1 + ddim1 + tdim2, sdim1);
+
+ /* Now add the subscript equalities. */
+ dreq = dr_equality_constraints (dim, tdim1 + ddim1 + tdim2 + ddim2, sdim1);
+
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 0);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id1);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id2);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc1);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc2);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr1);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr2);
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, dreq);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (id1);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (id2);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (sc1);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (sc2);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (isc1);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (isc2);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (idr1);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (idr2);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (dreq);
+
+ if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (res))
+ build_lexicographically_gt_constraint (&res, dim, MIN (tdim1, tdim2),
+ tdim1 + ddim1, direction);
+ return res;
+}
+
+/* Build the dependence polyhedron for data references PDR1 and PDR2.
+ If possible use already cached information. */
+
+static ppl_Pointset_Powerset_C_Polyhedron_t
+dependence_polyhedron (poly_bb_p pbb1, poly_bb_p pbb2,
+ ppl_Pointset_Powerset_C_Polyhedron_t d1,
+ ppl_Pointset_Powerset_C_Polyhedron_t d2,
+ poly_dr_p pdr1, poly_dr_p pdr2,
+ ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
+ bool direction,
+ bool original_scattering_p)
+{
+ poly_dr_pair tmp;
+ PTR *x = NULL;
+ ppl_Pointset_Powerset_C_Polyhedron_t res;
+
+ if (original_scattering_p)
+ {
+ tmp.source = pdr1;
+ tmp.sink = pdr2;
+ x = htab_find_slot (SCOP_ORIGINAL_PDR_PAIRS (PBB_SCOP (pbb1)),
+ &tmp, INSERT);
+
+ if (x && *x)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\nddp cache: hit.\n");
+ return ((poly_dr_pair *)*x)->ddp;
+ }
+ else if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\nddp cache: miss.\n");
+ }
+
+ res = dependence_polyhedron_1 (pbb1, pbb2, d1, d2, pdr1, pdr2,
+ s1, s2, direction, original_scattering_p);
+
+ if (original_scattering_p)
+ {
+ gcc_assert (x && *x == NULL);
+ *x = new_poly_dr_pair (pdr1, pdr2, res);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\nddp cache: add element.\n");
+ }
+
+ return res;
+}
+
+/* Returns true when the PBB_TRANSFORMED_SCATTERING functions of PBB1
+ and PBB2 respect the data dependences of PBB_ORIGINAL_SCATTERING
+ functions. */
+
+static bool
+graphite_legal_transform_dr (poly_bb_p pbb1, poly_bb_p pbb2,
+ poly_dr_p pdr1, poly_dr_p pdr2)
+{
+ ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
+ ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
+ ppl_Polyhedron_t so1 = PBB_ORIGINAL_SCATTERING (pbb1);
+ ppl_Polyhedron_t so2 = PBB_ORIGINAL_SCATTERING (pbb2);
+ ppl_Pointset_Powerset_C_Polyhedron_t po;
+
+ graphite_dim_t sdim1 = pdr_nb_subscripts (pdr1) + 1;
+ graphite_dim_t sdim2 = pdr_nb_subscripts (pdr2) + 1;
+
+ if (sdim1 != sdim2)
+ return true;
+
+ po = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
+ true, true);
+
+ if (ppl_Pointset_Powerset_C_Polyhedron_is_empty (po))
+ return true;
+ else
+ {
+ ppl_Polyhedron_t st1 = PBB_TRANSFORMED_SCATTERING (pbb1);
+ ppl_Polyhedron_t st2 = PBB_TRANSFORMED_SCATTERING (pbb2);
+ ppl_Pointset_Powerset_C_Polyhedron_t pt;
+ graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
+ graphite_dim_t otdim1 = pbb_nb_scattering_orig (pbb1);
+ graphite_dim_t otdim2 = pbb_nb_scattering_orig (pbb2);
+ graphite_dim_t ttdim1 = pbb_nb_scattering_transform (pbb1);
+ graphite_dim_t ttdim2 = pbb_nb_scattering_transform (pbb2);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\nloop carries dependency.\n");
+ pt = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, st1, st2,
+ false, false);
+
+ /* Extend PO and PT to have the same dimensions. */
+ ppl_insert_dimensions_pointset (po, otdim1, ttdim1);
+ ppl_insert_dimensions_pointset (po, otdim1 + ttdim1 + ddim1 + otdim2,
+ ttdim2);
+ ppl_insert_dimensions_pointset (pt, 0, otdim1);
+ ppl_insert_dimensions_pointset (pt, otdim1 + ttdim1 + ddim1, otdim2);
+
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (po, pt);
+ return ppl_Pointset_Powerset_C_Polyhedron_is_empty (po);
+ }
+}
+
+/* Iterates over the data references of PBB1 and PBB2 and detect
+ whether the transformed schedule is correct. */
+
+static bool
+graphite_legal_transform_bb (poly_bb_p pbb1, poly_bb_p pbb2)
+{
+ int i, j;
+ poly_dr_p pdr1, pdr2;
+
+ for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
+ for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
+ if (!graphite_legal_transform_dr (pbb1, pbb2, pdr1, pdr2))
+ return false;
+ return true;
+}
+
+/* Iterates over the SCOP and detect whether the transformed schedule
+ is correct. */
+
+bool
+graphite_legal_transform (scop_p scop)
+{
+ int i, j;
+ poly_bb_p pbb1, pbb2;
+
+ for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
+ for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
+ if (!graphite_legal_transform_bb (pbb1, pbb2))
+ return false;
+
+ return true;
+}
+
+/* Remove all the dimensions except alias information at dimension
+ ALIAS_DIM. */
+
+static void
+build_alias_set_powerset (ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset,
+ ppl_dimension_type alias_dim)
+{
+ ppl_dimension_type *ds;
+ ppl_dimension_type access_dim;
+ unsigned i, pos = 0;
+
+ ppl_Pointset_Powerset_C_Polyhedron_space_dimension (alias_powerset,
+ &access_dim);
+ ds = XNEWVEC (ppl_dimension_type, access_dim-1);
+ for (i = 0; i < access_dim; i++)
+ {
+ if (i == alias_dim)
+ continue;
+
+ ds[pos] = i;
+ pos++;
+ }
+
+ ppl_Pointset_Powerset_C_Polyhedron_remove_space_dimensions (alias_powerset,
+ ds,
+ access_dim - 1);
+ free (ds);
+}
+
+/* Return true when PDR1 and PDR2 may alias. */
+
+static bool
+poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2)
+{
+ ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset1, alias_powerset2;
+ ppl_Pointset_Powerset_C_Polyhedron_t accesses1 = PDR_ACCESSES (pdr1);
+ ppl_Pointset_Powerset_C_Polyhedron_t accesses2 = PDR_ACCESSES (pdr2);
+ ppl_dimension_type alias_dim1 = pdr_alias_set_dim (pdr1);
+ ppl_dimension_type alias_dim2 = pdr_alias_set_dim (pdr2);
+ int empty_p;
+
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
+ (&alias_powerset1, accesses1);
+ ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
+ (&alias_powerset2, accesses2);
+
+ build_alias_set_powerset (alias_powerset1, alias_dim1);
+ build_alias_set_powerset (alias_powerset2, alias_dim2);
+
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign
+ (alias_powerset1, alias_powerset2);
+
+ empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (alias_powerset1);
+
+ ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset1);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset2);
+
+ return !empty_p;
+}
+
+/* Returns TRUE when the dependence polyhedron between PDR1 and
+ PDR2 represents a loop carried dependence at level LEVEL. Otherwise
+ return FALSE. */
+
+static bool
+graphite_carried_dependence_level_k (poly_dr_p pdr1, poly_dr_p pdr2,
+ int level)
+{
+ poly_bb_p pbb1 = PDR_PBB (pdr1);
+ poly_bb_p pbb2 = PDR_PBB (pdr2);
+ ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
+ ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
+ ppl_Polyhedron_t so1 = PBB_TRANSFORMED_SCATTERING (pbb1);
+ ppl_Polyhedron_t so2 = PBB_TRANSFORMED_SCATTERING (pbb2);
+ ppl_Pointset_Powerset_C_Polyhedron_t po;
+ ppl_Pointset_Powerset_C_Polyhedron_t eqpp;
+ graphite_dim_t sdim1 = pdr_nb_subscripts (pdr1) + 1;
+ graphite_dim_t sdim2 = pdr_nb_subscripts (pdr2) + 1;
+ graphite_dim_t tdim1 = pbb_nb_scattering_transform (pbb1);
+ graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
+ ppl_dimension_type dim;
+ bool empty_p;
+
+ if ((PDR_TYPE (pdr1) == PDR_READ && PDR_TYPE (pdr2) == PDR_READ)
+ || !poly_drs_may_alias_p (pdr1, pdr2))
+ return false;
+
+ if (sdim1 != sdim2)
+ return true;
+
+ po = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
+ true, false);
+ if (ppl_Pointset_Powerset_C_Polyhedron_is_empty (po))
+ {
+ ppl_delete_Pointset_Powerset_C_Polyhedron (po);
+ return false;
+ }
+
+ ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &dim);
+ eqpp = build_pairwise_scheduling_inequality (dim, level, tdim1 + ddim1, 1);
+
+ ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (eqpp, po);
+ empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (eqpp);
+
+ ppl_delete_Pointset_Powerset_C_Polyhedron (po);
+ ppl_delete_Pointset_Powerset_C_Polyhedron (eqpp);
+ return !empty_p;
+}
+
+/* Check data dependency between PBB1 and PBB2 at level LEVEL. */
+
+bool
+dependency_between_pbbs_p (poly_bb_p pbb1, poly_bb_p pbb2, int level)
+{
+ int i, j;
+ poly_dr_p pdr1, pdr2;
+
+ for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
+ for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
+ if (graphite_carried_dependence_level_k (pdr1, pdr2, level))
+ return true;
+
+ return false;
+}
+
+#endif