]>
Commit | Line | Data |
---|---|---|
4ee9c684 | 1 | /* Loop optimizations over tree-ssa. |
711789cc | 2 | Copyright (C) 2003-2013 Free Software Foundation, Inc. |
48e1416a | 3 | |
4ee9c684 | 4 | This file is part of GCC. |
48e1416a | 5 | |
4ee9c684 | 6 | GCC is free software; you can redistribute it and/or modify it |
7 | under the terms of the GNU General Public License as published by the | |
8c4c00c1 | 8 | Free Software Foundation; either version 3, or (at your option) any |
4ee9c684 | 9 | later version. |
48e1416a | 10 | |
4ee9c684 | 11 | GCC is distributed in the hope that it will be useful, but WITHOUT |
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
48e1416a | 15 | |
4ee9c684 | 16 | You should have received a copy of the GNU General Public License |
8c4c00c1 | 17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
4ee9c684 | 19 | |
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "tm.h" | |
24 | #include "tree.h" | |
4ee9c684 | 25 | #include "tm_p.h" |
4ee9c684 | 26 | #include "basic-block.h" |
4ee9c684 | 27 | #include "tree-flow.h" |
4ee9c684 | 28 | #include "tree-pass.h" |
4ee9c684 | 29 | #include "cfgloop.h" |
30 | #include "flags.h" | |
31 | #include "tree-inline.h" | |
c91e8223 | 32 | #include "tree-scalar-evolution.h" |
0b205f4c | 33 | #include "diagnostic-core.h" |
10230637 | 34 | #include "tree-vectorizer.h" |
4ee9c684 | 35 | |
dcb9eccb | 36 | /* The loop superpass. */ |
37 | ||
38 | static bool | |
0526a3ff | 39 | gate_tree_loop (void) |
dcb9eccb | 40 | { |
41 | return flag_tree_loop_optimize != 0; | |
42 | } | |
43 | ||
cbe8bda8 | 44 | namespace { |
45 | ||
46 | const pass_data pass_data_tree_loop = | |
47 | { | |
48 | GIMPLE_PASS, /* type */ | |
49 | "loop", /* name */ | |
50 | OPTGROUP_LOOP, /* optinfo_flags */ | |
51 | true, /* has_gate */ | |
52 | false, /* has_execute */ | |
53 | TV_TREE_LOOP, /* tv_id */ | |
54 | PROP_cfg, /* properties_required */ | |
55 | 0, /* properties_provided */ | |
56 | 0, /* properties_destroyed */ | |
57 | 0, /* todo_flags_start */ | |
58 | TODO_verify_ssa, /* todo_flags_finish */ | |
dcb9eccb | 59 | }; |
60 | ||
cbe8bda8 | 61 | class pass_tree_loop : public gimple_opt_pass |
62 | { | |
63 | public: | |
64 | pass_tree_loop(gcc::context *ctxt) | |
65 | : gimple_opt_pass(pass_data_tree_loop, ctxt) | |
66 | {} | |
67 | ||
68 | /* opt_pass methods: */ | |
69 | bool gate () { return gate_tree_loop (); } | |
70 | ||
71 | }; // class pass_tree_loop | |
72 | ||
73 | } // anon namespace | |
74 | ||
75 | gimple_opt_pass * | |
76 | make_pass_tree_loop (gcc::context *ctxt) | |
77 | { | |
78 | return new pass_tree_loop (ctxt); | |
79 | } | |
80 | ||
dcb9eccb | 81 | /* Loop optimizer initialization. */ |
82 | ||
2a1990e9 | 83 | static unsigned int |
dcb9eccb | 84 | tree_ssa_loop_init (void) |
85 | { | |
75a70cf9 | 86 | loop_optimizer_init (LOOPS_NORMAL |
87 | | LOOPS_HAVE_RECORDED_EXITS); | |
88 | rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); | |
89 | ||
9df082d2 | 90 | /* We might discover new loops, e.g. when turning irreducible |
91 | regions into reducible. */ | |
92 | scev_initialize (); | |
93 | ||
41f75a99 | 94 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 95 | return 0; |
bb445479 | 96 | |
2a1990e9 | 97 | return 0; |
dcb9eccb | 98 | } |
48e1416a | 99 | |
cbe8bda8 | 100 | namespace { |
101 | ||
102 | const pass_data pass_data_tree_loop_init = | |
103 | { | |
104 | GIMPLE_PASS, /* type */ | |
105 | "loopinit", /* name */ | |
106 | OPTGROUP_LOOP, /* optinfo_flags */ | |
107 | false, /* has_gate */ | |
108 | true, /* has_execute */ | |
109 | TV_NONE, /* tv_id */ | |
110 | PROP_cfg, /* properties_required */ | |
111 | 0, /* properties_provided */ | |
112 | 0, /* properties_destroyed */ | |
113 | 0, /* todo_flags_start */ | |
114 | 0, /* todo_flags_finish */ | |
dcb9eccb | 115 | }; |
116 | ||
cbe8bda8 | 117 | class pass_tree_loop_init : public gimple_opt_pass |
118 | { | |
119 | public: | |
120 | pass_tree_loop_init(gcc::context *ctxt) | |
121 | : gimple_opt_pass(pass_data_tree_loop_init, ctxt) | |
122 | {} | |
123 | ||
124 | /* opt_pass methods: */ | |
125 | unsigned int execute () { return tree_ssa_loop_init (); } | |
126 | ||
127 | }; // class pass_tree_loop_init | |
128 | ||
129 | } // anon namespace | |
130 | ||
131 | gimple_opt_pass * | |
132 | make_pass_tree_loop_init (gcc::context *ctxt) | |
133 | { | |
134 | return new pass_tree_loop_init (ctxt); | |
135 | } | |
136 | ||
7d23383d | 137 | /* Loop invariant motion pass. */ |
138 | ||
2a1990e9 | 139 | static unsigned int |
7d23383d | 140 | tree_ssa_loop_im (void) |
141 | { | |
41f75a99 | 142 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 143 | return 0; |
7d23383d | 144 | |
9bf0a3f9 | 145 | return tree_ssa_lim (); |
7d23383d | 146 | } |
147 | ||
148 | static bool | |
149 | gate_tree_ssa_loop_im (void) | |
150 | { | |
41b5cc78 | 151 | return flag_tree_loop_im != 0; |
7d23383d | 152 | } |
153 | ||
cbe8bda8 | 154 | namespace { |
155 | ||
156 | const pass_data pass_data_lim = | |
157 | { | |
158 | GIMPLE_PASS, /* type */ | |
159 | "lim", /* name */ | |
160 | OPTGROUP_LOOP, /* optinfo_flags */ | |
161 | true, /* has_gate */ | |
162 | true, /* has_execute */ | |
163 | TV_LIM, /* tv_id */ | |
164 | PROP_cfg, /* properties_required */ | |
165 | 0, /* properties_provided */ | |
166 | 0, /* properties_destroyed */ | |
167 | 0, /* todo_flags_start */ | |
168 | 0, /* todo_flags_finish */ | |
e12d0591 | 169 | }; |
170 | ||
cbe8bda8 | 171 | class pass_lim : public gimple_opt_pass |
172 | { | |
173 | public: | |
174 | pass_lim(gcc::context *ctxt) | |
175 | : gimple_opt_pass(pass_data_lim, ctxt) | |
176 | {} | |
177 | ||
178 | /* opt_pass methods: */ | |
179 | opt_pass * clone () { return new pass_lim (ctxt_); } | |
180 | bool gate () { return gate_tree_ssa_loop_im (); } | |
181 | unsigned int execute () { return tree_ssa_loop_im (); } | |
182 | ||
183 | }; // class pass_lim | |
184 | ||
185 | } // anon namespace | |
186 | ||
187 | gimple_opt_pass * | |
188 | make_pass_lim (gcc::context *ctxt) | |
189 | { | |
190 | return new pass_lim (ctxt); | |
191 | } | |
192 | ||
e12d0591 | 193 | /* Loop unswitching pass. */ |
194 | ||
2a1990e9 | 195 | static unsigned int |
e12d0591 | 196 | tree_ssa_loop_unswitch (void) |
197 | { | |
41f75a99 | 198 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 199 | return 0; |
e12d0591 | 200 | |
7194de72 | 201 | return tree_ssa_unswitch_loops (); |
e12d0591 | 202 | } |
203 | ||
204 | static bool | |
205 | gate_tree_ssa_loop_unswitch (void) | |
206 | { | |
207 | return flag_unswitch_loops != 0; | |
208 | } | |
209 | ||
cbe8bda8 | 210 | namespace { |
211 | ||
212 | const pass_data pass_data_tree_unswitch = | |
213 | { | |
214 | GIMPLE_PASS, /* type */ | |
215 | "unswitch", /* name */ | |
216 | OPTGROUP_LOOP, /* optinfo_flags */ | |
217 | true, /* has_gate */ | |
218 | true, /* has_execute */ | |
219 | TV_TREE_LOOP_UNSWITCH, /* tv_id */ | |
220 | PROP_cfg, /* properties_required */ | |
221 | 0, /* properties_provided */ | |
222 | 0, /* properties_destroyed */ | |
223 | 0, /* todo_flags_start */ | |
224 | 0, /* todo_flags_finish */ | |
7d23383d | 225 | }; |
226 | ||
cbe8bda8 | 227 | class pass_tree_unswitch : public gimple_opt_pass |
228 | { | |
229 | public: | |
230 | pass_tree_unswitch(gcc::context *ctxt) | |
231 | : gimple_opt_pass(pass_data_tree_unswitch, ctxt) | |
232 | {} | |
233 | ||
234 | /* opt_pass methods: */ | |
235 | bool gate () { return gate_tree_ssa_loop_unswitch (); } | |
236 | unsigned int execute () { return tree_ssa_loop_unswitch (); } | |
237 | ||
238 | }; // class pass_tree_unswitch | |
239 | ||
240 | } // anon namespace | |
241 | ||
242 | gimple_opt_pass * | |
243 | make_pass_tree_unswitch (gcc::context *ctxt) | |
244 | { | |
245 | return new pass_tree_unswitch (ctxt); | |
246 | } | |
247 | ||
ad4a85ad | 248 | /* Predictive commoning. */ |
249 | ||
250 | static unsigned | |
251 | run_tree_predictive_commoning (void) | |
252 | { | |
253 | if (!current_loops) | |
254 | return 0; | |
255 | ||
e5d5c850 | 256 | return tree_predictive_commoning (); |
ad4a85ad | 257 | } |
258 | ||
259 | static bool | |
260 | gate_tree_predictive_commoning (void) | |
261 | { | |
262 | return flag_predictive_commoning != 0; | |
263 | } | |
264 | ||
cbe8bda8 | 265 | namespace { |
266 | ||
267 | const pass_data pass_data_predcom = | |
268 | { | |
269 | GIMPLE_PASS, /* type */ | |
270 | "pcom", /* name */ | |
271 | OPTGROUP_LOOP, /* optinfo_flags */ | |
272 | true, /* has_gate */ | |
273 | true, /* has_execute */ | |
274 | TV_PREDCOM, /* tv_id */ | |
275 | PROP_cfg, /* properties_required */ | |
276 | 0, /* properties_provided */ | |
277 | 0, /* properties_destroyed */ | |
278 | 0, /* todo_flags_start */ | |
279 | TODO_update_ssa_only_virtuals, /* todo_flags_finish */ | |
ad4a85ad | 280 | }; |
281 | ||
cbe8bda8 | 282 | class pass_predcom : public gimple_opt_pass |
283 | { | |
284 | public: | |
285 | pass_predcom(gcc::context *ctxt) | |
286 | : gimple_opt_pass(pass_data_predcom, ctxt) | |
287 | {} | |
288 | ||
289 | /* opt_pass methods: */ | |
290 | bool gate () { return gate_tree_predictive_commoning (); } | |
291 | unsigned int execute () { return run_tree_predictive_commoning (); } | |
292 | ||
293 | }; // class pass_predcom | |
294 | ||
295 | } // anon namespace | |
296 | ||
297 | gimple_opt_pass * | |
298 | make_pass_predcom (gcc::context *ctxt) | |
299 | { | |
300 | return new pass_predcom (ctxt); | |
301 | } | |
302 | ||
c91e8223 | 303 | /* Loop autovectorization. */ |
304 | ||
2a1990e9 | 305 | static unsigned int |
c91e8223 | 306 | tree_vectorize (void) |
307 | { | |
41f75a99 | 308 | if (number_of_loops (cfun) <= 1) |
d88fd237 | 309 | return 0; |
310 | ||
7194de72 | 311 | return vectorize_loops (); |
c91e8223 | 312 | } |
313 | ||
314 | static bool | |
315 | gate_tree_vectorize (void) | |
316 | { | |
3d483a94 | 317 | return flag_tree_vectorize || cfun->has_force_vect_loops; |
c91e8223 | 318 | } |
319 | ||
cbe8bda8 | 320 | namespace { |
321 | ||
322 | const pass_data pass_data_vectorize = | |
323 | { | |
324 | GIMPLE_PASS, /* type */ | |
325 | "vect", /* name */ | |
326 | OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */ | |
327 | true, /* has_gate */ | |
328 | true, /* has_execute */ | |
329 | TV_TREE_VECTORIZATION, /* tv_id */ | |
330 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
331 | 0, /* properties_provided */ | |
332 | 0, /* properties_destroyed */ | |
333 | 0, /* todo_flags_start */ | |
334 | 0, /* todo_flags_finish */ | |
c91e8223 | 335 | }; |
336 | ||
cbe8bda8 | 337 | class pass_vectorize : public gimple_opt_pass |
338 | { | |
339 | public: | |
340 | pass_vectorize(gcc::context *ctxt) | |
341 | : gimple_opt_pass(pass_data_vectorize, ctxt) | |
342 | {} | |
343 | ||
344 | /* opt_pass methods: */ | |
345 | bool gate () { return gate_tree_vectorize (); } | |
346 | unsigned int execute () { return tree_vectorize (); } | |
347 | ||
348 | }; // class pass_vectorize | |
349 | ||
350 | } // anon namespace | |
351 | ||
352 | gimple_opt_pass * | |
353 | make_pass_vectorize (gcc::context *ctxt) | |
354 | { | |
355 | return new pass_vectorize (ctxt); | |
356 | } | |
357 | ||
255b6be7 | 358 | /* GRAPHITE optimizations. */ |
359 | ||
360 | static unsigned int | |
361 | graphite_transforms (void) | |
362 | { | |
363 | if (!current_loops) | |
364 | return 0; | |
365 | ||
366 | graphite_transform_loops (); | |
367 | ||
368 | return 0; | |
369 | } | |
370 | ||
371 | static bool | |
372 | gate_graphite_transforms (void) | |
373 | { | |
48e1416a | 374 | /* Enable -fgraphite pass if any one of the graphite optimization flags |
255b6be7 | 375 | is turned on. */ |
d60a90cc | 376 | if (flag_loop_block |
377 | || flag_loop_interchange | |
378 | || flag_loop_strip_mine | |
379 | || flag_graphite_identity | |
89049f25 | 380 | || flag_loop_parallelize_all |
381 | || flag_loop_optimize_isl) | |
255b6be7 | 382 | flag_graphite = 1; |
383 | ||
384 | return flag_graphite != 0; | |
385 | } | |
386 | ||
cbe8bda8 | 387 | namespace { |
388 | ||
389 | const pass_data pass_data_graphite = | |
390 | { | |
391 | GIMPLE_PASS, /* type */ | |
392 | "graphite0", /* name */ | |
393 | OPTGROUP_LOOP, /* optinfo_flags */ | |
394 | true, /* has_gate */ | |
395 | false, /* has_execute */ | |
396 | TV_GRAPHITE, /* tv_id */ | |
397 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
398 | 0, /* properties_provided */ | |
399 | 0, /* properties_destroyed */ | |
400 | 0, /* todo_flags_start */ | |
401 | 0, /* todo_flags_finish */ | |
b90bb125 | 402 | }; |
403 | ||
cbe8bda8 | 404 | class pass_graphite : public gimple_opt_pass |
405 | { | |
406 | public: | |
407 | pass_graphite(gcc::context *ctxt) | |
408 | : gimple_opt_pass(pass_data_graphite, ctxt) | |
409 | {} | |
410 | ||
411 | /* opt_pass methods: */ | |
412 | bool gate () { return gate_graphite_transforms (); } | |
413 | ||
414 | }; // class pass_graphite | |
415 | ||
416 | } // anon namespace | |
417 | ||
418 | gimple_opt_pass * | |
419 | make_pass_graphite (gcc::context *ctxt) | |
420 | { | |
421 | return new pass_graphite (ctxt); | |
422 | } | |
423 | ||
424 | namespace { | |
425 | ||
426 | const pass_data pass_data_graphite_transforms = | |
427 | { | |
428 | GIMPLE_PASS, /* type */ | |
429 | "graphite", /* name */ | |
430 | OPTGROUP_LOOP, /* optinfo_flags */ | |
431 | true, /* has_gate */ | |
432 | true, /* has_execute */ | |
433 | TV_GRAPHITE_TRANSFORMS, /* tv_id */ | |
434 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
435 | 0, /* properties_provided */ | |
436 | 0, /* properties_destroyed */ | |
437 | 0, /* todo_flags_start */ | |
438 | 0, /* todo_flags_finish */ | |
255b6be7 | 439 | }; |
440 | ||
cbe8bda8 | 441 | class pass_graphite_transforms : public gimple_opt_pass |
442 | { | |
443 | public: | |
444 | pass_graphite_transforms(gcc::context *ctxt) | |
445 | : gimple_opt_pass(pass_data_graphite_transforms, ctxt) | |
446 | {} | |
447 | ||
448 | /* opt_pass methods: */ | |
449 | bool gate () { return gate_graphite_transforms (); } | |
450 | unsigned int execute () { return graphite_transforms (); } | |
451 | ||
452 | }; // class pass_graphite_transforms | |
453 | ||
454 | } // anon namespace | |
455 | ||
456 | gimple_opt_pass * | |
457 | make_pass_graphite_transforms (gcc::context *ctxt) | |
458 | { | |
459 | return new pass_graphite_transforms (ctxt); | |
460 | } | |
461 | ||
355572cc | 462 | /* Check the correctness of the data dependence analyzers. */ |
463 | ||
464 | static unsigned int | |
465 | check_data_deps (void) | |
466 | { | |
41f75a99 | 467 | if (number_of_loops (cfun) <= 1) |
355572cc | 468 | return 0; |
469 | ||
470 | tree_check_data_deps (); | |
471 | return 0; | |
472 | } | |
473 | ||
474 | static bool | |
475 | gate_check_data_deps (void) | |
476 | { | |
477 | return flag_check_data_deps != 0; | |
478 | } | |
479 | ||
cbe8bda8 | 480 | namespace { |
481 | ||
482 | const pass_data pass_data_check_data_deps = | |
483 | { | |
484 | GIMPLE_PASS, /* type */ | |
485 | "ckdd", /* name */ | |
486 | OPTGROUP_LOOP, /* optinfo_flags */ | |
487 | true, /* has_gate */ | |
488 | true, /* has_execute */ | |
489 | TV_CHECK_DATA_DEPS, /* tv_id */ | |
490 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
491 | 0, /* properties_provided */ | |
492 | 0, /* properties_destroyed */ | |
493 | 0, /* todo_flags_start */ | |
494 | 0, /* todo_flags_finish */ | |
355572cc | 495 | }; |
496 | ||
cbe8bda8 | 497 | class pass_check_data_deps : public gimple_opt_pass |
498 | { | |
499 | public: | |
500 | pass_check_data_deps(gcc::context *ctxt) | |
501 | : gimple_opt_pass(pass_data_check_data_deps, ctxt) | |
502 | {} | |
503 | ||
504 | /* opt_pass methods: */ | |
505 | bool gate () { return gate_check_data_deps (); } | |
506 | unsigned int execute () { return check_data_deps (); } | |
507 | ||
508 | }; // class pass_check_data_deps | |
509 | ||
510 | } // anon namespace | |
511 | ||
512 | gimple_opt_pass * | |
513 | make_pass_check_data_deps (gcc::context *ctxt) | |
514 | { | |
515 | return new pass_check_data_deps (ctxt); | |
516 | } | |
517 | ||
bb445479 | 518 | /* Canonical induction variable creation pass. */ |
519 | ||
2a1990e9 | 520 | static unsigned int |
bb445479 | 521 | tree_ssa_loop_ivcanon (void) |
522 | { | |
41f75a99 | 523 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 524 | return 0; |
bb445479 | 525 | |
7194de72 | 526 | return canonicalize_induction_variables (); |
bb445479 | 527 | } |
528 | ||
529 | static bool | |
530 | gate_tree_ssa_loop_ivcanon (void) | |
531 | { | |
41b5cc78 | 532 | return flag_tree_loop_ivcanon != 0; |
bb445479 | 533 | } |
534 | ||
cbe8bda8 | 535 | namespace { |
536 | ||
537 | const pass_data pass_data_iv_canon = | |
538 | { | |
539 | GIMPLE_PASS, /* type */ | |
540 | "ivcanon", /* name */ | |
541 | OPTGROUP_LOOP, /* optinfo_flags */ | |
542 | true, /* has_gate */ | |
543 | true, /* has_execute */ | |
544 | TV_TREE_LOOP_IVCANON, /* tv_id */ | |
545 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
546 | 0, /* properties_provided */ | |
547 | 0, /* properties_destroyed */ | |
548 | 0, /* todo_flags_start */ | |
549 | 0, /* todo_flags_finish */ | |
10fec820 | 550 | }; |
551 | ||
cbe8bda8 | 552 | class pass_iv_canon : public gimple_opt_pass |
553 | { | |
554 | public: | |
555 | pass_iv_canon(gcc::context *ctxt) | |
556 | : gimple_opt_pass(pass_data_iv_canon, ctxt) | |
557 | {} | |
558 | ||
559 | /* opt_pass methods: */ | |
560 | bool gate () { return gate_tree_ssa_loop_ivcanon (); } | |
561 | unsigned int execute () { return tree_ssa_loop_ivcanon (); } | |
562 | ||
563 | }; // class pass_iv_canon | |
564 | ||
565 | } // anon namespace | |
566 | ||
567 | gimple_opt_pass * | |
568 | make_pass_iv_canon (gcc::context *ctxt) | |
569 | { | |
570 | return new pass_iv_canon (ctxt); | |
571 | } | |
572 | ||
10fec820 | 573 | /* Propagation of constants using scev. */ |
574 | ||
575 | static bool | |
576 | gate_scev_const_prop (void) | |
577 | { | |
2a6e95ba | 578 | return flag_tree_scev_cprop; |
10fec820 | 579 | } |
580 | ||
cbe8bda8 | 581 | namespace { |
582 | ||
583 | const pass_data pass_data_scev_cprop = | |
584 | { | |
585 | GIMPLE_PASS, /* type */ | |
586 | "sccp", /* name */ | |
587 | OPTGROUP_LOOP, /* optinfo_flags */ | |
588 | true, /* has_gate */ | |
589 | true, /* has_execute */ | |
590 | TV_SCEV_CONST, /* tv_id */ | |
591 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
592 | 0, /* properties_provided */ | |
593 | 0, /* properties_destroyed */ | |
594 | 0, /* todo_flags_start */ | |
595 | ( TODO_cleanup_cfg | |
596 | | TODO_update_ssa_only_virtuals ), /* todo_flags_finish */ | |
8feba661 | 597 | }; |
598 | ||
cbe8bda8 | 599 | class pass_scev_cprop : public gimple_opt_pass |
600 | { | |
601 | public: | |
602 | pass_scev_cprop(gcc::context *ctxt) | |
603 | : gimple_opt_pass(pass_data_scev_cprop, ctxt) | |
604 | {} | |
605 | ||
606 | /* opt_pass methods: */ | |
607 | bool gate () { return gate_scev_const_prop (); } | |
608 | unsigned int execute () { return scev_const_prop (); } | |
609 | ||
610 | }; // class pass_scev_cprop | |
611 | ||
612 | } // anon namespace | |
613 | ||
614 | gimple_opt_pass * | |
615 | make_pass_scev_cprop (gcc::context *ctxt) | |
616 | { | |
617 | return new pass_scev_cprop (ctxt); | |
618 | } | |
619 | ||
41fc6ce4 | 620 | /* Record bounds on numbers of iterations of loops. */ |
621 | ||
2a1990e9 | 622 | static unsigned int |
41fc6ce4 | 623 | tree_ssa_loop_bounds (void) |
624 | { | |
41f75a99 | 625 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 626 | return 0; |
41fc6ce4 | 627 | |
7f521ab4 | 628 | estimate_numbers_of_iterations (); |
41fc6ce4 | 629 | scev_reset (); |
2a1990e9 | 630 | return 0; |
41fc6ce4 | 631 | } |
632 | ||
cbe8bda8 | 633 | namespace { |
634 | ||
635 | const pass_data pass_data_record_bounds = | |
636 | { | |
637 | GIMPLE_PASS, /* type */ | |
638 | "*record_bounds", /* name */ | |
639 | OPTGROUP_NONE, /* optinfo_flags */ | |
640 | false, /* has_gate */ | |
641 | true, /* has_execute */ | |
642 | TV_TREE_LOOP_BOUNDS, /* tv_id */ | |
643 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
644 | 0, /* properties_provided */ | |
645 | 0, /* properties_destroyed */ | |
646 | 0, /* todo_flags_start */ | |
647 | 0, /* todo_flags_finish */ | |
41fc6ce4 | 648 | }; |
649 | ||
cbe8bda8 | 650 | class pass_record_bounds : public gimple_opt_pass |
651 | { | |
652 | public: | |
653 | pass_record_bounds(gcc::context *ctxt) | |
654 | : gimple_opt_pass(pass_data_record_bounds, ctxt) | |
655 | {} | |
656 | ||
657 | /* opt_pass methods: */ | |
658 | unsigned int execute () { return tree_ssa_loop_bounds (); } | |
659 | ||
660 | }; // class pass_record_bounds | |
661 | ||
662 | } // anon namespace | |
663 | ||
664 | gimple_opt_pass * | |
665 | make_pass_record_bounds (gcc::context *ctxt) | |
666 | { | |
667 | return new pass_record_bounds (ctxt); | |
668 | } | |
669 | ||
bb445479 | 670 | /* Complete unrolling of loops. */ |
671 | ||
2a1990e9 | 672 | static unsigned int |
bb445479 | 673 | tree_complete_unroll (void) |
674 | { | |
41f75a99 | 675 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 676 | return 0; |
bb445479 | 677 | |
7194de72 | 678 | return tree_unroll_loops_completely (flag_unroll_loops |
679 | || flag_peel_loops | |
d88fd237 | 680 | || optimize >= 3, true); |
bb445479 | 681 | } |
682 | ||
683 | static bool | |
684 | gate_tree_complete_unroll (void) | |
685 | { | |
604f7b8a | 686 | return true; |
bb445479 | 687 | } |
688 | ||
cbe8bda8 | 689 | namespace { |
690 | ||
691 | const pass_data pass_data_complete_unroll = | |
692 | { | |
693 | GIMPLE_PASS, /* type */ | |
694 | "cunroll", /* name */ | |
695 | OPTGROUP_LOOP, /* optinfo_flags */ | |
696 | true, /* has_gate */ | |
697 | true, /* has_execute */ | |
698 | TV_COMPLETE_UNROLL, /* tv_id */ | |
699 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
700 | 0, /* properties_provided */ | |
701 | 0, /* properties_destroyed */ | |
702 | 0, /* todo_flags_start */ | |
703 | 0, /* todo_flags_finish */ | |
dec41e98 | 704 | }; |
705 | ||
cbe8bda8 | 706 | class pass_complete_unroll : public gimple_opt_pass |
707 | { | |
708 | public: | |
709 | pass_complete_unroll(gcc::context *ctxt) | |
710 | : gimple_opt_pass(pass_data_complete_unroll, ctxt) | |
711 | {} | |
712 | ||
713 | /* opt_pass methods: */ | |
714 | bool gate () { return gate_tree_complete_unroll (); } | |
715 | unsigned int execute () { return tree_complete_unroll (); } | |
716 | ||
717 | }; // class pass_complete_unroll | |
718 | ||
719 | } // anon namespace | |
720 | ||
721 | gimple_opt_pass * | |
722 | make_pass_complete_unroll (gcc::context *ctxt) | |
723 | { | |
724 | return new pass_complete_unroll (ctxt); | |
725 | } | |
726 | ||
d88fd237 | 727 | /* Complete unrolling of inner loops. */ |
728 | ||
729 | static unsigned int | |
730 | tree_complete_unroll_inner (void) | |
731 | { | |
732 | unsigned ret = 0; | |
733 | ||
734 | loop_optimizer_init (LOOPS_NORMAL | |
735 | | LOOPS_HAVE_RECORDED_EXITS); | |
41f75a99 | 736 | if (number_of_loops (cfun) > 1) |
d88fd237 | 737 | { |
738 | scev_initialize (); | |
739 | ret = tree_unroll_loops_completely (optimize >= 3, false); | |
740 | free_numbers_of_iterations_estimates (); | |
741 | scev_finalize (); | |
742 | } | |
743 | loop_optimizer_finalize (); | |
744 | ||
745 | return ret; | |
746 | } | |
747 | ||
748 | static bool | |
749 | gate_tree_complete_unroll_inner (void) | |
750 | { | |
751 | return optimize >= 2; | |
752 | } | |
753 | ||
cbe8bda8 | 754 | namespace { |
755 | ||
756 | const pass_data pass_data_complete_unrolli = | |
757 | { | |
758 | GIMPLE_PASS, /* type */ | |
759 | "cunrolli", /* name */ | |
760 | OPTGROUP_LOOP, /* optinfo_flags */ | |
761 | true, /* has_gate */ | |
762 | true, /* has_execute */ | |
763 | TV_COMPLETE_UNROLL, /* tv_id */ | |
764 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
765 | 0, /* properties_provided */ | |
766 | 0, /* properties_destroyed */ | |
767 | 0, /* todo_flags_start */ | |
768 | TODO_verify_flow, /* todo_flags_finish */ | |
d88fd237 | 769 | }; |
770 | ||
cbe8bda8 | 771 | class pass_complete_unrolli : public gimple_opt_pass |
772 | { | |
773 | public: | |
774 | pass_complete_unrolli(gcc::context *ctxt) | |
775 | : gimple_opt_pass(pass_data_complete_unrolli, ctxt) | |
776 | {} | |
777 | ||
778 | /* opt_pass methods: */ | |
779 | bool gate () { return gate_tree_complete_unroll_inner (); } | |
780 | unsigned int execute () { return tree_complete_unroll_inner (); } | |
781 | ||
782 | }; // class pass_complete_unrolli | |
783 | ||
784 | } // anon namespace | |
785 | ||
786 | gimple_opt_pass * | |
787 | make_pass_complete_unrolli (gcc::context *ctxt) | |
788 | { | |
789 | return new pass_complete_unrolli (ctxt); | |
790 | } | |
791 | ||
28c92cbb | 792 | /* Parallelization. */ |
793 | ||
794 | static bool | |
795 | gate_tree_parallelize_loops (void) | |
796 | { | |
326f0dc4 | 797 | return flag_tree_parallelize_loops > 1; |
28c92cbb | 798 | } |
799 | ||
800 | static unsigned | |
801 | tree_parallelize_loops (void) | |
802 | { | |
41f75a99 | 803 | if (number_of_loops (cfun) <= 1) |
28c92cbb | 804 | return 0; |
805 | ||
806 | if (parallelize_loops ()) | |
807 | return TODO_cleanup_cfg | TODO_rebuild_alias; | |
808 | return 0; | |
809 | } | |
810 | ||
cbe8bda8 | 811 | namespace { |
812 | ||
813 | const pass_data pass_data_parallelize_loops = | |
814 | { | |
815 | GIMPLE_PASS, /* type */ | |
816 | "parloops", /* name */ | |
817 | OPTGROUP_LOOP, /* optinfo_flags */ | |
818 | true, /* has_gate */ | |
819 | true, /* has_execute */ | |
820 | TV_TREE_PARALLELIZE_LOOPS, /* tv_id */ | |
821 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
822 | 0, /* properties_provided */ | |
823 | 0, /* properties_destroyed */ | |
824 | 0, /* todo_flags_start */ | |
825 | TODO_verify_flow, /* todo_flags_finish */ | |
28c92cbb | 826 | }; |
827 | ||
cbe8bda8 | 828 | class pass_parallelize_loops : public gimple_opt_pass |
829 | { | |
830 | public: | |
831 | pass_parallelize_loops(gcc::context *ctxt) | |
832 | : gimple_opt_pass(pass_data_parallelize_loops, ctxt) | |
833 | {} | |
834 | ||
835 | /* opt_pass methods: */ | |
836 | bool gate () { return gate_tree_parallelize_loops (); } | |
837 | unsigned int execute () { return tree_parallelize_loops (); } | |
838 | ||
839 | }; // class pass_parallelize_loops | |
840 | ||
841 | } // anon namespace | |
842 | ||
843 | gimple_opt_pass * | |
844 | make_pass_parallelize_loops (gcc::context *ctxt) | |
845 | { | |
846 | return new pass_parallelize_loops (ctxt); | |
847 | } | |
848 | ||
b30560de | 849 | /* Prefetching. */ |
850 | ||
2a1990e9 | 851 | static unsigned int |
b30560de | 852 | tree_ssa_loop_prefetch (void) |
853 | { | |
41f75a99 | 854 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 855 | return 0; |
b30560de | 856 | |
7194de72 | 857 | return tree_ssa_prefetch_arrays (); |
b30560de | 858 | } |
859 | ||
860 | static bool | |
861 | gate_tree_ssa_loop_prefetch (void) | |
862 | { | |
cd459e62 | 863 | return flag_prefetch_loop_arrays > 0; |
b30560de | 864 | } |
865 | ||
cbe8bda8 | 866 | namespace { |
867 | ||
868 | const pass_data pass_data_loop_prefetch = | |
869 | { | |
870 | GIMPLE_PASS, /* type */ | |
871 | "aprefetch", /* name */ | |
872 | OPTGROUP_LOOP, /* optinfo_flags */ | |
873 | true, /* has_gate */ | |
874 | true, /* has_execute */ | |
875 | TV_TREE_PREFETCH, /* tv_id */ | |
876 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
877 | 0, /* properties_provided */ | |
878 | 0, /* properties_destroyed */ | |
879 | 0, /* todo_flags_start */ | |
880 | 0, /* todo_flags_finish */ | |
b30560de | 881 | }; |
882 | ||
cbe8bda8 | 883 | class pass_loop_prefetch : public gimple_opt_pass |
884 | { | |
885 | public: | |
886 | pass_loop_prefetch(gcc::context *ctxt) | |
887 | : gimple_opt_pass(pass_data_loop_prefetch, ctxt) | |
888 | {} | |
889 | ||
890 | /* opt_pass methods: */ | |
891 | bool gate () { return gate_tree_ssa_loop_prefetch (); } | |
892 | unsigned int execute () { return tree_ssa_loop_prefetch (); } | |
893 | ||
894 | }; // class pass_loop_prefetch | |
895 | ||
896 | } // anon namespace | |
897 | ||
898 | gimple_opt_pass * | |
899 | make_pass_loop_prefetch (gcc::context *ctxt) | |
900 | { | |
901 | return new pass_loop_prefetch (ctxt); | |
902 | } | |
903 | ||
dec41e98 | 904 | /* Induction variable optimizations. */ |
905 | ||
2a1990e9 | 906 | static unsigned int |
dec41e98 | 907 | tree_ssa_loop_ivopts (void) |
908 | { | |
41f75a99 | 909 | if (number_of_loops (cfun) <= 1) |
2a1990e9 | 910 | return 0; |
dec41e98 | 911 | |
7194de72 | 912 | tree_ssa_iv_optimize (); |
2a1990e9 | 913 | return 0; |
dec41e98 | 914 | } |
915 | ||
916 | static bool | |
917 | gate_tree_ssa_loop_ivopts (void) | |
918 | { | |
919 | return flag_ivopts != 0; | |
920 | } | |
921 | ||
cbe8bda8 | 922 | namespace { |
923 | ||
924 | const pass_data pass_data_iv_optimize = | |
925 | { | |
926 | GIMPLE_PASS, /* type */ | |
927 | "ivopts", /* name */ | |
928 | OPTGROUP_LOOP, /* optinfo_flags */ | |
929 | true, /* has_gate */ | |
930 | true, /* has_execute */ | |
931 | TV_TREE_LOOP_IVOPTS, /* tv_id */ | |
932 | ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
933 | 0, /* properties_provided */ | |
934 | 0, /* properties_destroyed */ | |
935 | 0, /* todo_flags_start */ | |
936 | TODO_update_ssa, /* todo_flags_finish */ | |
bb445479 | 937 | }; |
938 | ||
cbe8bda8 | 939 | class pass_iv_optimize : public gimple_opt_pass |
940 | { | |
941 | public: | |
942 | pass_iv_optimize(gcc::context *ctxt) | |
943 | : gimple_opt_pass(pass_data_iv_optimize, ctxt) | |
944 | {} | |
945 | ||
946 | /* opt_pass methods: */ | |
947 | bool gate () { return gate_tree_ssa_loop_ivopts (); } | |
948 | unsigned int execute () { return tree_ssa_loop_ivopts (); } | |
949 | ||
950 | }; // class pass_iv_optimize | |
951 | ||
952 | } // anon namespace | |
953 | ||
954 | gimple_opt_pass * | |
955 | make_pass_iv_optimize (gcc::context *ctxt) | |
956 | { | |
957 | return new pass_iv_optimize (ctxt); | |
958 | } | |
959 | ||
dcb9eccb | 960 | /* Loop optimizer finalization. */ |
961 | ||
2a1990e9 | 962 | static unsigned int |
dcb9eccb | 963 | tree_ssa_loop_done (void) |
964 | { | |
7194de72 | 965 | free_numbers_of_iterations_estimates (); |
bb445479 | 966 | scev_finalize (); |
88e6f696 | 967 | loop_optimizer_finalize (); |
2a1990e9 | 968 | return 0; |
dcb9eccb | 969 | } |
48e1416a | 970 | |
cbe8bda8 | 971 | namespace { |
972 | ||
973 | const pass_data pass_data_tree_loop_done = | |
974 | { | |
975 | GIMPLE_PASS, /* type */ | |
976 | "loopdone", /* name */ | |
977 | OPTGROUP_LOOP, /* optinfo_flags */ | |
978 | false, /* has_gate */ | |
979 | true, /* has_execute */ | |
980 | TV_NONE, /* tv_id */ | |
981 | PROP_cfg, /* properties_required */ | |
982 | 0, /* properties_provided */ | |
983 | 0, /* properties_destroyed */ | |
984 | 0, /* todo_flags_start */ | |
985 | ( TODO_cleanup_cfg | TODO_verify_flow ), /* todo_flags_finish */ | |
dcb9eccb | 986 | }; |
cbe8bda8 | 987 | |
988 | class pass_tree_loop_done : public gimple_opt_pass | |
989 | { | |
990 | public: | |
991 | pass_tree_loop_done(gcc::context *ctxt) | |
992 | : gimple_opt_pass(pass_data_tree_loop_done, ctxt) | |
993 | {} | |
994 | ||
995 | /* opt_pass methods: */ | |
996 | unsigned int execute () { return tree_ssa_loop_done (); } | |
997 | ||
998 | }; // class pass_tree_loop_done | |
999 | ||
1000 | } // anon namespace | |
1001 | ||
1002 | gimple_opt_pass * | |
1003 | make_pass_tree_loop_done (gcc::context *ctxt) | |
1004 | { | |
1005 | return new pass_tree_loop_done (ctxt); | |
1006 | } |