xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/graphite-optimize-isl.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* A scheduling optimizer for Graphite
2*8feb0f0bSmrg    Copyright (C) 2012-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Contributed by Tobias Grosser <tobias@grosser.es>.
41debfc3dSmrg 
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg 
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify
81debfc3dSmrg it under the terms of the GNU General Public License as published by
91debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
101debfc3dSmrg any later version.
111debfc3dSmrg 
121debfc3dSmrg GCC is distributed in the hope that it will be useful,
131debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
141debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151debfc3dSmrg GNU General Public License for more details.
161debfc3dSmrg 
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3.  If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>.  */
201debfc3dSmrg 
211debfc3dSmrg #define USES_ISL
221debfc3dSmrg 
231debfc3dSmrg #include "config.h"
241debfc3dSmrg 
251debfc3dSmrg #ifdef HAVE_isl
261debfc3dSmrg 
271debfc3dSmrg #include "system.h"
281debfc3dSmrg #include "coretypes.h"
291debfc3dSmrg #include "backend.h"
301debfc3dSmrg #include "cfghooks.h"
311debfc3dSmrg #include "tree.h"
321debfc3dSmrg #include "gimple.h"
331debfc3dSmrg #include "fold-const.h"
341debfc3dSmrg #include "gimple-iterator.h"
351debfc3dSmrg #include "tree-ssa-loop.h"
361debfc3dSmrg #include "cfgloop.h"
371debfc3dSmrg #include "tree-data-ref.h"
381debfc3dSmrg #include "dumpfile.h"
39a2dc1f3fSmrg #include "tree-vectorizer.h"
401debfc3dSmrg #include "graphite.h"
411debfc3dSmrg 
421debfc3dSmrg 
431debfc3dSmrg /* get_schedule_for_node_st - Improve schedule for the schedule node.
441debfc3dSmrg    Only Simple loop tiling is considered.  */
451debfc3dSmrg 
461debfc3dSmrg static __isl_give isl_schedule_node *
get_schedule_for_node_st(__isl_take isl_schedule_node * node,void * user)471debfc3dSmrg get_schedule_for_node_st (__isl_take isl_schedule_node *node, void *user)
481debfc3dSmrg {
491debfc3dSmrg   if (user)
501debfc3dSmrg     return node;
511debfc3dSmrg 
521debfc3dSmrg   if (isl_schedule_node_get_type (node) != isl_schedule_node_band
531debfc3dSmrg       || isl_schedule_node_n_children (node) != 1)
541debfc3dSmrg     return node;
551debfc3dSmrg 
561debfc3dSmrg   isl_space *space = isl_schedule_node_band_get_space (node);
571debfc3dSmrg   unsigned dims = isl_space_dim (space, isl_dim_set);
581debfc3dSmrg   isl_schedule_node *child = isl_schedule_node_get_child (node, 0);
591debfc3dSmrg   isl_schedule_node_type type = isl_schedule_node_get_type (child);
601debfc3dSmrg   isl_space_free (space);
611debfc3dSmrg   isl_schedule_node_free (child);
621debfc3dSmrg 
631debfc3dSmrg   if (type != isl_schedule_node_leaf)
641debfc3dSmrg     return node;
651debfc3dSmrg 
66*8feb0f0bSmrg   long tile_size = param_loop_block_tile_size;
67a2dc1f3fSmrg   if (dims <= 1
68a2dc1f3fSmrg       || tile_size == 0
69a2dc1f3fSmrg       || !isl_schedule_node_band_get_permutable (node))
701debfc3dSmrg     {
711debfc3dSmrg       if (dump_file && dump_flags)
721debfc3dSmrg 	fprintf (dump_file, "not tiled\n");
731debfc3dSmrg       return node;
741debfc3dSmrg     }
751debfc3dSmrg 
761debfc3dSmrg   /* Tile loops.  */
771debfc3dSmrg   space = isl_schedule_node_band_get_space (node);
781debfc3dSmrg   isl_multi_val *sizes = isl_multi_val_zero (space);
791debfc3dSmrg   isl_ctx *ctx = isl_schedule_node_get_ctx (node);
801debfc3dSmrg 
811debfc3dSmrg   for (unsigned i = 0; i < dims; i++)
821debfc3dSmrg     {
831debfc3dSmrg       sizes = isl_multi_val_set_val (sizes, i,
841debfc3dSmrg 				     isl_val_int_from_si (ctx, tile_size));
851debfc3dSmrg       if (dump_file && dump_flags)
861debfc3dSmrg 	fprintf (dump_file, "tiled by %ld\n", tile_size);
871debfc3dSmrg     }
881debfc3dSmrg 
891debfc3dSmrg   node = isl_schedule_node_band_tile (node, sizes);
901debfc3dSmrg   node = isl_schedule_node_child (node, 0);
911debfc3dSmrg 
921debfc3dSmrg   return node;
931debfc3dSmrg }
941debfc3dSmrg 
951debfc3dSmrg static isl_union_set *
scop_get_domains(scop_p scop)961debfc3dSmrg scop_get_domains (scop_p scop)
971debfc3dSmrg {
981debfc3dSmrg   int i;
991debfc3dSmrg   poly_bb_p pbb;
1001debfc3dSmrg   isl_space *space = isl_set_get_space (scop->param_context);
1011debfc3dSmrg   isl_union_set *res = isl_union_set_empty (space);
1021debfc3dSmrg 
1031debfc3dSmrg   FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
1041debfc3dSmrg     res = isl_union_set_add_set (res, isl_set_copy (pbb->domain));
1051debfc3dSmrg 
1061debfc3dSmrg   return res;
1071debfc3dSmrg }
1081debfc3dSmrg 
1091debfc3dSmrg /* Compute the schedule for SCOP based on its parameters, domain and set of
1101debfc3dSmrg    constraints.  Then apply the schedule to SCOP.  */
1111debfc3dSmrg 
1121debfc3dSmrg static bool
optimize_isl(scop_p scop)1131debfc3dSmrg optimize_isl (scop_p scop)
1141debfc3dSmrg {
115a2dc1f3fSmrg   int old_err = isl_options_get_on_error (scop->isl_context);
1161debfc3dSmrg   int old_max_operations = isl_ctx_get_max_operations (scop->isl_context);
117*8feb0f0bSmrg   int max_operations = param_max_isl_operations;
1181debfc3dSmrg   if (max_operations)
1191debfc3dSmrg     isl_ctx_set_max_operations (scop->isl_context, max_operations);
1201debfc3dSmrg   isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_CONTINUE);
1211debfc3dSmrg 
1221debfc3dSmrg   isl_union_set *domain = scop_get_domains (scop);
1231debfc3dSmrg 
1241debfc3dSmrg   /* Simplify the dependences on the domain.  */
1251debfc3dSmrg   scop_get_dependences (scop);
1261debfc3dSmrg   isl_union_map *dependences
1271debfc3dSmrg     = isl_union_map_gist_domain (isl_union_map_copy (scop->dependence),
1281debfc3dSmrg 				 isl_union_set_copy (domain));
1291debfc3dSmrg   isl_union_map *validity
1301debfc3dSmrg     = isl_union_map_gist_range (dependences, isl_union_set_copy (domain));
1311debfc3dSmrg 
1321debfc3dSmrg   /* FIXME: proximity should not be validity.  */
1331debfc3dSmrg   isl_union_map *proximity = isl_union_map_copy (validity);
1341debfc3dSmrg 
1351debfc3dSmrg   isl_schedule_constraints *sc = isl_schedule_constraints_on_domain (domain);
1361debfc3dSmrg   sc = isl_schedule_constraints_set_proximity (sc, proximity);
1371debfc3dSmrg   sc = isl_schedule_constraints_set_validity (sc, isl_union_map_copy (validity));
1381debfc3dSmrg   sc = isl_schedule_constraints_set_coincidence (sc, validity);
1391debfc3dSmrg 
1401debfc3dSmrg   isl_options_set_schedule_serialize_sccs (scop->isl_context, 0);
1411debfc3dSmrg   isl_options_set_schedule_maximize_band_depth (scop->isl_context, 1);
1421debfc3dSmrg   isl_options_set_schedule_max_constant_term (scop->isl_context, 20);
1431debfc3dSmrg   isl_options_set_schedule_max_coefficient (scop->isl_context, 20);
1441debfc3dSmrg   isl_options_set_tile_scale_tile_loops (scop->isl_context, 0);
1451debfc3dSmrg   /* Generate loop upper bounds that consist of the current loop iterator, an
1461debfc3dSmrg      operator (< or <=) and an expression not involving the iterator.  If this
1471debfc3dSmrg      option is not set, then the current loop iterator may appear several times
1481debfc3dSmrg      in the upper bound.  See the isl manual for more details.  */
1491debfc3dSmrg   isl_options_set_ast_build_atomic_upper_bound (scop->isl_context, 1);
1501debfc3dSmrg 
1511debfc3dSmrg   scop->transformed_schedule = isl_schedule_constraints_compute_schedule (sc);
1521debfc3dSmrg   scop->transformed_schedule =
1531debfc3dSmrg     isl_schedule_map_schedule_node_bottom_up (scop->transformed_schedule,
1541debfc3dSmrg 					      get_schedule_for_node_st, NULL);
1551debfc3dSmrg 
156a2dc1f3fSmrg   isl_options_set_on_error (scop->isl_context, old_err);
1571debfc3dSmrg   isl_ctx_reset_operations (scop->isl_context);
1581debfc3dSmrg   isl_ctx_set_max_operations (scop->isl_context, old_max_operations);
1591debfc3dSmrg   if (!scop->transformed_schedule
160a2dc1f3fSmrg       || isl_ctx_last_error (scop->isl_context) != isl_error_none)
1611debfc3dSmrg     {
162c0a68be4Smrg       if (dump_enabled_p ())
163c0a68be4Smrg 	{
164c0a68be4Smrg 	  dump_user_location_t loc = find_loop_location
165a2dc1f3fSmrg 	    (scop->scop_info->region.entry->dest->loop_father);
166a2dc1f3fSmrg 	  if (isl_ctx_last_error (scop->isl_context) == isl_error_quota)
167a2dc1f3fSmrg 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
168a2dc1f3fSmrg 			     "loop nest not optimized, optimization timed out "
169a2dc1f3fSmrg 			     "after %d operations [--param max-isl-operations]\n",
1701debfc3dSmrg 			     max_operations);
171a2dc1f3fSmrg 	  else
172a2dc1f3fSmrg 	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
173a2dc1f3fSmrg 			     "loop nest not optimized, ISL signalled an error\n");
174c0a68be4Smrg 	}
1751debfc3dSmrg       return false;
1761debfc3dSmrg     }
1771debfc3dSmrg 
1781debfc3dSmrg   gcc_assert (scop->original_schedule);
1791debfc3dSmrg   isl_union_map *original = isl_schedule_get_map (scop->original_schedule);
1801debfc3dSmrg   isl_union_map *transformed = isl_schedule_get_map (scop->transformed_schedule);
1811debfc3dSmrg   bool same_schedule = isl_union_map_is_equal (original, transformed);
1821debfc3dSmrg   isl_union_map_free (original);
1831debfc3dSmrg   isl_union_map_free (transformed);
1841debfc3dSmrg 
1851debfc3dSmrg   if (same_schedule)
1861debfc3dSmrg     {
187c0a68be4Smrg       if (dump_enabled_p ())
188c0a68be4Smrg 	{
189c0a68be4Smrg 	  dump_user_location_t loc = find_loop_location
190a2dc1f3fSmrg 	    (scop->scop_info->region.entry->dest->loop_father);
191a2dc1f3fSmrg 	  dump_printf_loc (MSG_NOTE, loc,
192a2dc1f3fSmrg 			   "loop nest not optimized, optimized schedule is "
193a2dc1f3fSmrg 			   "identical to original schedule\n");
194c0a68be4Smrg 	}
1951debfc3dSmrg       if (dump_file)
1961debfc3dSmrg 	print_schedule_ast (dump_file, scop->original_schedule, scop);
1971debfc3dSmrg       isl_schedule_free (scop->transformed_schedule);
1981debfc3dSmrg       scop->transformed_schedule = isl_schedule_copy (scop->original_schedule);
199a2dc1f3fSmrg       return flag_graphite_identity || flag_loop_parallelize_all;
2001debfc3dSmrg     }
2011debfc3dSmrg 
2021debfc3dSmrg   return true;
2031debfc3dSmrg }
2041debfc3dSmrg 
2051debfc3dSmrg /* Apply graphite transformations to all the basic blocks of SCOP.  */
2061debfc3dSmrg 
2071debfc3dSmrg bool
apply_poly_transforms(scop_p scop)2081debfc3dSmrg apply_poly_transforms (scop_p scop)
2091debfc3dSmrg {
2101debfc3dSmrg   if (flag_loop_nest_optimize)
2111debfc3dSmrg     return optimize_isl (scop);
2121debfc3dSmrg 
2131debfc3dSmrg   if (!flag_graphite_identity && !flag_loop_parallelize_all)
2141debfc3dSmrg     return false;
2151debfc3dSmrg 
2161debfc3dSmrg   /* Generate code even if we did not apply any real transformation.
2171debfc3dSmrg      This also allows to check the performance for the identity
2181debfc3dSmrg      transformation: GIMPLE -> GRAPHITE -> GIMPLE.  */
2191debfc3dSmrg   gcc_assert (scop->original_schedule);
2201debfc3dSmrg   scop->transformed_schedule = isl_schedule_copy (scop->original_schedule);
2211debfc3dSmrg   return true;
2221debfc3dSmrg }
2231debfc3dSmrg 
2241debfc3dSmrg #endif /* HAVE_isl */
225