]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite.c
re PR tree-optimization/67700 ([graphite] miscompile due to wrong codegen)
[thirdparty/gcc.git] / gcc / graphite.c
CommitLineData
f8bf9252 1/* Gimple Represented as Polyhedra.
5624e564 2 Copyright (C) 2006-2015 Free Software Foundation, Inc.
f8bf9252
SP
3 Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21/* This pass converts GIMPLE to GRAPHITE, performs some loop
22 transformations and then converts the resulting representation back
204b560f 23 to GIMPLE.
f8bf9252
SP
24
25 An early description of this pass can be found in the GCC Summit'06
26 paper "GRAPHITE: Polyhedral Analyses and Optimizations for GCC".
27 The wiki page http://gcc.gnu.org/wiki/Graphite contains pointers to
d6bb5ccf 28 the related work. */
f8bf9252
SP
29
30#include "config.h"
33ad93b9 31
eae1a5d4 32#ifdef HAVE_isl
4bc190dc
JW
33/* Workaround for GMP 5.1.3 bug, see PR56019. */
34#include <stddef.h>
35
32400032 36#include <isl/constraint.h>
33ad93b9
RG
37#include <isl/set.h>
38#include <isl/map.h>
39#include <isl/options.h>
40#include <isl/union_map.h>
eae1a5d4 41#endif
33ad93b9 42
f8bf9252
SP
43#include "system.h"
44#include "coretypes.h"
c7131fb2 45#include "backend.h"
9c358739
AM
46#include "diagnostic-core.h"
47#include "cfgloop.h"
48#include "tree-pass.h"
49b8fe6c 49#include "params.h"
9c358739
AM
50
51#ifdef HAVE_isl
9fdcd34e 52#include "cfghooks.h"
40e23961 53#include "tree.h"
c7131fb2 54#include "gimple.h"
c7131fb2 55#include "fold-const.h"
5be5c238 56#include "gimple-iterator.h"
442b4905
AM
57#include "tree-cfg.h"
58#include "tree-ssa-loop.h"
f8bf9252
SP
59#include "tree-data-ref.h"
60#include "tree-scalar-evolution.h"
9c358739 61#include "graphite-poly.h"
6a7441f5 62#include "dbgcnt.h"
c1bf2a39 63#include "tree-parloops.h"
4484a35a 64#include "tree-cfgcleanup.h"
204b560f 65#include "graphite-scop-detection.h"
f6cc3103 66#include "graphite-isl-ast-to-gimple.h"
204b560f 67#include "graphite-sese-to-poly.h"
57d598f7 68
204b560f 69/* Print global statistics to FILE. */
4d6c7237
SP
70
71static void
204b560f 72print_global_statistics (FILE* file)
4d6c7237 73{
204b560f
SP
74 long n_bbs = 0;
75 long n_loops = 0;
76 long n_stmts = 0;
77 long n_conditions = 0;
78 long n_p_bbs = 0;
79 long n_p_loops = 0;
80 long n_p_stmts = 0;
81 long n_p_conditions = 0;
4d6c7237 82
204b560f 83 basic_block bb;
4d6c7237 84
04a90bec 85 FOR_ALL_BB_FN (bb, cfun)
204b560f
SP
86 {
87 gimple_stmt_iterator psi;
4d6c7237 88
204b560f
SP
89 n_bbs++;
90 n_p_bbs += bb->count;
4d6c7237 91
204b560f
SP
92 /* Ignore artificial surrounding loop. */
93 if (bb == bb->loop_father->header
94 && bb->index != 0)
4d6c7237 95 {
204b560f
SP
96 n_loops++;
97 n_p_loops += bb->count;
4d6c7237 98 }
4d6c7237 99
d630245f 100 if (EDGE_COUNT (bb->succs) > 1)
204b560f
SP
101 {
102 n_conditions++;
103 n_p_conditions += bb->count;
104 }
4d6c7237 105
204b560f
SP
106 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
107 {
108 n_stmts++;
109 n_p_stmts += bb->count;
110 }
4d6c7237
SP
111 }
112
204b560f
SP
113 fprintf (file, "\nGlobal statistics (");
114 fprintf (file, "BBS:%ld, ", n_bbs);
115 fprintf (file, "LOOPS:%ld, ", n_loops);
116 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
117 fprintf (file, "STMTS:%ld)\n", n_stmts);
118 fprintf (file, "\nGlobal profiling statistics (");
119 fprintf (file, "BBS:%ld, ", n_p_bbs);
120 fprintf (file, "LOOPS:%ld, ", n_p_loops);
121 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
122 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
f8bf9252
SP
123}
124
204b560f 125/* Print statistics for SCOP to FILE. */
f8bf9252
SP
126
127static void
204b560f 128print_graphite_scop_statistics (FILE* file, scop_p scop)
f8bf9252 129{
204b560f
SP
130 long n_bbs = 0;
131 long n_loops = 0;
132 long n_stmts = 0;
133 long n_conditions = 0;
134 long n_p_bbs = 0;
135 long n_p_loops = 0;
136 long n_p_stmts = 0;
137 long n_p_conditions = 0;
f8bf9252 138
204b560f 139 basic_block bb;
f8bf9252 140
04a90bec 141 FOR_ALL_BB_FN (bb, cfun)
f8bf9252 142 {
204b560f
SP
143 gimple_stmt_iterator psi;
144 loop_p loop = bb->loop_father;
f8bf9252 145
204b560f
SP
146 if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
147 continue;
f8bf9252 148
204b560f
SP
149 n_bbs++;
150 n_p_bbs += bb->count;
f8bf9252 151
d630245f 152 if (EDGE_COUNT (bb->succs) > 1)
f8bf9252 153 {
204b560f
SP
154 n_conditions++;
155 n_p_conditions += bb->count;
f8bf9252 156 }
f8bf9252 157
204b560f 158 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
f8bf9252 159 {
204b560f
SP
160 n_stmts++;
161 n_p_stmts += bb->count;
f8bf9252 162 }
f8bf9252 163
204b560f
SP
164 if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
165 {
166 n_loops++;
167 n_p_loops += bb->count;
168 }
169 }
6a114766 170
204b560f
SP
171 fprintf (file, "\nSCoP statistics (");
172 fprintf (file, "BBS:%ld, ", n_bbs);
173 fprintf (file, "LOOPS:%ld, ", n_loops);
174 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
175 fprintf (file, "STMTS:%ld)\n", n_stmts);
176 fprintf (file, "\nSCoP profiling statistics (");
177 fprintf (file, "BBS:%ld, ", n_p_bbs);
178 fprintf (file, "LOOPS:%ld, ", n_p_loops);
179 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
180 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
f8bf9252
SP
181}
182
204b560f 183/* Print statistics for SCOPS to FILE. */
f8bf9252 184
204b560f 185static void
9771b263 186print_graphite_statistics (FILE* file, vec<scop_p> scops)
f8bf9252 187{
f8bf9252 188 int i;
f8bf9252 189
204b560f 190 scop_p scop;
f8bf9252 191
9771b263 192 FOR_EACH_VEC_ELT (scops, i, scop)
204b560f 193 print_graphite_scop_statistics (file, scop);
f8bf9252
SP
194}
195
204b560f 196/* Initialize graphite: when there are no loops returns false. */
f8bf9252
SP
197
198static bool
33ad93b9 199graphite_initialize (isl_ctx *ctx)
f8bf9252 200{
0fc822d0 201 if (number_of_loops (cfun) <= 1
9bf13085
SP
202 /* FIXME: This limit on the number of basic blocks of a function
203 should be removed when the SCOP detection is faster. */
0cae8d31
DM
204 || (n_basic_blocks_for_fn (cfun) >
205 PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION)))
f8bf9252 206 {
204b560f
SP
207 if (dump_file && (dump_flags & TDF_DETAILS))
208 print_global_statistics (dump_file);
f8bf9252 209
33ad93b9 210 isl_ctx_free (ctx);
204b560f 211 return false;
f8bf9252
SP
212 }
213
cdb9802c 214 scev_reset ();
204b560f
SP
215 recompute_all_dominators ();
216 initialize_original_copy_tables ();
85437633 217
204b560f
SP
218 if (dump_file && dump_flags)
219 dump_function_to_file (current_function_decl, dump_file, dump_flags);
f8bf9252 220
204b560f 221 return true;
f8bf9252
SP
222}
223
204b560f
SP
224/* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
225 true. */
f8bf9252
SP
226
227static void
204b560f 228graphite_finalize (bool need_cfg_cleanup_p)
f8bf9252 229{
204b560f 230 if (need_cfg_cleanup_p)
8e88f9fd 231 {
fd4a56ff 232 scev_reset ();
8e88f9fd 233 cleanup_tree_cfg ();
0a6a6ac9 234 profile_status_for_fn (cfun) = PROFILE_ABSENT;
8e88f9fd
SP
235 release_recorded_exits ();
236 tree_estimate_probability ();
237 }
f8bf9252 238
204b560f 239 free_original_copy_tables ();
a61e3d2a 240
204b560f
SP
241 if (dump_file && dump_flags)
242 print_loops (dump_file, 3);
f8bf9252
SP
243}
244
33ad93b9
RG
245isl_ctx *the_isl_ctx;
246
f8bf9252
SP
247/* Perform a set of linear transforms on the loops of the current
248 function. */
249
250void
251graphite_transform_loops (void)
252{
253 int i;
254 scop_p scop;
204b560f 255 bool need_cfg_cleanup_p = false;
6e1aa848 256 vec<scop_p> scops = vNULL;
33ad93b9 257 isl_ctx *ctx;
f8bf9252 258
62e0a1ed
RG
259 /* If a function is parallel it was most probably already run through graphite
260 once. No need to run again. */
261 if (parallelized_function_p (cfun->decl))
262 return;
263
33ad93b9 264 ctx = isl_ctx_alloc ();
c3284718 265 isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
33ad93b9 266 if (!graphite_initialize (ctx))
f8bf9252
SP
267 return;
268
33ad93b9 269 the_isl_ctx = ctx;
204b560f 270 build_scops (&scops);
f8bf9252
SP
271
272 if (dump_file && (dump_flags & TDF_DETAILS))
f8bf9252 273 {
204b560f
SP
274 print_graphite_statistics (dump_file, scops);
275 print_global_statistics (dump_file);
276 }
0b040072 277
9771b263 278 FOR_EACH_VEC_ELT (scops, i, scop)
6a7441f5
SP
279 if (dbg_cnt (graphite_scop))
280 {
33ad93b9 281 scop->ctx = ctx;
efa21390 282 build_poly_scop (scop);
f8bf9252 283
d6bb5ccf
SP
284 if (dump_file && dump_flags)
285 print_scop (dump_file, scop, 3);
286
eae1a5d4
RG
287 if (POLY_SCOP_P (scop)
288 && apply_poly_transforms (scop)
289 && graphite_regenerate_ast_isl (scop))
290 need_cfg_cleanup_p = true;
eae1a5d4 291
efa21390 292 }
f8bf9252 293
204b560f
SP
294 free_scops (scops);
295 graphite_finalize (need_cfg_cleanup_p);
33ad93b9
RG
296 the_isl_ctx = NULL;
297 isl_ctx_free (ctx);
f8bf9252
SP
298}
299
eae1a5d4 300#else /* If ISL is not available: #ifndef HAVE_isl. */
f8bf9252 301
c1bf2a39 302static void
f8bf9252
SP
303graphite_transform_loops (void)
304{
eae1a5d4 305 sorry ("Graphite loop optimizations cannot be used (ISL is not available).");
f8bf9252
SP
306}
307
308#endif
c1bf2a39
AM
309
310
311static unsigned int
726338f4 312graphite_transforms (struct function *fun)
c1bf2a39 313{
726338f4 314 if (number_of_loops (fun) <= 1)
c1bf2a39
AM
315 return 0;
316
317 graphite_transform_loops ();
318
319 return 0;
320}
321
322static bool
323gate_graphite_transforms (void)
324{
325 /* Enable -fgraphite pass if any one of the graphite optimization flags
326 is turned on. */
d6bb5ccf 327 if (flag_graphite_identity
c1bf2a39 328 || flag_loop_parallelize_all
a5e5ea0c 329 || flag_loop_optimize_isl)
c1bf2a39
AM
330 flag_graphite = 1;
331
332 return flag_graphite != 0;
333}
334
17795822
TS
335namespace {
336
337const pass_data pass_data_graphite =
c1bf2a39
AM
338{
339 GIMPLE_PASS, /* type */
340 "graphite0", /* name */
341 OPTGROUP_LOOP, /* optinfo_flags */
c1bf2a39
AM
342 TV_GRAPHITE, /* tv_id */
343 ( PROP_cfg | PROP_ssa ), /* properties_required */
344 0, /* properties_provided */
345 0, /* properties_destroyed */
346 0, /* todo_flags_start */
347 0, /* todo_flags_finish */
348};
349
17795822 350class pass_graphite : public gimple_opt_pass
c1bf2a39
AM
351{
352public:
353 pass_graphite (gcc::context *ctxt)
354 : gimple_opt_pass (pass_data_graphite, ctxt)
355 {}
356
357 /* opt_pass methods: */
1a3d085c 358 virtual bool gate (function *) { return gate_graphite_transforms (); }
c1bf2a39
AM
359
360}; // class pass_graphite
361
17795822
TS
362} // anon namespace
363
c1bf2a39
AM
364gimple_opt_pass *
365make_pass_graphite (gcc::context *ctxt)
366{
367 return new pass_graphite (ctxt);
368}
369
17795822
TS
370namespace {
371
372const pass_data pass_data_graphite_transforms =
c1bf2a39
AM
373{
374 GIMPLE_PASS, /* type */
375 "graphite", /* name */
376 OPTGROUP_LOOP, /* optinfo_flags */
c1bf2a39
AM
377 TV_GRAPHITE_TRANSFORMS, /* tv_id */
378 ( PROP_cfg | PROP_ssa ), /* properties_required */
379 0, /* properties_provided */
380 0, /* properties_destroyed */
381 0, /* todo_flags_start */
382 0, /* todo_flags_finish */
383};
384
17795822 385class pass_graphite_transforms : public gimple_opt_pass
c1bf2a39
AM
386{
387public:
388 pass_graphite_transforms (gcc::context *ctxt)
389 : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
390 {}
391
392 /* opt_pass methods: */
1a3d085c 393 virtual bool gate (function *) { return gate_graphite_transforms (); }
726338f4 394 virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }
c1bf2a39
AM
395
396}; // class pass_graphite_transforms
397
17795822
TS
398} // anon namespace
399
c1bf2a39
AM
400gimple_opt_pass *
401make_pass_graphite_transforms (gcc::context *ctxt)
402{
403 return new pass_graphite_transforms (ctxt);
404}
405
406