* gimple.h: Remove all includes. (recalculate_side_effects): Move prototype to gimplify.h. * Makefile.in (PLUGIN_HEADERS): Add flattened gimple.h includes. * gengtype.c (open_base_files): Add gimple.h include list. * gimplify.h (recalculate_side_effects): Relocate prototype here. * gimple.c: Adjust include list. (recalculate_side_effects): Move to gimplify.c. * gimplify.c: Adjust include list. (recalculate_side_effects): Relocate from gimple.c. * alias.c: Add required include files removed from gimple.h. * asan.c: Likewise. * builtins.c: Likewise. * calls.c: Likewise. * cfgexpand.c: Likewise. * cfgloop.c: Likewise. * cfgloopmanip.c: Likewise. * cgraphbuild.c: Likewise. * cgraph.c: Likewise. * cgraphclones.c: Likewise. * cgraphunit.c: Likewise. * cilk-common.c: Likewise. * data-streamer.c: Likewise. * data-streamer-in.c: Likewise. * data-streamer-out.c: Likewise. * dse.c: Likewise. * dwarf2out.c: Likewise. * emit-rtl.c: Likewise. * except.c: Likewise. * expr.c: Likewise. * fold-const.c: Likewise. * function.c: Likewise. * gimple-builder.c: Likewise. * gimple-expr.c: Likewise. * gimple-fold.c: Likewise. * gimple-iterator.c: Likewise. * gimple-low.c: Likewise. * gimple-pretty-print.c: Likewise. * gimple-ssa-isolate-paths.c: Likewise. * gimple-ssa-strength-reduction.c: Likewise. * gimple-streamer-in.c: Likewise. * gimple-streamer-out.c: Likewise. * gimple-walk.c: Likewise. * gimplify-me.c: Likewise. * graphite-blocking.c: Likewise. * graphite.c: Likewise. * graphite-clast-to-gimple.c: Likewise. * graphite-dependences.c: Likewise. * graphite-interchange.c: Likewise. * graphite-optimize-isl.c: Likewise. * graphite-poly.c: Likewise. * graphite-scop-detection.c: Likewise. * graphite-sese-to-poly.c: Likewise. * internal-fn.c: Likewise. * ipa.c: Likewise. * ipa-cp.c: Likewise. * ipa-devirt.c: Likewise. * ipa-inline-analysis.c: Likewise. * ipa-inline.c: Likewise. * ipa-profile.c: Likewise. * ipa-prop.c: Likewise. * ipa-pure-const.c: Likewise. * ipa-reference.c: Likewise. * ipa-split.c: Likewise. * ipa-utils.c: Likewise. * langhooks.c: Likewise. * lto-cgraph.c: Likewise. * lto-compress.c: Likewise. * lto-opts.c: Likewise. * lto-section-in.c: Likewise. * lto-section-out.c: Likewise. * lto-streamer.c: Likewise. * lto-streamer-in.c: Likewise. * lto-streamer-out.c: Likewise. * omp-low.c: Likewise. * opts-global.c: Likewise. * passes.c: Likewise. * predict.c: Likewise. * profile.c: Likewise. * sese.c: Likewise. * stmt.c: Likewise. * stor-layout.c: Likewise. * symtab.c: Likewise. * targhooks.c: Likewise. * toplev.c: Likewise. * tracer.c: Likewise. * trans-mem.c: Likewise. * tree-affine.c: Likewise. * tree.c: Likewise. * tree-call-cdce.c: Likewise. * tree-cfg.c: Likewise. * tree-cfgcleanup.c: Likewise. * tree-chrec.c: Likewise. * tree-complex.c: Likewise. * tree-data-ref.c: Likewise. * tree-dfa.c: Likewise. * tree-eh.c: Likewise. * tree-emutls.c: Likewise. * tree-if-conv.c: Likewise. * tree-inline.c: Likewise. * tree-into-ssa.c: Likewise. * tree-loop-distribution.c: Likewise. * tree-nested.c: Likewise. * tree-nrv.c: Likewise. * tree-object-size.c: Likewise. * tree-outof-ssa.c: Likewise. * tree-parloops.c: Likewise. * tree-phinodes.c: Likewise. * tree-predcom.c: Likewise. * tree-pretty-print.c: Likewise. * tree-profile.c: Likewise. * tree-scalar-evolution.c: Likewise. * tree-sra.c: Likewise. * tree-ssa-address.c: Likewise. * tree-ssa-alias.c: Likewise. * tree-ssa.c: Likewise. * tree-ssa-ccp.c: Likewise. * tree-ssa-coalesce.c: Likewise. * tree-ssa-copy.c: Likewise. * tree-ssa-copyrename.c: Likewise. * tree-ssa-dce.c: Likewise. * tree-ssa-dom.c: Likewise. * tree-ssa-dse.c: Likewise. * tree-ssa-forwprop.c: Likewise. * tree-ssa-ifcombine.c: Likewise. * tree-ssa-live.c: Likewise. * tree-ssa-loop.c: Likewise. * tree-ssa-loop-ch.c: Likewise. * tree-ssa-loop-im.c: Likewise. * tree-ssa-loop-ivcanon.c: Likewise. * tree-ssa-loop-ivopts.c: Likewise. * tree-ssa-loop-manip.c: Likewise. * tree-ssa-loop-niter.c: Likewise. * tree-ssa-loop-prefetch.c: Likewise. * tree-ssa-loop-unswitch.c: Likewise. * tree-ssa-math-opts.c: Likewise. * tree-ssanames.c: Likewise. * tree-ssa-operands.c: Likewise. * tree-ssa-phiopt.c: Likewise. * tree-ssa-phiprop.c: Likewise. * tree-ssa-pre.c: Likewise. * tree-ssa-propagate.c: Likewise. * tree-ssa-reassoc.c: Likewise. * tree-ssa-sccvn.c: Likewise. * tree-ssa-sink.c: Likewise. * tree-ssa-strlen.c: Likewise. * tree-ssa-structalias.c: Likewise. * tree-ssa-tail-merge.c: Likewise. * tree-ssa-ter.c: Likewise. * tree-ssa-threadedge.c: Likewise. * tree-ssa-threadupdate.c: Likewise. * tree-ssa-uncprop.c: Likewise. * tree-ssa-uninit.c: Likewise. * tree-stdarg.c: Likewise. * tree-streamer.c: Likewise. * tree-streamer-in.c: Likewise. * tree-streamer-out.c: Likewise. * tree-switch-conversion.c: Likewise. * tree-tailcall.c: Likewise. * tree-vect-data-refs.c: Likewise. * tree-vect-generic.c: Likewise. * tree-vect-loop.c: Likewise. * tree-vect-loop-manip.c: Likewise. * tree-vectorizer.c: Likewise. * tree-vect-patterns.c: Likewise. * tree-vect-slp.c: Likewise. * tree-vect-stmts.c: Likewise. * tree-vrp.c: Likewise. * tsan.c: Likewise. * ubsan.c: Likewise. * value-prof.c: Likewise. * varpool.c: Likewise. * var-tracking.c: Likewise. * vtable-verify.c: Likewise. * ada/gcc-interface/trans.c: Add required include files from gimple.h. * c/c-typeck.c: Add required include files from gimple.h. * c-family/c-common.c: Add required include files from gimple.h. * c-family/c-gimplify.c: Likewise * c-family/cilk.c: Likewise * cp/class.c: Add required include files from gimple.h. * cp/cp-gimplify.c: Likewise * cp/decl2.c: Likewise * cp/init.c: Likewise * cp/optimize.c: Likewise * cp/pt.c: Likewise * cp/semantics.c: Likewise * cp/tree.c: Likewise * cp/typeck.c: Likewise * cp/vtable-class-hierarchy.c: Likewise * fortran/trans.c: Add required include files from gimple.h. * fortran/trans-expr.c: Likewise * fortran/trans-openmp.c: Likewise * go/gofrontend/expressions.cc: Add required include files from gimple.h. * go/gofrontend/gogo-tree.cc: Likewise * go/gofrontend/types.cc: Likewise * go/go-gcc.cc: Likewise * go/go-lang.c: Likewise * java/java-gimplify.c: Add required include files from gimple.h. * lto/lto.c: Add required include files from gimple.h. * lto/lto-lang.c: Likewise * lto/lto-object.c: Likewise * lto/lto-partition.c: Likewise * lto/lto-symtab.c: Likewise * objc/objc-act.c: Add required include files from gimple.h. * config/darwin.c: Add required include files removed from gimple.h. * config/aarch64/aarch64-builtins.c: Likewise. * config/aarch64/aarch64.c: Likewise. * config/alpha/alpha.c: Likewise. * config/i386/i386.c: Likewise. * config/i386/winnt.c: Likewise. * config/ia64/ia64.c: Likewise. * config/m32c/m32c.c: Likewise. * config/mep/mep.c: Likewise. * config/mips/mips.c: Likewise. * config/rs6000/rs6000.c: Likewise. * config/s390/s390.c: Likewise. * config/sh/sh.c: Likewise. * config/sparc/sparc.c: Likewise. * config/spu/spu.c: Likewise. * config/stormy16/stormy16.c: Likewise. * config/tilegx/tilegx.c: Likewise. * config/tilepro/tilepro.c: Likewise. * config/xtensa/xtensa.c: Likewise. * testsuite/gcc.dg/plugin/finish_unit_plugin.c: Add required include files removed from gimple.h. * testsuite/gcc.dg/plugin/ggcplug.c: Likewise. * testsuite/gcc.dg/plugin/one_time_plugin.c: Likewise. * testsuite/gcc.dg/plugin/selfassign.c: Likewise. * testsuite/gcc.dg/plugin/start_unit_plugin.c: Likewise. * testsuite/g++.dg/plugin/selfassign.c: Likewise. From-SVN: r205272
605 lines
17 KiB
C
605 lines
17 KiB
C
/* Data dependence analysis for Graphite.
|
|
Copyright (C) 2009-2013 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"
|
|
|
|
#ifdef HAVE_cloog
|
|
#include <isl/set.h>
|
|
#include <isl/map.h>
|
|
#include <isl/union_map.h>
|
|
#include <isl/flow.h>
|
|
#include <isl/constraint.h>
|
|
#include <cloog/cloog.h>
|
|
#include <cloog/isl/domain.h>
|
|
#endif
|
|
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "tree.h"
|
|
#include "basic-block.h"
|
|
#include "tree-ssa-alias.h"
|
|
#include "internal-fn.h"
|
|
#include "gimple-expr.h"
|
|
#include "is-a.h"
|
|
#include "gimple.h"
|
|
#include "gimple-iterator.h"
|
|
#include "tree-ssa-loop.h"
|
|
#include "tree-pass.h"
|
|
#include "cfgloop.h"
|
|
#include "tree-chrec.h"
|
|
#include "tree-data-ref.h"
|
|
#include "tree-scalar-evolution.h"
|
|
#include "sese.h"
|
|
|
|
#ifdef HAVE_cloog
|
|
#include "graphite-poly.h"
|
|
#include "graphite-htab.h"
|
|
|
|
/* Add the constraints from the set S to the domain of MAP. */
|
|
|
|
static isl_map *
|
|
constrain_domain (isl_map *map, isl_set *s)
|
|
{
|
|
isl_space *d = isl_map_get_space (map);
|
|
isl_id *id = isl_space_get_tuple_id (d, isl_dim_in);
|
|
|
|
s = isl_set_set_tuple_id (s, id);
|
|
isl_space_free (d);
|
|
return isl_map_intersect_domain (map, s);
|
|
}
|
|
|
|
/* Constrain pdr->accesses with pdr->extent and pbb->domain. */
|
|
|
|
static isl_map *
|
|
add_pdr_constraints (poly_dr_p pdr, poly_bb_p pbb)
|
|
{
|
|
isl_map *x = isl_map_intersect_range (isl_map_copy (pdr->accesses),
|
|
isl_set_copy (pdr->extent));
|
|
x = constrain_domain (x, isl_set_copy (pbb->domain));
|
|
return x;
|
|
}
|
|
|
|
/* Returns all the memory reads in SCOP. */
|
|
|
|
static isl_union_map *
|
|
scop_get_reads (scop_p scop, vec<poly_bb_p> pbbs)
|
|
{
|
|
int i, j;
|
|
poly_bb_p pbb;
|
|
poly_dr_p pdr;
|
|
isl_space *space = isl_set_get_space (scop->context);
|
|
isl_union_map *res = isl_union_map_empty (space);
|
|
|
|
FOR_EACH_VEC_ELT (pbbs, i, pbb)
|
|
{
|
|
FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
|
|
if (pdr_read_p (pdr))
|
|
res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/* Returns all the memory must writes in SCOP. */
|
|
|
|
static isl_union_map *
|
|
scop_get_must_writes (scop_p scop, vec<poly_bb_p> pbbs)
|
|
{
|
|
int i, j;
|
|
poly_bb_p pbb;
|
|
poly_dr_p pdr;
|
|
isl_space *space = isl_set_get_space (scop->context);
|
|
isl_union_map *res = isl_union_map_empty (space);
|
|
|
|
FOR_EACH_VEC_ELT (pbbs, i, pbb)
|
|
{
|
|
FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
|
|
if (pdr_write_p (pdr))
|
|
res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/* Returns all the memory may writes in SCOP. */
|
|
|
|
static isl_union_map *
|
|
scop_get_may_writes (scop_p scop, vec<poly_bb_p> pbbs)
|
|
{
|
|
int i, j;
|
|
poly_bb_p pbb;
|
|
poly_dr_p pdr;
|
|
isl_space *space = isl_set_get_space (scop->context);
|
|
isl_union_map *res = isl_union_map_empty (space);
|
|
|
|
FOR_EACH_VEC_ELT (pbbs, i, pbb)
|
|
{
|
|
FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
|
|
if (pdr_may_write_p (pdr))
|
|
res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/* Returns all the original schedules in SCOP. */
|
|
|
|
static isl_union_map *
|
|
scop_get_original_schedule (scop_p scop, vec<poly_bb_p> pbbs)
|
|
{
|
|
int i;
|
|
poly_bb_p pbb;
|
|
isl_space *space = isl_set_get_space (scop->context);
|
|
isl_union_map *res = isl_union_map_empty (space);
|
|
|
|
FOR_EACH_VEC_ELT (pbbs, i, pbb)
|
|
{
|
|
res = isl_union_map_add_map
|
|
(res, constrain_domain (isl_map_copy (pbb->schedule),
|
|
isl_set_copy (pbb->domain)));
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/* Returns all the transformed schedules in SCOP. */
|
|
|
|
static isl_union_map *
|
|
scop_get_transformed_schedule (scop_p scop, vec<poly_bb_p> pbbs)
|
|
{
|
|
int i;
|
|
poly_bb_p pbb;
|
|
isl_space *space = isl_set_get_space (scop->context);
|
|
isl_union_map *res = isl_union_map_empty (space);
|
|
|
|
FOR_EACH_VEC_ELT (pbbs, i, pbb)
|
|
{
|
|
res = isl_union_map_add_map
|
|
(res, constrain_domain (isl_map_copy (pbb->transformed),
|
|
isl_set_copy (pbb->domain)));
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/* Helper function used on each MAP of a isl_union_map. Computes the
|
|
maximal output dimension. */
|
|
|
|
static int
|
|
max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
|
|
{
|
|
int global_max = *((int *) user);
|
|
isl_space *space = isl_map_get_space (map);
|
|
int nb_out = isl_space_dim (space, isl_dim_out);
|
|
|
|
if (global_max < nb_out)
|
|
*((int *) user) = nb_out;
|
|
|
|
isl_map_free (map);
|
|
isl_space_free (space);
|
|
return 0;
|
|
}
|
|
|
|
/* Extends the output dimension of MAP to MAX dimensions. */
|
|
|
|
static __isl_give isl_map *
|
|
extend_map (__isl_take isl_map *map, int max)
|
|
{
|
|
isl_space *space = isl_map_get_space (map);
|
|
int n = isl_space_dim (space, isl_dim_out);
|
|
|
|
isl_space_free (space);
|
|
return isl_map_add_dims (map, isl_dim_out, max - n);
|
|
}
|
|
|
|
/* Structure used to pass parameters to extend_schedule_1. */
|
|
|
|
struct extend_schedule_str {
|
|
int max;
|
|
isl_union_map *umap;
|
|
};
|
|
|
|
/* Helper function for extend_schedule. */
|
|
|
|
static int
|
|
extend_schedule_1 (__isl_take isl_map *map, void *user)
|
|
{
|
|
struct extend_schedule_str *str = (struct extend_schedule_str *) user;
|
|
str->umap = isl_union_map_add_map (str->umap, extend_map (map, str->max));
|
|
return 0;
|
|
}
|
|
|
|
/* Return a relation that has uniform output dimensions. */
|
|
|
|
__isl_give isl_union_map *
|
|
extend_schedule (__isl_take isl_union_map *x)
|
|
{
|
|
int max = 0;
|
|
int res;
|
|
struct extend_schedule_str str;
|
|
|
|
res = isl_union_map_foreach_map (x, max_number_of_out_dimensions, (void *) &max);
|
|
gcc_assert (res == 0);
|
|
|
|
str.max = max;
|
|
str.umap = isl_union_map_empty (isl_union_map_get_space (x));
|
|
res = isl_union_map_foreach_map (x, extend_schedule_1, (void *) &str);
|
|
gcc_assert (res == 0);
|
|
|
|
isl_union_map_free (x);
|
|
return str.umap;
|
|
}
|
|
|
|
/* Applies SCHEDULE to the in and out dimensions of the dependences
|
|
DEPS and return the resulting relation. */
|
|
|
|
static isl_map *
|
|
apply_schedule_on_deps (__isl_keep isl_union_map *schedule,
|
|
__isl_keep isl_union_map *deps)
|
|
{
|
|
isl_map *x;
|
|
isl_union_map *ux, *trans;
|
|
|
|
trans = isl_union_map_copy (schedule);
|
|
trans = extend_schedule (trans);
|
|
ux = isl_union_map_copy (deps);
|
|
ux = isl_union_map_apply_domain (ux, isl_union_map_copy (trans));
|
|
ux = isl_union_map_apply_range (ux, trans);
|
|
x = isl_map_from_union_map (ux);
|
|
|
|
return x;
|
|
}
|
|
|
|
/* Return true when SCHEDULE does not violate the data DEPS: that is
|
|
when the intersection of LEX with the DEPS transformed by SCHEDULE
|
|
is empty. LEX is the relation in which the outputs occur before
|
|
the inputs. */
|
|
|
|
static bool
|
|
no_violations (__isl_keep isl_union_map *schedule,
|
|
__isl_keep isl_union_map *deps)
|
|
{
|
|
bool res;
|
|
isl_space *space;
|
|
isl_map *lex, *x;
|
|
|
|
if (isl_union_map_is_empty (deps))
|
|
return true;
|
|
|
|
x = apply_schedule_on_deps (schedule, deps);
|
|
space = isl_map_get_space (x);
|
|
space = isl_space_range (space);
|
|
lex = isl_map_lex_ge (space);
|
|
x = isl_map_intersect (x, lex);
|
|
res = isl_map_is_empty (x);
|
|
|
|
isl_map_free (x);
|
|
return res;
|
|
}
|
|
|
|
/* Return true when DEPS is non empty and the intersection of LEX with
|
|
the DEPS transformed by SCHEDULE is non empty. LEX is the relation
|
|
in which all the inputs before DEPTH occur at the same time as the
|
|
output, and the input at DEPTH occurs before output. */
|
|
|
|
static bool
|
|
carries_deps (__isl_keep isl_union_map *schedule,
|
|
__isl_keep isl_union_map *deps,
|
|
int depth)
|
|
{
|
|
bool res;
|
|
int i;
|
|
isl_space *space;
|
|
isl_map *lex, *x;
|
|
isl_constraint *ineq;
|
|
|
|
if (isl_union_map_is_empty (deps))
|
|
return false;
|
|
|
|
x = apply_schedule_on_deps (schedule, deps);
|
|
space = isl_map_get_space (x);
|
|
space = isl_space_range (space);
|
|
lex = isl_map_lex_le (space);
|
|
space = isl_map_get_space (x);
|
|
ineq = isl_inequality_alloc (isl_local_space_from_space (space));
|
|
|
|
for (i = 0; i < depth - 1; i++)
|
|
lex = isl_map_equate (lex, isl_dim_in, i, isl_dim_out, i);
|
|
|
|
/* in + 1 <= out */
|
|
ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, depth - 1, 1);
|
|
ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, depth - 1, -1);
|
|
ineq = isl_constraint_set_constant_si (ineq, -1);
|
|
lex = isl_map_add_constraint (lex, ineq);
|
|
x = isl_map_intersect (x, lex);
|
|
res = !isl_map_is_empty (x);
|
|
|
|
isl_map_free (x);
|
|
return res;
|
|
}
|
|
|
|
/* Subtract from the RAW, WAR, and WAW dependences those relations
|
|
that have been marked as belonging to an associative commutative
|
|
reduction. */
|
|
|
|
static void
|
|
subtract_commutative_associative_deps (scop_p scop,
|
|
vec<poly_bb_p> pbbs,
|
|
isl_union_map *original,
|
|
isl_union_map **must_raw,
|
|
isl_union_map **may_raw,
|
|
isl_union_map **must_raw_no_source,
|
|
isl_union_map **may_raw_no_source,
|
|
isl_union_map **must_war,
|
|
isl_union_map **may_war,
|
|
isl_union_map **must_war_no_source,
|
|
isl_union_map **may_war_no_source,
|
|
isl_union_map **must_waw,
|
|
isl_union_map **may_waw,
|
|
isl_union_map **must_waw_no_source,
|
|
isl_union_map **may_waw_no_source)
|
|
{
|
|
int i, j;
|
|
poly_bb_p pbb;
|
|
poly_dr_p pdr;
|
|
isl_space *space = isl_set_get_space (scop->context);
|
|
|
|
FOR_EACH_VEC_ELT (pbbs, i, pbb)
|
|
if (PBB_IS_REDUCTION (pbb))
|
|
{
|
|
int res;
|
|
isl_union_map *r = isl_union_map_empty (isl_space_copy (space));
|
|
isl_union_map *must_w = isl_union_map_empty (isl_space_copy (space));
|
|
isl_union_map *may_w = isl_union_map_empty (isl_space_copy (space));
|
|
isl_union_map *all_w;
|
|
isl_union_map *empty;
|
|
isl_union_map *x_must_raw;
|
|
isl_union_map *x_may_raw;
|
|
isl_union_map *x_must_raw_no_source;
|
|
isl_union_map *x_may_raw_no_source;
|
|
isl_union_map *x_must_war;
|
|
isl_union_map *x_may_war;
|
|
isl_union_map *x_must_war_no_source;
|
|
isl_union_map *x_may_war_no_source;
|
|
isl_union_map *x_must_waw;
|
|
isl_union_map *x_may_waw;
|
|
isl_union_map *x_must_waw_no_source;
|
|
isl_union_map *x_may_waw_no_source;
|
|
|
|
FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
|
|
if (pdr_read_p (pdr))
|
|
r = isl_union_map_add_map (r, add_pdr_constraints (pdr, pbb));
|
|
|
|
FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
|
|
if (pdr_write_p (pdr))
|
|
must_w = isl_union_map_add_map (must_w,
|
|
add_pdr_constraints (pdr, pbb));
|
|
|
|
FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
|
|
if (pdr_may_write_p (pdr))
|
|
may_w = isl_union_map_add_map (may_w,
|
|
add_pdr_constraints (pdr, pbb));
|
|
|
|
all_w = isl_union_map_union
|
|
(isl_union_map_copy (must_w), isl_union_map_copy (may_w));
|
|
empty = isl_union_map_empty (isl_union_map_get_space (all_w));
|
|
|
|
res = isl_union_map_compute_flow (isl_union_map_copy (r),
|
|
isl_union_map_copy (must_w),
|
|
isl_union_map_copy (may_w),
|
|
isl_union_map_copy (original),
|
|
&x_must_raw, &x_may_raw,
|
|
&x_must_raw_no_source,
|
|
&x_may_raw_no_source);
|
|
gcc_assert (res == 0);
|
|
res = isl_union_map_compute_flow (isl_union_map_copy (all_w),
|
|
r, empty,
|
|
isl_union_map_copy (original),
|
|
&x_must_war, &x_may_war,
|
|
&x_must_war_no_source,
|
|
&x_may_war_no_source);
|
|
gcc_assert (res == 0);
|
|
res = isl_union_map_compute_flow (all_w, must_w, may_w,
|
|
isl_union_map_copy (original),
|
|
&x_must_waw, &x_may_waw,
|
|
&x_must_waw_no_source,
|
|
&x_may_waw_no_source);
|
|
gcc_assert (res == 0);
|
|
|
|
*must_raw = isl_union_map_subtract (*must_raw, x_must_raw);
|
|
*may_raw = isl_union_map_subtract (*may_raw, x_may_raw);
|
|
*must_raw_no_source = isl_union_map_subtract (*must_raw_no_source,
|
|
x_must_raw_no_source);
|
|
*may_raw_no_source = isl_union_map_subtract (*may_raw_no_source,
|
|
x_may_raw_no_source);
|
|
*must_war = isl_union_map_subtract (*must_war, x_must_war);
|
|
*may_war = isl_union_map_subtract (*may_war, x_may_war);
|
|
*must_war_no_source = isl_union_map_subtract (*must_war_no_source,
|
|
x_must_war_no_source);
|
|
*may_war_no_source = isl_union_map_subtract (*may_war_no_source,
|
|
x_may_war_no_source);
|
|
*must_waw = isl_union_map_subtract (*must_waw, x_must_waw);
|
|
*may_waw = isl_union_map_subtract (*may_waw, x_may_waw);
|
|
*must_waw_no_source = isl_union_map_subtract (*must_waw_no_source,
|
|
x_must_waw_no_source);
|
|
*may_waw_no_source = isl_union_map_subtract (*may_waw_no_source,
|
|
x_may_waw_no_source);
|
|
}
|
|
|
|
isl_union_map_free (original);
|
|
isl_space_free (space);
|
|
}
|
|
|
|
/* Compute the original data dependences in SCOP for all the reads and
|
|
writes in PBBS. */
|
|
|
|
void
|
|
compute_deps (scop_p scop, vec<poly_bb_p> pbbs,
|
|
isl_union_map **must_raw,
|
|
isl_union_map **may_raw,
|
|
isl_union_map **must_raw_no_source,
|
|
isl_union_map **may_raw_no_source,
|
|
isl_union_map **must_war,
|
|
isl_union_map **may_war,
|
|
isl_union_map **must_war_no_source,
|
|
isl_union_map **may_war_no_source,
|
|
isl_union_map **must_waw,
|
|
isl_union_map **may_waw,
|
|
isl_union_map **must_waw_no_source,
|
|
isl_union_map **may_waw_no_source)
|
|
{
|
|
isl_union_map *reads = scop_get_reads (scop, pbbs);
|
|
isl_union_map *must_writes = scop_get_must_writes (scop, pbbs);
|
|
isl_union_map *may_writes = scop_get_may_writes (scop, pbbs);
|
|
isl_union_map *all_writes = isl_union_map_union
|
|
(isl_union_map_copy (must_writes), isl_union_map_copy (may_writes));
|
|
isl_space *space = isl_union_map_get_space (all_writes);
|
|
isl_union_map *empty = isl_union_map_empty (space);
|
|
isl_union_map *original = scop_get_original_schedule (scop, pbbs);
|
|
int res;
|
|
|
|
res = isl_union_map_compute_flow (isl_union_map_copy (reads),
|
|
isl_union_map_copy (must_writes),
|
|
isl_union_map_copy (may_writes),
|
|
isl_union_map_copy (original),
|
|
must_raw, may_raw, must_raw_no_source,
|
|
may_raw_no_source);
|
|
gcc_assert (res == 0);
|
|
res = isl_union_map_compute_flow (isl_union_map_copy (all_writes),
|
|
reads, empty,
|
|
isl_union_map_copy (original),
|
|
must_war, may_war, must_war_no_source,
|
|
may_war_no_source);
|
|
gcc_assert (res == 0);
|
|
res = isl_union_map_compute_flow (all_writes, must_writes, may_writes,
|
|
isl_union_map_copy (original),
|
|
must_waw, may_waw, must_waw_no_source,
|
|
may_waw_no_source);
|
|
gcc_assert (res == 0);
|
|
|
|
subtract_commutative_associative_deps
|
|
(scop, pbbs, original,
|
|
must_raw, may_raw, must_raw_no_source, may_raw_no_source,
|
|
must_war, may_war, must_war_no_source, may_war_no_source,
|
|
must_waw, may_waw, must_waw_no_source, may_waw_no_source);
|
|
}
|
|
|
|
/* Given a TRANSFORM, check whether it respects the original
|
|
dependences in SCOP. Returns true when TRANSFORM is a safe
|
|
transformation. */
|
|
|
|
static bool
|
|
transform_is_safe (scop_p scop, isl_union_map *transform)
|
|
{
|
|
bool res;
|
|
|
|
if (!scop->must_raw)
|
|
compute_deps (scop, SCOP_BBS (scop),
|
|
&scop->must_raw, &scop->may_raw,
|
|
&scop->must_raw_no_source, &scop->may_raw_no_source,
|
|
&scop->must_war, &scop->may_war,
|
|
&scop->must_war_no_source, &scop->may_war_no_source,
|
|
&scop->must_waw, &scop->may_waw,
|
|
&scop->must_waw_no_source, &scop->may_waw_no_source);
|
|
|
|
res = (no_violations (transform, scop->must_raw)
|
|
&& no_violations (transform, scop->may_raw)
|
|
&& no_violations (transform, scop->must_war)
|
|
&& no_violations (transform, scop->may_war)
|
|
&& no_violations (transform, scop->must_waw)
|
|
&& no_violations (transform, scop->may_waw));
|
|
|
|
isl_union_map_free (transform);
|
|
return res;
|
|
}
|
|
|
|
/* Return true when the SCOP transformed schedule is correct. */
|
|
|
|
bool
|
|
graphite_legal_transform (scop_p scop)
|
|
{
|
|
int res;
|
|
isl_union_map *transform;
|
|
|
|
timevar_push (TV_GRAPHITE_DATA_DEPS);
|
|
transform = scop_get_transformed_schedule (scop, SCOP_BBS (scop));
|
|
res = transform_is_safe (scop, transform);
|
|
timevar_pop (TV_GRAPHITE_DATA_DEPS);
|
|
|
|
return res;
|
|
}
|
|
|
|
/* Return true when the loop at DEPTH carries dependences. BODY is
|
|
the body of the loop. */
|
|
|
|
static bool
|
|
loop_level_carries_dependences (scop_p scop, vec<poly_bb_p> body,
|
|
int depth)
|
|
{
|
|
isl_union_map *transform = scop_get_transformed_schedule (scop, body);
|
|
isl_union_map *must_raw, *may_raw;
|
|
isl_union_map *must_war, *may_war;
|
|
isl_union_map *must_waw, *may_waw;
|
|
int res;
|
|
|
|
compute_deps (scop, body,
|
|
&must_raw, &may_raw, NULL, NULL,
|
|
&must_war, &may_war, NULL, NULL,
|
|
&must_waw, &may_waw, NULL, NULL);
|
|
|
|
res = (carries_deps (transform, must_raw, depth)
|
|
|| carries_deps (transform, may_raw, depth)
|
|
|| carries_deps (transform, must_war, depth)
|
|
|| carries_deps (transform, may_war, depth)
|
|
|| carries_deps (transform, must_waw, depth)
|
|
|| carries_deps (transform, may_waw, depth));
|
|
|
|
isl_union_map_free (transform);
|
|
isl_union_map_free (must_raw);
|
|
isl_union_map_free (may_raw);
|
|
isl_union_map_free (must_war);
|
|
isl_union_map_free (may_war);
|
|
isl_union_map_free (must_waw);
|
|
isl_union_map_free (may_waw);
|
|
return res;
|
|
}
|
|
|
|
/* Returns true when the loop L at level DEPTH is parallel.
|
|
BB_PBB_MAPPING is a map between a basic_block and its related
|
|
poly_bb_p. */
|
|
|
|
bool
|
|
loop_is_parallel_p (loop_p loop, bb_pbb_htab_type bb_pbb_mapping, int depth)
|
|
{
|
|
bool dependences;
|
|
scop_p scop;
|
|
|
|
timevar_push (TV_GRAPHITE_DATA_DEPS);
|
|
stack_vec<poly_bb_p, 3> body;
|
|
scop = get_loop_body_pbbs (loop, bb_pbb_mapping, &body);
|
|
dependences = loop_level_carries_dependences (scop, body, depth);
|
|
timevar_pop (TV_GRAPHITE_DATA_DEPS);
|
|
|
|
return !dependences;
|
|
}
|
|
|
|
#endif
|