OSDN Git Service

2010-09-02 Ryan Mansfield <rmansfield@qnx.com>
[pf3gnuchains/gcc-fork.git] / gcc / graphite.c
1 /* Gimple Represented as Polyhedra.
2    Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3    Contributed by Sebastian Pop <sebastian.pop@inria.fr>.
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>.  */
20
21 /* This pass converts GIMPLE to GRAPHITE, performs some loop
22    transformations and then converts the resulting representation back
23    to GIMPLE.
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
28    the related work.
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"
36 #include "system.h"
37 #include "coretypes.h"
38 #include "tm.h"
39 #include "ggc.h"
40 #include "tree.h"
41 #include "rtl.h"
42 #include "basic-block.h"
43 #include "diagnostic.h"
44 #include "tree-flow.h"
45 #include "toplev.h"
46 #include "tree-dump.h"
47 #include "timevar.h"
48 #include "cfgloop.h"
49 #include "tree-chrec.h"
50 #include "tree-data-ref.h"
51 #include "tree-scalar-evolution.h"
52 #include "tree-pass.h"
53 #include "value-prof.h"
54 #include "pointer-set.h"
55 #include "gimple.h"
56 #include "sese.h"
57 #include "predict.h"
58 #include "dbgcnt.h"
59
60 #ifdef HAVE_cloog
61
62 #include "cloog/cloog.h"
63 #include "ppl_c.h"
64 #include "graphite-cloog-compat.h"
65 #include "graphite-ppl.h"
66 #include "graphite.h"
67 #include "graphite-poly.h"
68 #include "graphite-scop-detection.h"
69 #include "graphite-clast-to-gimple.h"
70 #include "graphite-sese-to-poly.h"
71
72 /* Print global statistics to FILE.  */
73
74 static void
75 print_global_statistics (FILE* file)
76 {
77   long n_bbs = 0;
78   long n_loops = 0;
79   long n_stmts = 0;
80   long n_conditions = 0;
81   long n_p_bbs = 0;
82   long n_p_loops = 0;
83   long n_p_stmts = 0;
84   long n_p_conditions = 0;
85
86   basic_block bb;
87
88   FOR_ALL_BB (bb)
89     {
90       gimple_stmt_iterator psi;
91
92       n_bbs++;
93       n_p_bbs += bb->count;
94
95       /* Ignore artificial surrounding loop.  */
96       if (bb == bb->loop_father->header
97           && bb->index != 0)
98         {
99           n_loops++;
100           n_p_loops += bb->count;
101         }
102
103       if (VEC_length (edge, bb->succs) > 1)
104         {
105           n_conditions++;
106           n_p_conditions += bb->count;
107         }
108
109       for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
110         {
111           n_stmts++;
112           n_p_stmts += bb->count;
113         }
114     }
115
116   fprintf (file, "\nGlobal statistics (");
117   fprintf (file, "BBS:%ld, ", n_bbs);
118   fprintf (file, "LOOPS:%ld, ", n_loops);
119   fprintf (file, "CONDITIONS:%ld, ", n_conditions);
120   fprintf (file, "STMTS:%ld)\n", n_stmts);
121   fprintf (file, "\nGlobal profiling statistics (");
122   fprintf (file, "BBS:%ld, ", n_p_bbs);
123   fprintf (file, "LOOPS:%ld, ", n_p_loops);
124   fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
125   fprintf (file, "STMTS:%ld)\n", n_p_stmts);
126 }
127
128 /* Print statistics for SCOP to FILE.  */
129
130 static void
131 print_graphite_scop_statistics (FILE* file, scop_p scop)
132 {
133   long n_bbs = 0;
134   long n_loops = 0;
135   long n_stmts = 0;
136   long n_conditions = 0;
137   long n_p_bbs = 0;
138   long n_p_loops = 0;
139   long n_p_stmts = 0;
140   long n_p_conditions = 0;
141
142   basic_block bb;
143
144   FOR_ALL_BB (bb)
145     {
146       gimple_stmt_iterator psi;
147       loop_p loop = bb->loop_father;
148
149       if (!bb_in_sese_p (bb, SCOP_REGION (scop)))
150         continue;
151
152       n_bbs++;
153       n_p_bbs += bb->count;
154
155       if (VEC_length (edge, bb->succs) > 1)
156         {
157           n_conditions++;
158           n_p_conditions += bb->count;
159         }
160
161       for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
162         {
163           n_stmts++;
164           n_p_stmts += bb->count;
165         }
166
167       if (loop->header == bb && loop_in_sese_p (loop, SCOP_REGION (scop)))
168         {
169           n_loops++;
170           n_p_loops += bb->count;
171         }
172     }
173
174   fprintf (file, "\nSCoP statistics (");
175   fprintf (file, "BBS:%ld, ", n_bbs);
176   fprintf (file, "LOOPS:%ld, ", n_loops);
177   fprintf (file, "CONDITIONS:%ld, ", n_conditions);
178   fprintf (file, "STMTS:%ld)\n", n_stmts);
179   fprintf (file, "\nSCoP profiling statistics (");
180   fprintf (file, "BBS:%ld, ", n_p_bbs);
181   fprintf (file, "LOOPS:%ld, ", n_p_loops);
182   fprintf (file, "CONDITIONS:%ld, ", n_p_conditions);
183   fprintf (file, "STMTS:%ld)\n", n_p_stmts);
184 }
185
186 /* Print statistics for SCOPS to FILE.  */
187
188 static void
189 print_graphite_statistics (FILE* file, VEC (scop_p, heap) *scops)
190 {
191   int i;
192
193   scop_p scop;
194
195   FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
196     print_graphite_scop_statistics (file, scop);
197 }
198
199 /* Initialize graphite: when there are no loops returns false.  */
200
201 static bool
202 graphite_initialize (void)
203 {
204   int ppl_initialized;
205
206   if (number_of_loops () <= 1
207       /* FIXME: This limit on the number of basic blocks of a function
208          should be removed when the SCOP detection is faster.  */
209       || n_basic_blocks > PARAM_VALUE (PARAM_GRAPHITE_MAX_BBS_PER_FUNCTION))
210     {
211       if (dump_file && (dump_flags & TDF_DETAILS))
212         print_global_statistics (dump_file);
213
214       return false;
215     }
216
217   recompute_all_dominators ();
218   initialize_original_copy_tables ();
219
220   ppl_initialized = ppl_initialize ();
221   gcc_assert (ppl_initialized == 0);
222
223   cloog_initialize ();
224
225   if (dump_file && dump_flags)
226     dump_function_to_file (current_function_decl, dump_file, dump_flags);
227
228   return true;
229 }
230
231 /* Finalize graphite: perform CFG cleanup when NEED_CFG_CLEANUP_P is
232    true.  */
233
234 static void
235 graphite_finalize (bool need_cfg_cleanup_p)
236 {
237   if (need_cfg_cleanup_p)
238     {
239       scev_reset ();
240       cleanup_tree_cfg ();
241       profile_status = PROFILE_ABSENT;
242       release_recorded_exits ();
243       tree_estimate_probability ();
244     }
245
246   cloog_finalize ();
247   ppl_finalize ();
248   free_original_copy_tables ();
249
250   if (dump_file && dump_flags)
251     print_loops (dump_file, 3);
252 }
253
254 /* Perform a set of linear transforms on the loops of the current
255    function.  */
256
257 void
258 graphite_transform_loops (void)
259 {
260   int i;
261   scop_p scop;
262   bool need_cfg_cleanup_p = false;
263   VEC (scop_p, heap) *scops = NULL;
264   htab_t bb_pbb_mapping;
265   sbitmap reductions;
266
267   if (!graphite_initialize ())
268     return;
269
270   build_scops (&scops);
271
272   if (dump_file && (dump_flags & TDF_DETAILS))
273     {
274       print_graphite_statistics (dump_file, scops);
275       print_global_statistics (dump_file);
276     }
277
278   bb_pbb_mapping = htab_create (10, bb_pbb_map_hash, eq_bb_pbb_map, free);
279   reductions = sbitmap_alloc (last_basic_block * 2);
280   sbitmap_zero (reductions);
281
282   FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
283     if (dbg_cnt (graphite_scop))
284       rewrite_commutative_reductions_out_of_ssa (SCOP_REGION (scop),
285                                                  reductions);
286
287   FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
288     if (dbg_cnt (graphite_scop))
289       {
290         rewrite_reductions_out_of_ssa (scop);
291         rewrite_cross_bb_scalar_deps_out_of_ssa (scop);
292         build_scop_bbs (scop, reductions);
293       }
294
295   sbitmap_free (reductions);
296
297   FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
298     if (dbg_cnt (graphite_scop))
299       build_poly_scop (scop);
300
301   FOR_EACH_VEC_ELT (scop_p, scops, i, scop)
302     if (POLY_SCOP_P (scop)
303         && apply_poly_transforms (scop)
304         && gloog (scop, bb_pbb_mapping))
305       need_cfg_cleanup_p = true;
306
307   htab_delete (bb_pbb_mapping);
308   free_scops (scops);
309   graphite_finalize (need_cfg_cleanup_p);
310 }
311
312 #else /* If Cloog is not available: #ifndef HAVE_cloog.  */
313
314 void
315 graphite_transform_loops (void)
316 {
317   sorry ("Graphite loop optimizations cannot be used");
318 }
319
320 #endif