]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite.c
re PR c++/67104 (Constant expression factory function initializes std::array with...
[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
204b560f 28 the related work.
f8bf9252
SP
29
30 One important document to read is CLooG's internal manual:
31 http://repo.or.cz/w/cloog-ppl.git?a=blob_plain;f=doc/cloog.texi;hb=HEAD
32 that describes the data structure of loops used in this file, and
33 the functions that are used for transforming the code. */
34
35#include "config.h"
33ad93b9 36
eae1a5d4 37#ifdef HAVE_isl
4bc190dc
JW
38/* Workaround for GMP 5.1.3 bug, see PR56019. */
39#include <stddef.h>
40
32400032 41#include <isl/constraint.h>
33ad93b9
RG
42#include <isl/set.h>
43#include <isl/map.h>
44#include <isl/options.h>
45#include <isl/union_map.h>
eae1a5d4 46#endif
33ad93b9 47
f8bf9252
SP
48#include "system.h"
49#include "coretypes.h"
c7131fb2 50#include "backend.h"
9c358739
AM
51#include "diagnostic-core.h"
52#include "cfgloop.h"
53#include "tree-pass.h"
49b8fe6c 54#include "params.h"
9c358739
AM
55
56#ifdef HAVE_isl
9fdcd34e 57#include "cfghooks.h"
40e23961 58#include "tree.h"
c7131fb2 59#include "gimple.h"
c7131fb2 60#include "fold-const.h"
5be5c238 61#include "gimple-iterator.h"
442b4905
AM
62#include "tree-cfg.h"
63#include "tree-ssa-loop.h"
f8bf9252
SP
64#include "tree-data-ref.h"
65#include "tree-scalar-evolution.h"
9c358739 66#include "graphite-poly.h"
6a7441f5 67#include "dbgcnt.h"
c1bf2a39 68#include "tree-parloops.h"
4484a35a 69#include "tree-cfgcleanup.h"
204b560f 70#include "graphite-scop-detection.h"
f6cc3103 71#include "graphite-isl-ast-to-gimple.h"
204b560f 72#include "graphite-sese-to-poly.h"
57d598f7 73
204b560f 74/* Print global statistics to FILE. */
4d6c7237
SP
75
76static void
204b560f 77print_global_statistics (FILE* file)
4d6c7237 78{
204b560f
SP
79 long n_bbs = 0;
80 long n_loops = 0;
81 long n_stmts = 0;
82 long n_conditions = 0;
83 long n_p_bbs = 0;
84 long n_p_loops = 0;
85 long n_p_stmts = 0;
86 long n_p_conditions = 0;
4d6c7237 87
204b560f 88 basic_block bb;
4d6c7237 89
04a90bec 90 FOR_ALL_BB_FN (bb, cfun)
204b560f
SP
91 {
92 gimple_stmt_iterator psi;
4d6c7237 93
204b560f
SP
94 n_bbs++;
95 n_p_bbs += bb->count;
4d6c7237 96
204b560f
SP
97 /* Ignore artificial surrounding loop. */
98 if (bb == bb->loop_father->header
99 && bb->index != 0)
4d6c7237 100 {
204b560f
SP
101 n_loops++;
102 n_p_loops += bb->count;
4d6c7237 103 }
4d6c7237 104
d630245f 105 if (EDGE_COUNT (bb->succs) > 1)
204b560f
SP
106 {
107 n_conditions++;
108 n_p_conditions += bb->count;
109 }
4d6c7237 110
204b560f
SP
111 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
112 {
113 n_stmts++;
114 n_p_stmts += bb->count;
115 }
4d6c7237
SP
116 }
117
204b560f
SP
118 fprintf (file, "\nGlobal statistics (");
119 fprintf (file, "BBS:%ld, ", n_bbs);
120 fprintf (file, "LOOPS:%ld, ", n_loops);
121 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
122 fprintf (file, "STMTS:%ld)\n", n_stmts);
123 fprintf (file, "\nGlobal profiling statistics (");
124 fprintf (file, "BBS:%ld, ", n_p_bbs);
125 fprintf (file, "LOOPS:%ld, ", n_p_loops);
126 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
127 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
f8bf9252
SP
128}
129
204b560f 130/* Print statistics for SCOP to FILE. */
f8bf9252
SP
131
132static void
204b560f 133print_graphite_scop_statistics (FILE* file, scop_p scop)
f8bf9252 134{
204b560f
SP
135 long n_bbs = 0;
136 long n_loops = 0;
137 long n_stmts = 0;
138 long n_conditions = 0;
139 long n_p_bbs = 0;
140 long n_p_loops = 0;
141 long n_p_stmts = 0;
142 long n_p_conditions = 0;
f8bf9252 143
204b560f 144 basic_block bb;
f8bf9252 145
04a90bec 146 FOR_ALL_BB_FN (bb, cfun)
f8bf9252 147 {
204b560f
SP
148 gimple_stmt_iterator psi;
149 loop_p loop = bb->loop_father;
f8bf9252 150
204b560f
SP
151 if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
152 continue;
f8bf9252 153
204b560f
SP
154 n_bbs++;
155 n_p_bbs += bb->count;
f8bf9252 156
d630245f 157 if (EDGE_COUNT (bb->succs) > 1)
f8bf9252 158 {
204b560f
SP
159 n_conditions++;
160 n_p_conditions += bb->count;
f8bf9252 161 }
f8bf9252 162
204b560f 163 for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
f8bf9252 164 {
204b560f
SP
165 n_stmts++;
166 n_p_stmts += bb->count;
f8bf9252 167 }
f8bf9252 168
204b560f
SP
169 if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
170 {
171 n_loops++;
172 n_p_loops += bb->count;
173 }
174 }
6a114766 175
204b560f
SP
176 fprintf (file, "\nSCoP statistics (");
177 fprintf (file, "BBS:%ld, ", n_bbs);
178 fprintf (file, "LOOPS:%ld, ", n_loops);
179 fprintf (file, "CONDITIONS:%ld, ", n_conditions);
180 fprintf (file, "STMTS:%ld)\n", n_stmts);
181 fprintf (file, "\nSCoP profiling statistics (");
182 fprintf (file, "BBS:%ld, ", n_p_bbs);
183 fprintf (file, "LOOPS:%ld, ", n_p_loops);
184 fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
185 fprintf (file, "STMTS:%ld)\n", n_p_stmts);
f8bf9252
SP
186}
187
204b560f 188/* Print statistics for SCOPS to FILE. */
f8bf9252 189
204b560f 190static void
9771b263 191print_graphite_statistics (FILE* file, vec<scop_p> scops)
f8bf9252 192{
f8bf9252 193 int i;
f8bf9252 194
204b560f 195 scop_p scop;
f8bf9252 196
9771b263 197 FOR_EACH_VEC_ELT (scops, i, scop)
204b560f 198 print_graphite_scop_statistics (file, scop);
f8bf9252
SP
199}
200
204b560f 201/* Initialize graphite: when there are no loops returns false. */
f8bf9252
SP
202
203static bool
33ad93b9 204graphite_initialize (isl_ctx *ctx)
f8bf9252 205{
0fc822d0 206 if (number_of_loops (cfun) <= 1
9bf13085
SP
207 /* FIXME: This limit on the number of basic blocks of a function
208 should be removed when the SCOP detection is faster. */
0cae8d31
DM
209 || (n_basic_blocks_for_fn (cfun) >
210 PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION)))
f8bf9252 211 {
204b560f
SP
212 if (dump_file && (dump_flags & TDF_DETAILS))
213 print_global_statistics (dump_file);
f8bf9252 214
33ad93b9 215 isl_ctx_free (ctx);
204b560f 216 return false;
f8bf9252
SP
217 }
218
cdb9802c 219 scev_reset ();
204b560f
SP
220 recompute_all_dominators ();
221 initialize_original_copy_tables ();
85437633 222
204b560f
SP
223 if (dump_file && dump_flags)
224 dump_function_to_file (current_function_decl, dump_file, dump_flags);
f8bf9252 225
204b560f 226 return true;
f8bf9252
SP
227}
228
204b560f
SP
229/* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
230 true. */
f8bf9252
SP
231
232static void
204b560f 233graphite_finalize (bool need_cfg_cleanup_p)
f8bf9252 234{
204b560f 235 if (need_cfg_cleanup_p)
8e88f9fd 236 {
fd4a56ff 237 scev_reset ();
8e88f9fd 238 cleanup_tree_cfg ();
0a6a6ac9 239 profile_status_for_fn (cfun) = PROFILE_ABSENT;
8e88f9fd
SP
240 release_recorded_exits ();
241 tree_estimate_probability ();
242 }
f8bf9252 243
204b560f 244 free_original_copy_tables ();
a61e3d2a 245
204b560f
SP
246 if (dump_file && dump_flags)
247 print_loops (dump_file, 3);
f8bf9252
SP
248}
249
33ad93b9
RG
250isl_ctx *the_isl_ctx;
251
f8bf9252
SP
252/* Perform a set of linear transforms on the loops of the current
253 function. */
254
255void
256graphite_transform_loops (void)
257{
258 int i;
259 scop_p scop;
204b560f 260 bool need_cfg_cleanup_p = false;
6e1aa848 261 vec<scop_p> scops = vNULL;
33ad93b9 262 isl_ctx *ctx;
f8bf9252 263
62e0a1ed
RG
264 /* If a function is parallel it was most probably already run through graphite
265 once. No need to run again. */
266 if (parallelized_function_p (cfun->decl))
267 return;
268
33ad93b9 269 ctx = isl_ctx_alloc ();
c3284718 270 isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
33ad93b9 271 if (!graphite_initialize (ctx))
f8bf9252
SP
272 return;
273
33ad93b9 274 the_isl_ctx = ctx;
204b560f 275 build_scops (&scops);
f8bf9252
SP
276
277 if (dump_file && (dump_flags & TDF_DETAILS))
f8bf9252 278 {
204b560f
SP
279 print_graphite_statistics (dump_file, scops);
280 print_global_statistics (dump_file);
281 }
0b040072 282
9771b263 283 FOR_EACH_VEC_ELT (scops, i, scop)
6a7441f5
SP
284 if (dbg_cnt (graphite_scop))
285 {
33ad93b9 286 scop->ctx = ctx;
efa21390 287 build_poly_scop (scop);
f8bf9252 288
eae1a5d4
RG
289 if (POLY_SCOP_P (scop)
290 && apply_poly_transforms (scop)
291 && graphite_regenerate_ast_isl (scop))
292 need_cfg_cleanup_p = true;
eae1a5d4 293
efa21390 294 }
f8bf9252 295
204b560f
SP
296 free_scops (scops);
297 graphite_finalize (need_cfg_cleanup_p);
33ad93b9
RG
298 the_isl_ctx = NULL;
299 isl_ctx_free (ctx);
f8bf9252
SP
300}
301
eae1a5d4 302#else /* If ISL is not available: #ifndef HAVE_isl. */
f8bf9252 303
c1bf2a39 304static void
f8bf9252
SP
305graphite_transform_loops (void)
306{
eae1a5d4 307 sorry ("Graphite loop optimizations cannot be used (ISL is not available).");
f8bf9252
SP
308}
309
310#endif
c1bf2a39
AM
311
312
313static unsigned int
726338f4 314graphite_transforms (struct function *fun)
c1bf2a39 315{
726338f4 316 if (number_of_loops (fun) <= 1)
c1bf2a39
AM
317 return 0;
318
319 graphite_transform_loops ();
320
321 return 0;
322}
323
324static bool
325gate_graphite_transforms (void)
326{
327 /* Enable -fgraphite pass if any one of the graphite optimization flags
328 is turned on. */
329 if (flag_loop_block
330 || flag_loop_interchange
331 || flag_loop_strip_mine
332 || flag_graphite_identity
333 || flag_loop_parallelize_all
20d3465b
MN
334 || flag_loop_optimize_isl
335 || flag_loop_unroll_jam)
c1bf2a39
AM
336 flag_graphite = 1;
337
338 return flag_graphite != 0;
339}
340
63ab94b6 341static const pass_data pass_data_graphite =
c1bf2a39
AM
342{
343 GIMPLE_PASS, /* type */
344 "graphite0", /* name */
345 OPTGROUP_LOOP, /* optinfo_flags */
c1bf2a39
AM
346 TV_GRAPHITE, /* tv_id */
347 ( PROP_cfg | PROP_ssa ), /* properties_required */
348 0, /* properties_provided */
349 0, /* properties_destroyed */
350 0, /* todo_flags_start */
351 0, /* todo_flags_finish */
352};
353
63ab94b6 354class pass_graphite GCC_FINAL : public gimple_opt_pass
c1bf2a39
AM
355{
356public:
357 pass_graphite (gcc::context *ctxt)
358 : gimple_opt_pass (pass_data_graphite, ctxt)
359 {}
360
361 /* opt_pass methods: */
1a3d085c 362 virtual bool gate (function *) { return gate_graphite_transforms (); }
c1bf2a39
AM
363
364}; // class pass_graphite
365
c1bf2a39
AM
366gimple_opt_pass *
367make_pass_graphite (gcc::context *ctxt)
368{
369 return new pass_graphite (ctxt);
370}
371
63ab94b6 372static const 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
63ab94b6 385class pass_graphite_transforms GCC_FINAL : 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
c1bf2a39
AM
398gimple_opt_pass *
399make_pass_graphite_transforms (gcc::context *ctxt)
400{
401 return new pass_graphite_transforms (ctxt);
402}
403
404