--- gcc/graphite-poly.c | 1 - gcc/graphite-poly.h | 6 +- gcc/graphite-sese-to-poly.c | 103 ++++++++++++++++++------- gcc/graphite-sese-to-poly.h | 26 ------- gcc/graphite.c | 27 +++---- gcc/sese.c | 2 + gcc/testsuite/gfortran.dg/graphite/pr68279.f90 | 28 +++++++ 7 files changed, 118 insertions(+), 75 deletions(-) delete mode 100644 gcc/graphite-sese-to-poly.h create mode 100644 gcc/testsuite/gfortran.dg/graphite/pr68279.f90
diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c index 809670a..bc6befa 100644 --- a/gcc/graphite-poly.c +++ b/gcc/graphite-poly.c @@ -307,7 +307,6 @@ new_scop (edge entry, edge exit) scop_set_region (scop, region); scop->original_schedule = NULL; scop->pbbs.create (3); - scop->poly_scop_p = false; scop->drs.create (3); return scop; diff --git a/gcc/graphite-poly.h b/gcc/graphite-poly.h index 3fcbbaf..dec7fd6 100644 --- a/gcc/graphite-poly.h +++ b/gcc/graphite-poly.h @@ -420,10 +420,6 @@ struct scop /* Original schedule of the SCoP. */ isl_union_map *original_schedule; - - /* True when the scop has been converted to its polyhedral - representation. */ - bool poly_scop_p; }; extern scop_p new_scop (edge, edge); @@ -468,4 +464,6 @@ carries_deps (__isl_keep isl_union_map *schedule, __isl_keep isl_union_map *deps, int depth); +bool build_poly_scop (scop_p); + #endif diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c index 83acc4a..2054fad 100644 --- a/gcc/graphite-sese-to-poly.c +++ b/gcc/graphite-sese-to-poly.c @@ -65,7 +65,6 @@ extern "C" { #include "domwalk.h" #include "graphite-poly.h" #include "tree-ssa-propagate.h" -#include "graphite-sese-to-poly.h" /* Assigns to RES the value of the INTEGER_CST T. */ @@ -589,10 +588,20 @@ set_scop_parameter_dim (scop_p scop) 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 void +static bool build_loop_iteration_domains (scop_p scop, struct loop *loop, int nb, isl_set *outer, isl_set **doms) @@ -637,11 +646,17 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop, 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)); - scop->param_context = isl_set_intersect (scop->param_context, valid); + + if (valid) + scop->param_context = 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), @@ -685,21 +700,24 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop, else gcc_unreachable (); - if (loop->inner) - build_loop_iteration_domains (scop, loop->inner, nb + 1, - isl_set_copy (inner), doms); + 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); + && 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. */ @@ -710,6 +728,11 @@ create_pw_aff_from_tree (poly_bb_p pbb, tree t) scop_p scop = PBB_SCOP (pbb); t = scalar_evolution_in_region (scop->scop_info->region, pbb_loop (pbb), t); + + /* Bail out as we do not know the scev. */ + if (chrec_contains_undetermined (t)) + return NULL; + gcc_assert (!automatically_generated_chrec_p (t)); return extract_affine (scop, t, isl_set_get_space (pbb->domain)); @@ -719,13 +742,21 @@ create_pw_aff_from_tree (poly_bb_p pbb, tree t) operator. This allows us to invert the condition or to handle inequalities. */ -static void +static bool add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code) { isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, gimple_cond_lhs (stmt)); + if (!lhs) + return false; + isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, gimple_cond_rhs (stmt)); - isl_set *cond; + if (!rhs) + { + isl_pw_aff_free (lhs); + return false; + } + isl_set *cond; switch (code) { case LT_EXPR: @@ -755,17 +786,18 @@ add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code) default: isl_pw_aff_free (lhs); isl_pw_aff_free (rhs); - return; + return true; } cond = isl_set_coalesce (cond); cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain)); pbb->domain = isl_set_intersect (pbb->domain, cond); + return true; } /* Add conditions to the domain of PBB. */ -static void +static bool add_conditions_to_domain (poly_bb_p pbb) { unsigned int i; @@ -773,7 +805,7 @@ add_conditions_to_domain (poly_bb_p pbb) gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb); if (GBB_CONDITIONS (gbb).is_empty ()) - return; + return true; FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt) switch (gimple_code (stmt)) @@ -791,7 +823,8 @@ add_conditions_to_domain (poly_bb_p pbb) if (!GBB_CONDITION_CASES (gbb)[i]) code = invert_tree_comparison (code, false); - add_condition_to_pbb (pbb, cond_stmt, code); + if (!add_condition_to_pbb (pbb, cond_stmt, code)) + return false; break; } @@ -802,19 +835,24 @@ add_conditions_to_domain (poly_bb_p pbb) gcc_unreachable (); break; } + + return true; } /* Traverses all the GBBs of the SCOP and add their constraints to the iteration domains. */ -static void +static bool add_conditions_to_constraints (scop_p scop) { int i; poly_bb_p pbb; FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) - add_conditions_to_domain (pbb); + if (!add_conditions_to_domain (pbb)) + return false; + + return true; } /* Add constraints on the possible values of parameter P from the type @@ -894,19 +932,23 @@ build_scop_context (scop_p scop) SCOP, and that vary for the execution of the current basic block. Returns false if there is no loop in SCOP. */ -static void +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); + 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) @@ -922,11 +964,13 @@ build_scop_iteration_domain (scop_p scop) 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 @@ -1186,20 +1230,21 @@ build_scop_drs (scop_p scop) /* Builds the polyhedral representation for a SESE region. */ -void +bool build_poly_scop (scop_p scop) { set_scop_parameter_dim (scop); - build_scop_iteration_domain (scop); + if (!build_scop_iteration_domain (scop)) + return false; + build_scop_context (scop); - add_conditions_to_constraints (scop); + + if (!add_conditions_to_constraints (scop)) + return false; build_scop_drs (scop); build_scop_minimal_scattering (scop); build_scop_original_schedule (scop); - - /* This SCoP has been translated to the polyhedral - representation. */ - scop->poly_scop_p = true; + return true; } #endif /* HAVE_isl */ diff --git a/gcc/graphite-sese-to-poly.h b/gcc/graphite-sese-to-poly.h deleted file mode 100644 index 48f0d56..0000000 --- a/gcc/graphite-sese-to-poly.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Conversion of SESE regions to Polyhedra. - Copyright (C) 2009-2015 Free Software Foundation, Inc. - Contributed by Sebastian Pop <sebastian....@amd.com>. - -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/>. */ - -#ifndef GCC_GRAPHITE_SESE_TO_POLY_H -#define GCC_GRAPHITE_SESE_TO_POLY_H - -void build_poly_scop (scop_p); - -#endif diff --git a/gcc/graphite.c b/gcc/graphite.c index 5316bc4..987e83f 100644 --- a/gcc/graphite.c +++ b/gcc/graphite.c @@ -65,7 +65,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfgcleanup.h" #include "graphite-scop-detection.h" #include "graphite-isl-ast-to-gimple.h" -#include "graphite-sese-to-poly.h" /* Print global statistics to FILE. */ @@ -329,20 +328,18 @@ graphite_transform_loops (void) if (dbg_cnt (graphite_scop)) { scop->isl_context = ctx; - build_poly_scop (scop); - - if (dump_file && dump_flags) - print_scop (dump_file, scop); - if (scop->poly_scop_p - && apply_poly_transforms (scop)) - { - need_cfg_cleanup_p = true; - /* When code generation is not successful, do not continue - generating code for the next scops: the IR has to be cleaned up - and could be in an inconsistent state. */ - if (!graphite_regenerate_ast_isl (scop)) - break; - } + if (!build_poly_scop (scop)) + continue; + + if (!apply_poly_transforms (scop)) + continue; + + need_cfg_cleanup_p = true; + /* When code generation is not successful, do not continue + generating code for the next scops: the IR has to be cleaned up + and could be in an inconsistent state. */ + if (!graphite_regenerate_ast_isl (scop)) + break; } free_scops (scops); diff --git a/gcc/sese.c b/gcc/sese.c index 9b932ce..74dc4ac 100644 --- a/gcc/sese.c +++ b/gcc/sese.c @@ -609,6 +609,8 @@ scalar_evolution_in_region (sese_l ®ion, loop_p loop, tree t) if (TREE_CODE (t) != SSA_NAME || loop_in_sese_p (loop, region)) + /* FIXME: we would need instantiate SCEV to work on a region, and be more + flexible wrt. memory loads that may be invariant in the region. */ return instantiate_scev (before, loop, analyze_scalar_evolution (loop, t)); diff --git a/gcc/testsuite/gfortran.dg/graphite/pr68279.f90 b/gcc/testsuite/gfortran.dg/graphite/pr68279.f90 new file mode 100644 index 0000000..e68d6e7 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/pr68279.f90 @@ -0,0 +1,28 @@ +! { dg-options "-std=legacy -floop-nest-optimize -O2" } + +MODULE dbcsr_mm_accdrv + INTEGER, SAVE :: accdrv_binning_nbins = 4096 + INTEGER, SAVE :: accdrv_binning_binsize = 16 + INTEGER, PARAMETER, PUBLIC :: dbcsr_ps_width = 7 + CONTAINS + SUBROUTINE stack_binning(params_in, params_out, stack_size) + INTEGER, INTENT(IN) :: stack_size + INTEGER, DIMENSION(dbcsr_ps_width, & + stack_size), INTENT(OUT) :: params_out + INTEGER, DIMENSION(dbcsr_ps_width, & + stack_size), INTENT(IN) :: params_in + INTEGER, DIMENSION(accdrv_binning_nbins) :: bin_top + INTEGER, DIMENSION(dbcsr_ps_width) :: val + INTEGER, DIMENSION(dbcsr_ps_width, & + accdrv_binning_binsize, & + accdrv_binning_nbins) :: bin_arr + DO i=1,stack_size + val(:) = params_in(:,i) + IF(bin_top(bin_id) > accdrv_binning_binsize) THEN + params_out(:, top:top+bin_top(bin_id)-2) = bin_arr(:, 1:bin_top(bin_id)-1, bin_id) + ENDIF + bin_arr(:, bin_top(bin_id), bin_id) = val(:) + bin_top(bin_id) = bin_top(bin_id) + 1 + END DO + END SUBROUTINE stack_binning +END MODULE -- 1.9.1