2017-06-14 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / graphite-optimize-isl.c
blob467503e1b62f8edf44ae2f4acf7b1581852c3290
1 /* A scheduling optimizer for Graphite
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
3 Contributed by Tobias Grosser <tobias@grosser.es>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #define USES_ISL
23 #include "config.h"
25 #ifdef HAVE_isl
27 #include "system.h"
28 #include "coretypes.h"
29 #include "backend.h"
30 #include "cfghooks.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "fold-const.h"
34 #include "gimple-iterator.h"
35 #include "tree-ssa-loop.h"
36 #include "cfgloop.h"
37 #include "tree-data-ref.h"
38 #include "params.h"
39 #include "dumpfile.h"
40 #include "graphite.h"
43 /* get_schedule_for_node_st - Improve schedule for the schedule node.
44 Only Simple loop tiling is considered. */
46 static __isl_give isl_schedule_node *
47 get_schedule_for_node_st (__isl_take isl_schedule_node *node, void *user)
49 if (user)
50 return node;
52 if (isl_schedule_node_get_type (node) != isl_schedule_node_band
53 || isl_schedule_node_n_children (node) != 1)
54 return node;
56 isl_space *space = isl_schedule_node_band_get_space (node);
57 unsigned dims = isl_space_dim (space, isl_dim_set);
58 isl_schedule_node *child = isl_schedule_node_get_child (node, 0);
59 isl_schedule_node_type type = isl_schedule_node_get_type (child);
60 isl_space_free (space);
61 isl_schedule_node_free (child);
63 if (type != isl_schedule_node_leaf)
64 return node;
66 if (dims <= 1 || !isl_schedule_node_band_get_permutable (node))
68 if (dump_file && dump_flags)
69 fprintf (dump_file, "not tiled\n");
70 return node;
73 /* Tile loops. */
74 space = isl_schedule_node_band_get_space (node);
75 isl_multi_val *sizes = isl_multi_val_zero (space);
76 long tile_size = PARAM_VALUE (PARAM_LOOP_BLOCK_TILE_SIZE);
77 isl_ctx *ctx = isl_schedule_node_get_ctx (node);
79 for (unsigned i = 0; i < dims; i++)
81 sizes = isl_multi_val_set_val (sizes, i,
82 isl_val_int_from_si (ctx, tile_size));
83 if (dump_file && dump_flags)
84 fprintf (dump_file, "tiled by %ld\n", tile_size);
87 node = isl_schedule_node_band_tile (node, sizes);
88 node = isl_schedule_node_child (node, 0);
90 return node;
93 static isl_union_set *
94 scop_get_domains (scop_p scop)
96 int i;
97 poly_bb_p pbb;
98 isl_space *space = isl_set_get_space (scop->param_context);
99 isl_union_set *res = isl_union_set_empty (space);
101 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
102 res = isl_union_set_add_set (res, isl_set_copy (pbb->domain));
104 return res;
107 /* Compute the schedule for SCOP based on its parameters, domain and set of
108 constraints. Then apply the schedule to SCOP. */
110 static bool
111 optimize_isl (scop_p scop)
113 int old_max_operations = isl_ctx_get_max_operations (scop->isl_context);
114 int max_operations = PARAM_VALUE (PARAM_MAX_ISL_OPERATIONS);
115 if (max_operations)
116 isl_ctx_set_max_operations (scop->isl_context, max_operations);
117 isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_CONTINUE);
119 isl_union_set *domain = scop_get_domains (scop);
121 /* Simplify the dependences on the domain. */
122 scop_get_dependences (scop);
123 isl_union_map *dependences
124 = isl_union_map_gist_domain (isl_union_map_copy (scop->dependence),
125 isl_union_set_copy (domain));
126 isl_union_map *validity
127 = isl_union_map_gist_range (dependences, isl_union_set_copy (domain));
129 /* FIXME: proximity should not be validity. */
130 isl_union_map *proximity = isl_union_map_copy (validity);
132 isl_schedule_constraints *sc = isl_schedule_constraints_on_domain (domain);
133 sc = isl_schedule_constraints_set_proximity (sc, proximity);
134 sc = isl_schedule_constraints_set_validity (sc, isl_union_map_copy (validity));
135 sc = isl_schedule_constraints_set_coincidence (sc, validity);
137 isl_options_set_schedule_serialize_sccs (scop->isl_context, 0);
138 isl_options_set_schedule_maximize_band_depth (scop->isl_context, 1);
139 isl_options_set_schedule_max_constant_term (scop->isl_context, 20);
140 isl_options_set_schedule_max_coefficient (scop->isl_context, 20);
141 isl_options_set_tile_scale_tile_loops (scop->isl_context, 0);
142 /* Generate loop upper bounds that consist of the current loop iterator, an
143 operator (< or <=) and an expression not involving the iterator. If this
144 option is not set, then the current loop iterator may appear several times
145 in the upper bound. See the isl manual for more details. */
146 isl_options_set_ast_build_atomic_upper_bound (scop->isl_context, 1);
148 scop->transformed_schedule = isl_schedule_constraints_compute_schedule (sc);
149 scop->transformed_schedule =
150 isl_schedule_map_schedule_node_bottom_up (scop->transformed_schedule,
151 get_schedule_for_node_st, NULL);
152 isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_ABORT);
154 isl_ctx_reset_operations (scop->isl_context);
155 isl_ctx_set_max_operations (scop->isl_context, old_max_operations);
156 if (!scop->transformed_schedule
157 || isl_ctx_last_error (scop->isl_context) == isl_error_quota)
159 if (dump_file && dump_flags)
160 fprintf (dump_file, "isl timed out --param max-isl-operations=%d\n",
161 max_operations);
162 return false;
165 gcc_assert (scop->original_schedule);
166 isl_union_map *original = isl_schedule_get_map (scop->original_schedule);
167 isl_union_map *transformed = isl_schedule_get_map (scop->transformed_schedule);
168 bool same_schedule = isl_union_map_is_equal (original, transformed);
169 isl_union_map_free (original);
170 isl_union_map_free (transformed);
172 if (same_schedule)
174 if (dump_file)
176 fprintf (dump_file, "[scheduler] isl optimized schedule is "
177 "identical to the original schedule.\n");
178 print_schedule_ast (dump_file, scop->original_schedule, scop);
180 isl_schedule_free (scop->transformed_schedule);
181 scop->transformed_schedule = isl_schedule_copy (scop->original_schedule);
182 return false;
185 return true;
188 /* Apply graphite transformations to all the basic blocks of SCOP. */
190 bool
191 apply_poly_transforms (scop_p scop)
193 if (flag_loop_nest_optimize)
194 return optimize_isl (scop);
196 if (!flag_graphite_identity && !flag_loop_parallelize_all)
197 return false;
199 /* Generate code even if we did not apply any real transformation.
200 This also allows to check the performance for the identity
201 transformation: GIMPLE -> GRAPHITE -> GIMPLE. */
202 gcc_assert (scop->original_schedule);
203 scop->transformed_schedule = isl_schedule_copy (scop->original_schedule);
204 return true;
207 #endif /* HAVE_isl */