1*e4b17023SJohn Marino /* Loop optimizations over tree-ssa.
2*e4b17023SJohn Marino    Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
8*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the
9*e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any
10*e4b17023SJohn Marino later version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
13*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*e4b17023SJohn Marino for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino #include "tm_p.h"
27*e4b17023SJohn Marino #include "basic-block.h"
28*e4b17023SJohn Marino #include "output.h"
29*e4b17023SJohn Marino #include "tree-flow.h"
30*e4b17023SJohn Marino #include "tree-dump.h"
31*e4b17023SJohn Marino #include "tree-pass.h"
32*e4b17023SJohn Marino #include "timevar.h"
33*e4b17023SJohn Marino #include "cfgloop.h"
34*e4b17023SJohn Marino #include "flags.h"
35*e4b17023SJohn Marino #include "tree-inline.h"
36*e4b17023SJohn Marino #include "tree-scalar-evolution.h"
37*e4b17023SJohn Marino #include "diagnostic-core.h"
38*e4b17023SJohn Marino #include "tree-vectorizer.h"
39*e4b17023SJohn Marino 
40*e4b17023SJohn Marino /* The loop superpass.  */
41*e4b17023SJohn Marino 
42*e4b17023SJohn Marino static bool
gate_tree_loop(void)43*e4b17023SJohn Marino gate_tree_loop (void)
44*e4b17023SJohn Marino {
45*e4b17023SJohn Marino   return flag_tree_loop_optimize != 0;
46*e4b17023SJohn Marino }
47*e4b17023SJohn Marino 
48*e4b17023SJohn Marino struct gimple_opt_pass pass_tree_loop =
49*e4b17023SJohn Marino {
50*e4b17023SJohn Marino  {
51*e4b17023SJohn Marino   GIMPLE_PASS,
52*e4b17023SJohn Marino   "loop",				/* name */
53*e4b17023SJohn Marino   gate_tree_loop,			/* gate */
54*e4b17023SJohn Marino   NULL,					/* execute */
55*e4b17023SJohn Marino   NULL,					/* sub */
56*e4b17023SJohn Marino   NULL,					/* next */
57*e4b17023SJohn Marino   0,					/* static_pass_number */
58*e4b17023SJohn Marino   TV_TREE_LOOP,				/* tv_id */
59*e4b17023SJohn Marino   PROP_cfg,				/* properties_required */
60*e4b17023SJohn Marino   0,					/* properties_provided */
61*e4b17023SJohn Marino   0,					/* properties_destroyed */
62*e4b17023SJohn Marino   TODO_ggc_collect,			/* todo_flags_start */
63*e4b17023SJohn Marino   TODO_verify_ssa | TODO_ggc_collect	/* todo_flags_finish */
64*e4b17023SJohn Marino  }
65*e4b17023SJohn Marino };
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino /* Loop optimizer initialization.  */
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_init(void)70*e4b17023SJohn Marino tree_ssa_loop_init (void)
71*e4b17023SJohn Marino {
72*e4b17023SJohn Marino   loop_optimizer_init (LOOPS_NORMAL
73*e4b17023SJohn Marino 		       | LOOPS_HAVE_RECORDED_EXITS);
74*e4b17023SJohn Marino   rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
75*e4b17023SJohn Marino 
76*e4b17023SJohn Marino   if (number_of_loops () <= 1)
77*e4b17023SJohn Marino     return 0;
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino   scev_initialize ();
80*e4b17023SJohn Marino   return 0;
81*e4b17023SJohn Marino }
82*e4b17023SJohn Marino 
83*e4b17023SJohn Marino struct gimple_opt_pass pass_tree_loop_init =
84*e4b17023SJohn Marino {
85*e4b17023SJohn Marino  {
86*e4b17023SJohn Marino   GIMPLE_PASS,
87*e4b17023SJohn Marino   "loopinit",				/* name */
88*e4b17023SJohn Marino   NULL,					/* gate */
89*e4b17023SJohn Marino   tree_ssa_loop_init,			/* execute */
90*e4b17023SJohn Marino   NULL,					/* sub */
91*e4b17023SJohn Marino   NULL,					/* next */
92*e4b17023SJohn Marino   0,					/* static_pass_number */
93*e4b17023SJohn Marino   TV_TREE_LOOP_INIT,			/* tv_id */
94*e4b17023SJohn Marino   PROP_cfg,				/* properties_required */
95*e4b17023SJohn Marino   0,					/* properties_provided */
96*e4b17023SJohn Marino   0,					/* properties_destroyed */
97*e4b17023SJohn Marino   0,					/* todo_flags_start */
98*e4b17023SJohn Marino   0             			/* todo_flags_finish */
99*e4b17023SJohn Marino  }
100*e4b17023SJohn Marino };
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino /* Loop invariant motion pass.  */
103*e4b17023SJohn Marino 
104*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_im(void)105*e4b17023SJohn Marino tree_ssa_loop_im (void)
106*e4b17023SJohn Marino {
107*e4b17023SJohn Marino   if (number_of_loops () <= 1)
108*e4b17023SJohn Marino     return 0;
109*e4b17023SJohn Marino 
110*e4b17023SJohn Marino   return tree_ssa_lim ();
111*e4b17023SJohn Marino }
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino static bool
gate_tree_ssa_loop_im(void)114*e4b17023SJohn Marino gate_tree_ssa_loop_im (void)
115*e4b17023SJohn Marino {
116*e4b17023SJohn Marino   return flag_tree_loop_im != 0;
117*e4b17023SJohn Marino }
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino struct gimple_opt_pass pass_lim =
120*e4b17023SJohn Marino {
121*e4b17023SJohn Marino  {
122*e4b17023SJohn Marino   GIMPLE_PASS,
123*e4b17023SJohn Marino   "lim",				/* name */
124*e4b17023SJohn Marino   gate_tree_ssa_loop_im,		/* gate */
125*e4b17023SJohn Marino   tree_ssa_loop_im,			/* execute */
126*e4b17023SJohn Marino   NULL,					/* sub */
127*e4b17023SJohn Marino   NULL,					/* next */
128*e4b17023SJohn Marino   0,					/* static_pass_number */
129*e4b17023SJohn Marino   TV_LIM,				/* tv_id */
130*e4b17023SJohn Marino   PROP_cfg,				/* properties_required */
131*e4b17023SJohn Marino   0,					/* properties_provided */
132*e4b17023SJohn Marino   0,					/* properties_destroyed */
133*e4b17023SJohn Marino   0,					/* todo_flags_start */
134*e4b17023SJohn Marino   0             			/* todo_flags_finish */
135*e4b17023SJohn Marino  }
136*e4b17023SJohn Marino };
137*e4b17023SJohn Marino 
138*e4b17023SJohn Marino /* Loop unswitching pass.  */
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_unswitch(void)141*e4b17023SJohn Marino tree_ssa_loop_unswitch (void)
142*e4b17023SJohn Marino {
143*e4b17023SJohn Marino   if (number_of_loops () <= 1)
144*e4b17023SJohn Marino     return 0;
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino   return tree_ssa_unswitch_loops ();
147*e4b17023SJohn Marino }
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino static bool
gate_tree_ssa_loop_unswitch(void)150*e4b17023SJohn Marino gate_tree_ssa_loop_unswitch (void)
151*e4b17023SJohn Marino {
152*e4b17023SJohn Marino   return flag_unswitch_loops != 0;
153*e4b17023SJohn Marino }
154*e4b17023SJohn Marino 
155*e4b17023SJohn Marino struct gimple_opt_pass pass_tree_unswitch =
156*e4b17023SJohn Marino {
157*e4b17023SJohn Marino  {
158*e4b17023SJohn Marino   GIMPLE_PASS,
159*e4b17023SJohn Marino   "unswitch",				/* name */
160*e4b17023SJohn Marino   gate_tree_ssa_loop_unswitch,		/* gate */
161*e4b17023SJohn Marino   tree_ssa_loop_unswitch,		/* execute */
162*e4b17023SJohn Marino   NULL,					/* sub */
163*e4b17023SJohn Marino   NULL,					/* next */
164*e4b17023SJohn Marino   0,					/* static_pass_number */
165*e4b17023SJohn Marino   TV_TREE_LOOP_UNSWITCH,		/* tv_id */
166*e4b17023SJohn Marino   PROP_cfg,				/* properties_required */
167*e4b17023SJohn Marino   0,					/* properties_provided */
168*e4b17023SJohn Marino   0,					/* properties_destroyed */
169*e4b17023SJohn Marino   0,					/* todo_flags_start */
170*e4b17023SJohn Marino   TODO_ggc_collect                  	/* todo_flags_finish */
171*e4b17023SJohn Marino  }
172*e4b17023SJohn Marino };
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino /* Predictive commoning.  */
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino static unsigned
run_tree_predictive_commoning(void)177*e4b17023SJohn Marino run_tree_predictive_commoning (void)
178*e4b17023SJohn Marino {
179*e4b17023SJohn Marino   if (!current_loops)
180*e4b17023SJohn Marino     return 0;
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino   return tree_predictive_commoning ();
183*e4b17023SJohn Marino }
184*e4b17023SJohn Marino 
185*e4b17023SJohn Marino static bool
gate_tree_predictive_commoning(void)186*e4b17023SJohn Marino gate_tree_predictive_commoning (void)
187*e4b17023SJohn Marino {
188*e4b17023SJohn Marino   return flag_predictive_commoning != 0;
189*e4b17023SJohn Marino }
190*e4b17023SJohn Marino 
191*e4b17023SJohn Marino struct gimple_opt_pass pass_predcom =
192*e4b17023SJohn Marino {
193*e4b17023SJohn Marino  {
194*e4b17023SJohn Marino   GIMPLE_PASS,
195*e4b17023SJohn Marino   "pcom",				/* name */
196*e4b17023SJohn Marino   gate_tree_predictive_commoning,	/* gate */
197*e4b17023SJohn Marino   run_tree_predictive_commoning,	/* execute */
198*e4b17023SJohn Marino   NULL,					/* sub */
199*e4b17023SJohn Marino   NULL,					/* next */
200*e4b17023SJohn Marino   0,					/* static_pass_number */
201*e4b17023SJohn Marino   TV_PREDCOM,				/* tv_id */
202*e4b17023SJohn Marino   PROP_cfg,				/* properties_required */
203*e4b17023SJohn Marino   0,					/* properties_provided */
204*e4b17023SJohn Marino   0,					/* properties_destroyed */
205*e4b17023SJohn Marino   0,					/* todo_flags_start */
206*e4b17023SJohn Marino   TODO_update_ssa_only_virtuals 	/* todo_flags_finish */
207*e4b17023SJohn Marino  }
208*e4b17023SJohn Marino };
209*e4b17023SJohn Marino 
210*e4b17023SJohn Marino /* Loop autovectorization.  */
211*e4b17023SJohn Marino 
212*e4b17023SJohn Marino static unsigned int
tree_vectorize(void)213*e4b17023SJohn Marino tree_vectorize (void)
214*e4b17023SJohn Marino {
215*e4b17023SJohn Marino   if (number_of_loops () <= 1)
216*e4b17023SJohn Marino     return 0;
217*e4b17023SJohn Marino 
218*e4b17023SJohn Marino   return vectorize_loops ();
219*e4b17023SJohn Marino }
220*e4b17023SJohn Marino 
221*e4b17023SJohn Marino static bool
gate_tree_vectorize(void)222*e4b17023SJohn Marino gate_tree_vectorize (void)
223*e4b17023SJohn Marino {
224*e4b17023SJohn Marino   return flag_tree_vectorize;
225*e4b17023SJohn Marino }
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino struct gimple_opt_pass pass_vectorize =
228*e4b17023SJohn Marino {
229*e4b17023SJohn Marino  {
230*e4b17023SJohn Marino   GIMPLE_PASS,
231*e4b17023SJohn Marino   "vect",                               /* name */
232*e4b17023SJohn Marino   gate_tree_vectorize,                  /* gate */
233*e4b17023SJohn Marino   tree_vectorize,                       /* execute */
234*e4b17023SJohn Marino   NULL,                                 /* sub */
235*e4b17023SJohn Marino   NULL,                                 /* next */
236*e4b17023SJohn Marino   0,                                    /* static_pass_number */
237*e4b17023SJohn Marino   TV_TREE_VECTORIZATION,                /* tv_id */
238*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,                  /* properties_required */
239*e4b17023SJohn Marino   0,                                    /* properties_provided */
240*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
241*e4b17023SJohn Marino   0,					/* todo_flags_start */
242*e4b17023SJohn Marino   TODO_update_ssa
243*e4b17023SJohn Marino     | TODO_ggc_collect			/* todo_flags_finish */
244*e4b17023SJohn Marino  }
245*e4b17023SJohn Marino };
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino /* GRAPHITE optimizations.  */
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino static unsigned int
graphite_transforms(void)250*e4b17023SJohn Marino graphite_transforms (void)
251*e4b17023SJohn Marino {
252*e4b17023SJohn Marino   if (!current_loops)
253*e4b17023SJohn Marino     return 0;
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino   graphite_transform_loops ();
256*e4b17023SJohn Marino 
257*e4b17023SJohn Marino   return 0;
258*e4b17023SJohn Marino }
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino static bool
gate_graphite_transforms(void)261*e4b17023SJohn Marino gate_graphite_transforms (void)
262*e4b17023SJohn Marino {
263*e4b17023SJohn Marino   /* Enable -fgraphite pass if any one of the graphite optimization flags
264*e4b17023SJohn Marino      is turned on.  */
265*e4b17023SJohn Marino   if (flag_loop_block
266*e4b17023SJohn Marino       || flag_loop_interchange
267*e4b17023SJohn Marino       || flag_loop_strip_mine
268*e4b17023SJohn Marino       || flag_graphite_identity
269*e4b17023SJohn Marino       || flag_loop_parallelize_all
270*e4b17023SJohn Marino       || flag_loop_flatten)
271*e4b17023SJohn Marino     flag_graphite = 1;
272*e4b17023SJohn Marino 
273*e4b17023SJohn Marino   return flag_graphite != 0;
274*e4b17023SJohn Marino }
275*e4b17023SJohn Marino 
276*e4b17023SJohn Marino struct gimple_opt_pass pass_graphite =
277*e4b17023SJohn Marino {
278*e4b17023SJohn Marino  {
279*e4b17023SJohn Marino   GIMPLE_PASS,
280*e4b17023SJohn Marino   "graphite0",				/* name */
281*e4b17023SJohn Marino   gate_graphite_transforms,		/* gate */
282*e4b17023SJohn Marino   NULL,					/* execute */
283*e4b17023SJohn Marino   NULL,					/* sub */
284*e4b17023SJohn Marino   NULL,					/* next */
285*e4b17023SJohn Marino   0,					/* static_pass_number */
286*e4b17023SJohn Marino   TV_GRAPHITE,				/* tv_id */
287*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
288*e4b17023SJohn Marino   0,					/* properties_provided */
289*e4b17023SJohn Marino   0,					/* properties_destroyed */
290*e4b17023SJohn Marino   0,					/* todo_flags_start */
291*e4b17023SJohn Marino   0					/* todo_flags_finish */
292*e4b17023SJohn Marino  }
293*e4b17023SJohn Marino };
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino struct gimple_opt_pass pass_graphite_transforms =
296*e4b17023SJohn Marino {
297*e4b17023SJohn Marino  {
298*e4b17023SJohn Marino   GIMPLE_PASS,
299*e4b17023SJohn Marino   "graphite",				/* name */
300*e4b17023SJohn Marino   gate_graphite_transforms,		/* gate */
301*e4b17023SJohn Marino   graphite_transforms,       		/* execute */
302*e4b17023SJohn Marino   NULL,					/* sub */
303*e4b17023SJohn Marino   NULL,					/* next */
304*e4b17023SJohn Marino   0,					/* static_pass_number */
305*e4b17023SJohn Marino   TV_GRAPHITE_TRANSFORMS,  		/* tv_id */
306*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
307*e4b17023SJohn Marino   0,					/* properties_provided */
308*e4b17023SJohn Marino   0,					/* properties_destroyed */
309*e4b17023SJohn Marino   0,					/* todo_flags_start */
310*e4b17023SJohn Marino   0             			/* todo_flags_finish */
311*e4b17023SJohn Marino  }
312*e4b17023SJohn Marino };
313*e4b17023SJohn Marino 
314*e4b17023SJohn Marino /* Check the correctness of the data dependence analyzers.  */
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino static unsigned int
check_data_deps(void)317*e4b17023SJohn Marino check_data_deps (void)
318*e4b17023SJohn Marino {
319*e4b17023SJohn Marino   if (number_of_loops () <= 1)
320*e4b17023SJohn Marino     return 0;
321*e4b17023SJohn Marino 
322*e4b17023SJohn Marino   tree_check_data_deps ();
323*e4b17023SJohn Marino   return 0;
324*e4b17023SJohn Marino }
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino static bool
gate_check_data_deps(void)327*e4b17023SJohn Marino gate_check_data_deps (void)
328*e4b17023SJohn Marino {
329*e4b17023SJohn Marino   return flag_check_data_deps != 0;
330*e4b17023SJohn Marino }
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino struct gimple_opt_pass pass_check_data_deps =
333*e4b17023SJohn Marino {
334*e4b17023SJohn Marino  {
335*e4b17023SJohn Marino   GIMPLE_PASS,
336*e4b17023SJohn Marino   "ckdd",				/* name */
337*e4b17023SJohn Marino   gate_check_data_deps,	        	/* gate */
338*e4b17023SJohn Marino   check_data_deps,       		/* execute */
339*e4b17023SJohn Marino   NULL,					/* sub */
340*e4b17023SJohn Marino   NULL,					/* next */
341*e4b17023SJohn Marino   0,					/* static_pass_number */
342*e4b17023SJohn Marino   TV_CHECK_DATA_DEPS,  	        	/* tv_id */
343*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
344*e4b17023SJohn Marino   0,					/* properties_provided */
345*e4b17023SJohn Marino   0,					/* properties_destroyed */
346*e4b17023SJohn Marino   0,					/* todo_flags_start */
347*e4b17023SJohn Marino   0                             	/* todo_flags_finish */
348*e4b17023SJohn Marino  }
349*e4b17023SJohn Marino };
350*e4b17023SJohn Marino 
351*e4b17023SJohn Marino /* Canonical induction variable creation pass.  */
352*e4b17023SJohn Marino 
353*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_ivcanon(void)354*e4b17023SJohn Marino tree_ssa_loop_ivcanon (void)
355*e4b17023SJohn Marino {
356*e4b17023SJohn Marino   if (number_of_loops () <= 1)
357*e4b17023SJohn Marino     return 0;
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino   return canonicalize_induction_variables ();
360*e4b17023SJohn Marino }
361*e4b17023SJohn Marino 
362*e4b17023SJohn Marino static bool
gate_tree_ssa_loop_ivcanon(void)363*e4b17023SJohn Marino gate_tree_ssa_loop_ivcanon (void)
364*e4b17023SJohn Marino {
365*e4b17023SJohn Marino   return flag_tree_loop_ivcanon != 0;
366*e4b17023SJohn Marino }
367*e4b17023SJohn Marino 
368*e4b17023SJohn Marino struct gimple_opt_pass pass_iv_canon =
369*e4b17023SJohn Marino {
370*e4b17023SJohn Marino  {
371*e4b17023SJohn Marino   GIMPLE_PASS,
372*e4b17023SJohn Marino   "ivcanon",				/* name */
373*e4b17023SJohn Marino   gate_tree_ssa_loop_ivcanon,		/* gate */
374*e4b17023SJohn Marino   tree_ssa_loop_ivcanon,	       	/* execute */
375*e4b17023SJohn Marino   NULL,					/* sub */
376*e4b17023SJohn Marino   NULL,					/* next */
377*e4b17023SJohn Marino   0,					/* static_pass_number */
378*e4b17023SJohn Marino   TV_TREE_LOOP_IVCANON,	  		/* tv_id */
379*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
380*e4b17023SJohn Marino   0,					/* properties_provided */
381*e4b17023SJohn Marino   0,					/* properties_destroyed */
382*e4b17023SJohn Marino   0,					/* todo_flags_start */
383*e4b17023SJohn Marino   0             			/* todo_flags_finish */
384*e4b17023SJohn Marino  }
385*e4b17023SJohn Marino };
386*e4b17023SJohn Marino 
387*e4b17023SJohn Marino /* Propagation of constants using scev.  */
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino static bool
gate_scev_const_prop(void)390*e4b17023SJohn Marino gate_scev_const_prop (void)
391*e4b17023SJohn Marino {
392*e4b17023SJohn Marino   return flag_tree_scev_cprop;
393*e4b17023SJohn Marino }
394*e4b17023SJohn Marino 
395*e4b17023SJohn Marino struct gimple_opt_pass pass_scev_cprop =
396*e4b17023SJohn Marino {
397*e4b17023SJohn Marino  {
398*e4b17023SJohn Marino   GIMPLE_PASS,
399*e4b17023SJohn Marino   "sccp",				/* name */
400*e4b17023SJohn Marino   gate_scev_const_prop,			/* gate */
401*e4b17023SJohn Marino   scev_const_prop,	       		/* execute */
402*e4b17023SJohn Marino   NULL,					/* sub */
403*e4b17023SJohn Marino   NULL,					/* next */
404*e4b17023SJohn Marino   0,					/* static_pass_number */
405*e4b17023SJohn Marino   TV_SCEV_CONST,	  		/* tv_id */
406*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
407*e4b17023SJohn Marino   0,					/* properties_provided */
408*e4b17023SJohn Marino   0,					/* properties_destroyed */
409*e4b17023SJohn Marino   0,					/* todo_flags_start */
410*e4b17023SJohn Marino   TODO_cleanup_cfg
411*e4b17023SJohn Marino     | TODO_update_ssa_only_virtuals
412*e4b17023SJohn Marino 					/* todo_flags_finish */
413*e4b17023SJohn Marino  }
414*e4b17023SJohn Marino };
415*e4b17023SJohn Marino 
416*e4b17023SJohn Marino /* Record bounds on numbers of iterations of loops.  */
417*e4b17023SJohn Marino 
418*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_bounds(void)419*e4b17023SJohn Marino tree_ssa_loop_bounds (void)
420*e4b17023SJohn Marino {
421*e4b17023SJohn Marino   if (number_of_loops () <= 1)
422*e4b17023SJohn Marino     return 0;
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino   estimate_numbers_of_iterations (true);
425*e4b17023SJohn Marino   scev_reset ();
426*e4b17023SJohn Marino   return 0;
427*e4b17023SJohn Marino }
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino struct gimple_opt_pass pass_record_bounds =
430*e4b17023SJohn Marino {
431*e4b17023SJohn Marino  {
432*e4b17023SJohn Marino   GIMPLE_PASS,
433*e4b17023SJohn Marino   "*record_bounds",			/* name */
434*e4b17023SJohn Marino   NULL,					/* gate */
435*e4b17023SJohn Marino   tree_ssa_loop_bounds,		       	/* execute */
436*e4b17023SJohn Marino   NULL,					/* sub */
437*e4b17023SJohn Marino   NULL,					/* next */
438*e4b17023SJohn Marino   0,					/* static_pass_number */
439*e4b17023SJohn Marino   TV_TREE_LOOP_BOUNDS,	  		/* tv_id */
440*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
441*e4b17023SJohn Marino   0,					/* properties_provided */
442*e4b17023SJohn Marino   0,					/* properties_destroyed */
443*e4b17023SJohn Marino   0,					/* todo_flags_start */
444*e4b17023SJohn Marino   0			              	/* todo_flags_finish */
445*e4b17023SJohn Marino  }
446*e4b17023SJohn Marino };
447*e4b17023SJohn Marino 
448*e4b17023SJohn Marino /* Complete unrolling of loops.  */
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino static unsigned int
tree_complete_unroll(void)451*e4b17023SJohn Marino tree_complete_unroll (void)
452*e4b17023SJohn Marino {
453*e4b17023SJohn Marino   if (number_of_loops () <= 1)
454*e4b17023SJohn Marino     return 0;
455*e4b17023SJohn Marino 
456*e4b17023SJohn Marino   return tree_unroll_loops_completely (flag_unroll_loops
457*e4b17023SJohn Marino 				       || flag_peel_loops
458*e4b17023SJohn Marino 				       || optimize >= 3, true);
459*e4b17023SJohn Marino }
460*e4b17023SJohn Marino 
461*e4b17023SJohn Marino static bool
gate_tree_complete_unroll(void)462*e4b17023SJohn Marino gate_tree_complete_unroll (void)
463*e4b17023SJohn Marino {
464*e4b17023SJohn Marino   return true;
465*e4b17023SJohn Marino }
466*e4b17023SJohn Marino 
467*e4b17023SJohn Marino struct gimple_opt_pass pass_complete_unroll =
468*e4b17023SJohn Marino {
469*e4b17023SJohn Marino  {
470*e4b17023SJohn Marino   GIMPLE_PASS,
471*e4b17023SJohn Marino   "cunroll",				/* name */
472*e4b17023SJohn Marino   gate_tree_complete_unroll,		/* gate */
473*e4b17023SJohn Marino   tree_complete_unroll,		       	/* execute */
474*e4b17023SJohn Marino   NULL,					/* sub */
475*e4b17023SJohn Marino   NULL,					/* next */
476*e4b17023SJohn Marino   0,					/* static_pass_number */
477*e4b17023SJohn Marino   TV_COMPLETE_UNROLL,	  		/* tv_id */
478*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
479*e4b17023SJohn Marino   0,					/* properties_provided */
480*e4b17023SJohn Marino   0,					/* properties_destroyed */
481*e4b17023SJohn Marino   0,					/* todo_flags_start */
482*e4b17023SJohn Marino   TODO_ggc_collect			/* todo_flags_finish */
483*e4b17023SJohn Marino  }
484*e4b17023SJohn Marino };
485*e4b17023SJohn Marino 
486*e4b17023SJohn Marino /* Complete unrolling of inner loops.  */
487*e4b17023SJohn Marino 
488*e4b17023SJohn Marino static unsigned int
tree_complete_unroll_inner(void)489*e4b17023SJohn Marino tree_complete_unroll_inner (void)
490*e4b17023SJohn Marino {
491*e4b17023SJohn Marino   unsigned ret = 0;
492*e4b17023SJohn Marino 
493*e4b17023SJohn Marino   loop_optimizer_init (LOOPS_NORMAL
494*e4b17023SJohn Marino 		       | LOOPS_HAVE_RECORDED_EXITS);
495*e4b17023SJohn Marino   if (number_of_loops () > 1)
496*e4b17023SJohn Marino     {
497*e4b17023SJohn Marino       scev_initialize ();
498*e4b17023SJohn Marino       ret = tree_unroll_loops_completely (optimize >= 3, false);
499*e4b17023SJohn Marino       free_numbers_of_iterations_estimates ();
500*e4b17023SJohn Marino       scev_finalize ();
501*e4b17023SJohn Marino     }
502*e4b17023SJohn Marino   loop_optimizer_finalize ();
503*e4b17023SJohn Marino 
504*e4b17023SJohn Marino   return ret;
505*e4b17023SJohn Marino }
506*e4b17023SJohn Marino 
507*e4b17023SJohn Marino static bool
gate_tree_complete_unroll_inner(void)508*e4b17023SJohn Marino gate_tree_complete_unroll_inner (void)
509*e4b17023SJohn Marino {
510*e4b17023SJohn Marino   return optimize >= 2;
511*e4b17023SJohn Marino }
512*e4b17023SJohn Marino 
513*e4b17023SJohn Marino struct gimple_opt_pass pass_complete_unrolli =
514*e4b17023SJohn Marino {
515*e4b17023SJohn Marino  {
516*e4b17023SJohn Marino   GIMPLE_PASS,
517*e4b17023SJohn Marino   "cunrolli",				/* name */
518*e4b17023SJohn Marino   gate_tree_complete_unroll_inner,	/* gate */
519*e4b17023SJohn Marino   tree_complete_unroll_inner,	       	/* execute */
520*e4b17023SJohn Marino   NULL,					/* sub */
521*e4b17023SJohn Marino   NULL,					/* next */
522*e4b17023SJohn Marino   0,					/* static_pass_number */
523*e4b17023SJohn Marino   TV_COMPLETE_UNROLL,	  		/* tv_id */
524*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
525*e4b17023SJohn Marino   0,					/* properties_provided */
526*e4b17023SJohn Marino   0,					/* properties_destroyed */
527*e4b17023SJohn Marino   0,					/* todo_flags_start */
528*e4b17023SJohn Marino   TODO_verify_flow
529*e4b17023SJohn Marino     | TODO_ggc_collect 			/* todo_flags_finish */
530*e4b17023SJohn Marino  }
531*e4b17023SJohn Marino };
532*e4b17023SJohn Marino 
533*e4b17023SJohn Marino /* Parallelization.  */
534*e4b17023SJohn Marino 
535*e4b17023SJohn Marino static bool
gate_tree_parallelize_loops(void)536*e4b17023SJohn Marino gate_tree_parallelize_loops (void)
537*e4b17023SJohn Marino {
538*e4b17023SJohn Marino   return flag_tree_parallelize_loops > 1;
539*e4b17023SJohn Marino }
540*e4b17023SJohn Marino 
541*e4b17023SJohn Marino static unsigned
tree_parallelize_loops(void)542*e4b17023SJohn Marino tree_parallelize_loops (void)
543*e4b17023SJohn Marino {
544*e4b17023SJohn Marino   if (number_of_loops () <= 1)
545*e4b17023SJohn Marino     return 0;
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino   if (parallelize_loops ())
548*e4b17023SJohn Marino     return TODO_cleanup_cfg | TODO_rebuild_alias;
549*e4b17023SJohn Marino   return 0;
550*e4b17023SJohn Marino }
551*e4b17023SJohn Marino 
552*e4b17023SJohn Marino struct gimple_opt_pass pass_parallelize_loops =
553*e4b17023SJohn Marino {
554*e4b17023SJohn Marino  {
555*e4b17023SJohn Marino   GIMPLE_PASS,
556*e4b17023SJohn Marino   "parloops",				/* name */
557*e4b17023SJohn Marino   gate_tree_parallelize_loops,		/* gate */
558*e4b17023SJohn Marino   tree_parallelize_loops,      		/* execute */
559*e4b17023SJohn Marino   NULL,					/* sub */
560*e4b17023SJohn Marino   NULL,					/* next */
561*e4b17023SJohn Marino   0,					/* static_pass_number */
562*e4b17023SJohn Marino   TV_TREE_PARALLELIZE_LOOPS,  		/* tv_id */
563*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
564*e4b17023SJohn Marino   0,					/* properties_provided */
565*e4b17023SJohn Marino   0,					/* properties_destroyed */
566*e4b17023SJohn Marino   0,					/* todo_flags_start */
567*e4b17023SJohn Marino   0             			/* todo_flags_finish */
568*e4b17023SJohn Marino  }
569*e4b17023SJohn Marino };
570*e4b17023SJohn Marino 
571*e4b17023SJohn Marino /* Prefetching.  */
572*e4b17023SJohn Marino 
573*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_prefetch(void)574*e4b17023SJohn Marino tree_ssa_loop_prefetch (void)
575*e4b17023SJohn Marino {
576*e4b17023SJohn Marino   if (number_of_loops () <= 1)
577*e4b17023SJohn Marino     return 0;
578*e4b17023SJohn Marino 
579*e4b17023SJohn Marino   return tree_ssa_prefetch_arrays ();
580*e4b17023SJohn Marino }
581*e4b17023SJohn Marino 
582*e4b17023SJohn Marino static bool
gate_tree_ssa_loop_prefetch(void)583*e4b17023SJohn Marino gate_tree_ssa_loop_prefetch (void)
584*e4b17023SJohn Marino {
585*e4b17023SJohn Marino   return flag_prefetch_loop_arrays > 0;
586*e4b17023SJohn Marino }
587*e4b17023SJohn Marino 
588*e4b17023SJohn Marino struct gimple_opt_pass pass_loop_prefetch =
589*e4b17023SJohn Marino {
590*e4b17023SJohn Marino  {
591*e4b17023SJohn Marino   GIMPLE_PASS,
592*e4b17023SJohn Marino   "aprefetch",				/* name */
593*e4b17023SJohn Marino   gate_tree_ssa_loop_prefetch,		/* gate */
594*e4b17023SJohn Marino   tree_ssa_loop_prefetch,	       	/* execute */
595*e4b17023SJohn Marino   NULL,					/* sub */
596*e4b17023SJohn Marino   NULL,					/* next */
597*e4b17023SJohn Marino   0,					/* static_pass_number */
598*e4b17023SJohn Marino   TV_TREE_PREFETCH,	  		/* tv_id */
599*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
600*e4b17023SJohn Marino   0,					/* properties_provided */
601*e4b17023SJohn Marino   0,					/* properties_destroyed */
602*e4b17023SJohn Marino   0,					/* todo_flags_start */
603*e4b17023SJohn Marino   0             			/* todo_flags_finish */
604*e4b17023SJohn Marino  }
605*e4b17023SJohn Marino };
606*e4b17023SJohn Marino 
607*e4b17023SJohn Marino /* Induction variable optimizations.  */
608*e4b17023SJohn Marino 
609*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_ivopts(void)610*e4b17023SJohn Marino tree_ssa_loop_ivopts (void)
611*e4b17023SJohn Marino {
612*e4b17023SJohn Marino   if (number_of_loops () <= 1)
613*e4b17023SJohn Marino     return 0;
614*e4b17023SJohn Marino 
615*e4b17023SJohn Marino   tree_ssa_iv_optimize ();
616*e4b17023SJohn Marino   return 0;
617*e4b17023SJohn Marino }
618*e4b17023SJohn Marino 
619*e4b17023SJohn Marino static bool
gate_tree_ssa_loop_ivopts(void)620*e4b17023SJohn Marino gate_tree_ssa_loop_ivopts (void)
621*e4b17023SJohn Marino {
622*e4b17023SJohn Marino   return flag_ivopts != 0;
623*e4b17023SJohn Marino }
624*e4b17023SJohn Marino 
625*e4b17023SJohn Marino struct gimple_opt_pass pass_iv_optimize =
626*e4b17023SJohn Marino {
627*e4b17023SJohn Marino  {
628*e4b17023SJohn Marino   GIMPLE_PASS,
629*e4b17023SJohn Marino   "ivopts",				/* name */
630*e4b17023SJohn Marino   gate_tree_ssa_loop_ivopts,		/* gate */
631*e4b17023SJohn Marino   tree_ssa_loop_ivopts,		       	/* execute */
632*e4b17023SJohn Marino   NULL,					/* sub */
633*e4b17023SJohn Marino   NULL,					/* next */
634*e4b17023SJohn Marino   0,					/* static_pass_number */
635*e4b17023SJohn Marino   TV_TREE_LOOP_IVOPTS,	  		/* tv_id */
636*e4b17023SJohn Marino   PROP_cfg | PROP_ssa,			/* properties_required */
637*e4b17023SJohn Marino   0,					/* properties_provided */
638*e4b17023SJohn Marino   0,					/* properties_destroyed */
639*e4b17023SJohn Marino   0,					/* todo_flags_start */
640*e4b17023SJohn Marino   TODO_update_ssa | TODO_ggc_collect	/* todo_flags_finish */
641*e4b17023SJohn Marino  }
642*e4b17023SJohn Marino };
643*e4b17023SJohn Marino 
644*e4b17023SJohn Marino /* Loop optimizer finalization.  */
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino static unsigned int
tree_ssa_loop_done(void)647*e4b17023SJohn Marino tree_ssa_loop_done (void)
648*e4b17023SJohn Marino {
649*e4b17023SJohn Marino   free_numbers_of_iterations_estimates ();
650*e4b17023SJohn Marino   scev_finalize ();
651*e4b17023SJohn Marino   loop_optimizer_finalize ();
652*e4b17023SJohn Marino   return 0;
653*e4b17023SJohn Marino }
654*e4b17023SJohn Marino 
655*e4b17023SJohn Marino struct gimple_opt_pass pass_tree_loop_done =
656*e4b17023SJohn Marino {
657*e4b17023SJohn Marino  {
658*e4b17023SJohn Marino   GIMPLE_PASS,
659*e4b17023SJohn Marino   "loopdone",				/* name */
660*e4b17023SJohn Marino   NULL,					/* gate */
661*e4b17023SJohn Marino   tree_ssa_loop_done,			/* execute */
662*e4b17023SJohn Marino   NULL,					/* sub */
663*e4b17023SJohn Marino   NULL,					/* next */
664*e4b17023SJohn Marino   0,					/* static_pass_number */
665*e4b17023SJohn Marino   TV_TREE_LOOP_FINI,			/* tv_id */
666*e4b17023SJohn Marino   PROP_cfg,				/* properties_required */
667*e4b17023SJohn Marino   0,					/* properties_provided */
668*e4b17023SJohn Marino   0,					/* properties_destroyed */
669*e4b17023SJohn Marino   0,					/* todo_flags_start */
670*e4b17023SJohn Marino   TODO_cleanup_cfg
671*e4b17023SJohn Marino     | TODO_verify_flow			/* todo_flags_finish */
672*e4b17023SJohn Marino  }
673*e4b17023SJohn Marino };
674