Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-ssa-loop-ch.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* Loop header copying on trees. |
145 | 2 Copyright (C) 2004-2020 Free Software Foundation, Inc. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3 |
0 | 4 This file is part of GCC. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
5 |
0 | 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 | |
8 Free Software Foundation; either version 3, or (at your option) any | |
9 later version. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
10 |
0 | 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. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
15 |
0 | 16 You should have received a copy of the GNU General Public License |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
111 | 23 #include "backend.h" |
0 | 24 #include "tree.h" |
111 | 25 #include "gimple.h" |
26 #include "cfghooks.h" | |
0 | 27 #include "tree-pass.h" |
111 | 28 #include "gimple-ssa.h" |
29 #include "gimple-iterator.h" | |
30 #include "tree-cfg.h" | |
31 #include "tree-into-ssa.h" | |
0 | 32 #include "cfgloop.h" |
33 #include "tree-inline.h" | |
111 | 34 #include "tree-ssa-scopedtables.h" |
35 #include "tree-ssa-threadedge.h" | |
145 | 36 #include "tree-ssa-sccvn.h" |
37 #include "tree-phinodes.h" | |
38 #include "ssa-iterators.h" | |
0 | 39 |
40 /* Duplicates headers of loops if they are small enough, so that the statements | |
41 in the loop body are always executed when the loop is entered. This | |
42 increases effectiveness of code motion optimizations, and reduces the need | |
43 for loop preconditioning. */ | |
44 | |
45 /* Check whether we should duplicate HEADER of LOOP. At most *LIMIT | |
46 instructions should be duplicated, limit is decreased by the actual | |
47 amount. */ | |
48 | |
49 static bool | |
145 | 50 should_duplicate_loop_header_p (basic_block header, class loop *loop, |
0 | 51 int *limit) |
52 { | |
53 gimple_stmt_iterator bsi; | |
54 | |
111 | 55 gcc_assert (!header->aux); |
0 | 56 |
57 /* Loop header copying usually increases size of the code. This used not to | |
58 be true, since quite often it is possible to verify that the condition is | |
59 satisfied in the first iteration and therefore to eliminate it. Jump | |
60 threading handles these cases now. */ | |
131 | 61 if (optimize_loop_for_size_p (loop) |
62 && !loop->force_vectorize) | |
111 | 63 { |
64 if (dump_file && (dump_flags & TDF_DETAILS)) | |
65 fprintf (dump_file, | |
66 " Not duplicating bb %i: optimizing for size.\n", | |
67 header->index); | |
68 return false; | |
69 } | |
0 | 70 |
71 gcc_assert (EDGE_COUNT (header->succs) > 0); | |
72 if (single_succ_p (header)) | |
111 | 73 { |
74 if (dump_file && (dump_flags & TDF_DETAILS)) | |
75 fprintf (dump_file, | |
76 " Not duplicating bb %i: it is single succ.\n", | |
77 header->index); | |
78 return false; | |
79 } | |
80 | |
0 | 81 if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest) |
82 && flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest)) | |
111 | 83 { |
84 if (dump_file && (dump_flags & TDF_DETAILS)) | |
85 fprintf (dump_file, | |
86 " Not duplicating bb %i: both sucessors are in loop.\n", | |
87 loop->num); | |
88 return false; | |
89 } | |
0 | 90 |
91 /* If this is not the original loop header, we want it to have just | |
92 one predecessor in order to match the && pattern. */ | |
93 if (header != loop->header && !single_pred_p (header)) | |
111 | 94 { |
95 if (dump_file && (dump_flags & TDF_DETAILS)) | |
96 fprintf (dump_file, | |
97 " Not duplicating bb %i: it has mutiple predecestors.\n", | |
98 header->index); | |
99 return false; | |
100 } | |
0 | 101 |
145 | 102 gcond *last = safe_dyn_cast <gcond *> (last_stmt (header)); |
103 if (!last) | |
111 | 104 { |
105 if (dump_file && (dump_flags & TDF_DETAILS)) | |
106 fprintf (dump_file, | |
107 " Not duplicating bb %i: it does not end by conditional.\n", | |
108 header->index); | |
109 return false; | |
110 } | |
0 | 111 |
145 | 112 for (gphi_iterator psi = gsi_start_phis (header); !gsi_end_p (psi); |
113 gsi_next (&psi)) | |
114 { | |
115 gphi *phi = psi.phi (); | |
116 tree res = gimple_phi_result (phi); | |
117 if (INTEGRAL_TYPE_P (TREE_TYPE (res)) | |
118 || POINTER_TYPE_P (TREE_TYPE (res))) | |
119 gimple_set_uid (phi, 1 /* IV */); | |
120 else | |
121 gimple_set_uid (phi, 0); | |
122 } | |
123 | |
124 /* Count number of instructions and punt on calls. | |
125 Populate stmts INV/IV flag to later apply heuristics to the | |
126 kind of conditions we want to copy. */ | |
0 | 127 for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi)) |
128 { | |
145 | 129 gimple *last = gsi_stmt (bsi); |
0 | 130 |
131 if (gimple_code (last) == GIMPLE_LABEL) | |
132 continue; | |
133 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
134 if (is_gimple_debug (last)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
135 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
136 |
111 | 137 if (gimple_code (last) == GIMPLE_CALL |
138 && (!gimple_inexpensive_call_p (as_a <gcall *> (last)) | |
139 /* IFN_LOOP_DIST_ALIAS means that inner loop is distributed | |
140 at current loop's header. Don't copy in this case. */ | |
141 || gimple_call_internal_p (last, IFN_LOOP_DIST_ALIAS))) | |
142 { | |
143 if (dump_file && (dump_flags & TDF_DETAILS)) | |
144 fprintf (dump_file, | |
145 " Not duplicating bb %i: it contains call.\n", | |
146 header->index); | |
147 return false; | |
148 } | |
0 | 149 |
150 *limit -= estimate_num_insns (last, &eni_size_weights); | |
151 if (*limit < 0) | |
111 | 152 { |
153 if (dump_file && (dump_flags & TDF_DETAILS)) | |
154 fprintf (dump_file, | |
155 " Not duplicating bb %i contains too many insns.\n", | |
156 header->index); | |
157 return false; | |
158 } | |
145 | 159 |
160 /* Classify the stmt based on whether its computation is based | |
161 on a IV or whether it is invariant in the loop. */ | |
162 gimple_set_uid (last, 0); | |
163 if (!gimple_vuse (last)) | |
164 { | |
165 bool inv = true; | |
166 bool iv = false; | |
167 ssa_op_iter i; | |
168 tree op; | |
169 FOR_EACH_SSA_TREE_OPERAND (op, last, i, SSA_OP_USE) | |
170 if (!SSA_NAME_IS_DEFAULT_DEF (op) | |
171 && flow_bb_inside_loop_p (loop, | |
172 gimple_bb (SSA_NAME_DEF_STMT (op)))) | |
173 { | |
174 if (!(gimple_uid (SSA_NAME_DEF_STMT (op)) & 2 /* INV */)) | |
175 inv = false; | |
176 if (gimple_uid (SSA_NAME_DEF_STMT (op)) & 1 /* IV */) | |
177 iv = true; | |
178 } | |
179 gimple_set_uid (last, (iv ? 1 : 0) | (inv ? 2 : 0)); | |
180 } | |
0 | 181 } |
145 | 182 |
183 /* If the condition tests a non-IV loop variant we do not want to rotate | |
184 the loop further. Unless this is the original loop header. */ | |
185 tree lhs = gimple_cond_lhs (last); | |
186 tree rhs = gimple_cond_rhs (last); | |
187 if (header != loop->header | |
188 && ((TREE_CODE (lhs) == SSA_NAME | |
189 && !SSA_NAME_IS_DEFAULT_DEF (lhs) | |
190 && flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (lhs))) | |
191 && gimple_uid (SSA_NAME_DEF_STMT (lhs)) == 0) | |
192 || (TREE_CODE (rhs) == SSA_NAME | |
193 && !SSA_NAME_IS_DEFAULT_DEF (rhs) | |
194 && flow_bb_inside_loop_p (loop, | |
195 gimple_bb (SSA_NAME_DEF_STMT (rhs))) | |
196 && gimple_uid (SSA_NAME_DEF_STMT (rhs)) == 0))) | |
197 { | |
198 if (dump_file && (dump_flags & TDF_DETAILS)) | |
199 fprintf (dump_file, | |
200 " Not duplicating bb %i: condition based on non-IV loop" | |
201 " variant.\n", header->index); | |
202 return false; | |
203 } | |
204 | |
111 | 205 if (dump_file && (dump_flags & TDF_DETAILS)) |
206 fprintf (dump_file, " Will duplicate bb %i\n", header->index); | |
0 | 207 return true; |
208 } | |
209 | |
210 /* Checks whether LOOP is a do-while style loop. */ | |
211 | |
212 static bool | |
145 | 213 do_while_loop_p (class loop *loop) |
0 | 214 { |
111 | 215 gimple *stmt = last_stmt (loop->latch); |
0 | 216 |
217 /* If the latch of the loop is not empty, it is not a do-while loop. */ | |
218 if (stmt | |
219 && gimple_code (stmt) != GIMPLE_LABEL) | |
111 | 220 { |
221 if (dump_file && (dump_flags & TDF_DETAILS)) | |
222 fprintf (dump_file, | |
223 "Loop %i is not do-while loop: latch is not empty.\n", | |
224 loop->num); | |
225 return false; | |
226 } | |
0 | 227 |
131 | 228 /* If the latch does not have a single predecessor, it is not a |
229 do-while loop. */ | |
230 if (!single_pred_p (loop->latch)) | |
111 | 231 { |
232 if (dump_file && (dump_flags & TDF_DETAILS)) | |
233 fprintf (dump_file, | |
131 | 234 "Loop %i is not do-while loop: latch has multiple " |
235 "predecessors.\n", loop->num); | |
111 | 236 return false; |
237 } | |
131 | 238 |
239 /* If the latch predecessor doesn't exit the loop, it is not a | |
240 do-while loop. */ | |
241 if (!loop_exits_from_bb_p (loop, single_pred (loop->latch))) | |
242 { | |
243 if (dump_file && (dump_flags & TDF_DETAILS)) | |
244 fprintf (dump_file, | |
245 "Loop %i is not do-while loop: latch predecessor " | |
246 "does not exit loop.\n", loop->num); | |
247 return false; | |
248 } | |
249 | |
111 | 250 if (dump_file && (dump_flags & TDF_DETAILS)) |
251 fprintf (dump_file, "Loop %i is do-while loop\n", loop->num); | |
0 | 252 |
253 return true; | |
254 } | |
255 | |
111 | 256 namespace { |
257 | |
258 /* Common superclass for both header-copying phases. */ | |
259 class ch_base : public gimple_opt_pass | |
260 { | |
261 protected: | |
262 ch_base (pass_data data, gcc::context *ctxt) | |
263 : gimple_opt_pass (data, ctxt) | |
264 {} | |
265 | |
266 /* Copies headers of all loops in FUN for which process_loop_p is true. */ | |
267 unsigned int copy_headers (function *fun); | |
268 | |
269 /* Return true to copy headers of LOOP or false to skip. */ | |
145 | 270 virtual bool process_loop_p (class loop *loop) = 0; |
111 | 271 }; |
272 | |
273 const pass_data pass_data_ch = | |
274 { | |
275 GIMPLE_PASS, /* type */ | |
276 "ch", /* name */ | |
277 OPTGROUP_LOOP, /* optinfo_flags */ | |
278 TV_TREE_CH, /* tv_id */ | |
279 ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
280 0, /* properties_provided */ | |
281 0, /* properties_destroyed */ | |
282 0, /* todo_flags_start */ | |
283 0, /* todo_flags_finish */ | |
284 }; | |
285 | |
286 class pass_ch : public ch_base | |
287 { | |
288 public: | |
289 pass_ch (gcc::context *ctxt) | |
290 : ch_base (pass_data_ch, ctxt) | |
291 {} | |
292 | |
293 /* opt_pass methods: */ | |
294 virtual bool gate (function *) { return flag_tree_ch != 0; } | |
295 | |
296 /* Initialize and finalize loop structures, copying headers inbetween. */ | |
297 virtual unsigned int execute (function *); | |
298 | |
299 opt_pass * clone () { return new pass_ch (m_ctxt); } | |
300 | |
301 protected: | |
302 /* ch_base method: */ | |
145 | 303 virtual bool process_loop_p (class loop *loop); |
111 | 304 }; // class pass_ch |
305 | |
306 const pass_data pass_data_ch_vect = | |
307 { | |
308 GIMPLE_PASS, /* type */ | |
309 "ch_vect", /* name */ | |
310 OPTGROUP_LOOP, /* optinfo_flags */ | |
311 TV_TREE_CH, /* tv_id */ | |
312 ( PROP_cfg | PROP_ssa ), /* properties_required */ | |
313 0, /* properties_provided */ | |
314 0, /* properties_destroyed */ | |
315 0, /* todo_flags_start */ | |
316 0, /* todo_flags_finish */ | |
317 }; | |
318 | |
319 /* This is a more aggressive version of the same pass, designed to run just | |
320 before if-conversion and vectorization, to put more loops into the form | |
321 required for those phases. */ | |
322 class pass_ch_vect : public ch_base | |
323 { | |
324 public: | |
325 pass_ch_vect (gcc::context *ctxt) | |
326 : ch_base (pass_data_ch_vect, ctxt) | |
327 {} | |
328 | |
329 /* opt_pass methods: */ | |
330 virtual bool gate (function *fun) | |
331 { | |
332 return flag_tree_ch != 0 | |
333 && (flag_tree_loop_vectorize != 0 || fun->has_force_vectorize_loops); | |
334 } | |
335 | |
336 /* Just copy headers, no initialization/finalization of loop structures. */ | |
337 virtual unsigned int execute (function *); | |
338 | |
339 protected: | |
340 /* ch_base method: */ | |
145 | 341 virtual bool process_loop_p (class loop *loop); |
111 | 342 }; // class pass_ch_vect |
343 | |
0 | 344 /* For all loops, copy the condition at the end of the loop body in front |
345 of the loop. This is beneficial since it increases efficiency of | |
346 code motion optimizations. It also saves one jump on entry to the loop. */ | |
347 | |
111 | 348 unsigned int |
349 ch_base::copy_headers (function *fun) | |
0 | 350 { |
145 | 351 class loop *loop; |
0 | 352 basic_block header; |
353 edge exit, entry; | |
354 basic_block *bbs, *copied_bbs; | |
355 unsigned n_bbs; | |
356 unsigned bbs_size; | |
111 | 357 bool changed = false; |
0 | 358 |
111 | 359 if (number_of_loops (fun) <= 1) |
145 | 360 return 0; |
0 | 361 |
111 | 362 bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun)); |
363 copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun)); | |
364 bbs_size = n_basic_blocks_for_fn (fun); | |
0 | 365 |
145 | 366 auto_vec<std::pair<edge, loop_p> > copied; |
367 | |
111 | 368 FOR_EACH_LOOP (loop, 0) |
0 | 369 { |
145 | 370 int initial_limit = param_max_loop_header_insns; |
111 | 371 int remaining_limit = initial_limit; |
372 if (dump_file && (dump_flags & TDF_DETAILS)) | |
373 fprintf (dump_file, | |
374 "Analyzing loop %i\n", loop->num); | |
0 | 375 |
376 header = loop->header; | |
377 | |
378 /* If the loop is already a do-while style one (either because it was | |
379 written as such, or because jump threading transformed it into one), | |
380 we might be in fact peeling the first iteration of the loop. This | |
131 | 381 in general is not a good idea. Also avoid touching infinite loops. */ |
382 if (!loop_has_exit_edges (loop) | |
383 || !process_loop_p (loop)) | |
0 | 384 continue; |
385 | |
386 /* Iterate the header copying up to limit; this takes care of the cases | |
387 like while (a && b) {...}, where we want to have both of the conditions | |
388 copied. TODO -- handle while (a || b) - like cases, by not requiring | |
389 the header to have just a single successor and copying up to | |
390 postdominator. */ | |
391 | |
392 exit = NULL; | |
393 n_bbs = 0; | |
111 | 394 while (should_duplicate_loop_header_p (header, loop, &remaining_limit)) |
0 | 395 { |
396 /* Find a successor of header that is inside a loop; i.e. the new | |
397 header after the condition is copied. */ | |
398 if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)) | |
399 exit = EDGE_SUCC (header, 0); | |
400 else | |
401 exit = EDGE_SUCC (header, 1); | |
402 bbs[n_bbs++] = header; | |
403 gcc_assert (bbs_size > n_bbs); | |
404 header = exit->dest; | |
405 } | |
406 | |
407 if (!exit) | |
408 continue; | |
409 | |
410 if (dump_file && (dump_flags & TDF_DETAILS)) | |
411 fprintf (dump_file, | |
111 | 412 "Duplicating header of the loop %d up to edge %d->%d," |
413 " %i insns.\n", | |
414 loop->num, exit->src->index, exit->dest->index, | |
415 initial_limit - remaining_limit); | |
0 | 416 |
417 /* Ensure that the header will have just the latch as a predecessor | |
418 inside the loop. */ | |
419 if (!single_pred_p (exit->dest)) | |
420 exit = single_pred_edge (split_edge (exit)); | |
421 | |
422 entry = loop_preheader_edge (loop); | |
423 | |
111 | 424 propagate_threaded_block_debug_into (exit->dest, entry->dest); |
425 if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs, | |
426 true)) | |
0 | 427 { |
428 fprintf (dump_file, "Duplication failed.\n"); | |
429 continue; | |
430 } | |
145 | 431 copied.safe_push (std::make_pair (entry, loop)); |
0 | 432 |
433 /* If the loop has the form "for (i = j; i < j + 10; i++)" then | |
434 this copying can introduce a case where we rely on undefined | |
435 signed overflow to eliminate the preheader condition, because | |
436 we assume that "j < j + 10" is true. We don't want to warn | |
437 about that case for -Wstrict-overflow, because in general we | |
438 don't warn about overflow involving loops. Prevent the | |
439 warning by setting the no_warning flag in the condition. */ | |
440 if (warn_strict_overflow > 0) | |
441 { | |
442 unsigned int i; | |
443 | |
444 for (i = 0; i < n_bbs; ++i) | |
445 { | |
446 gimple_stmt_iterator bsi; | |
447 | |
448 for (bsi = gsi_start_bb (copied_bbs[i]); | |
449 !gsi_end_p (bsi); | |
450 gsi_next (&bsi)) | |
451 { | |
111 | 452 gimple *stmt = gsi_stmt (bsi); |
0 | 453 if (gimple_code (stmt) == GIMPLE_COND) |
145 | 454 { |
455 tree lhs = gimple_cond_lhs (stmt); | |
456 if (gimple_cond_code (stmt) != EQ_EXPR | |
457 && gimple_cond_code (stmt) != NE_EXPR | |
458 && INTEGRAL_TYPE_P (TREE_TYPE (lhs)) | |
459 && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))) | |
460 gimple_set_no_warning (stmt, true); | |
461 } | |
0 | 462 else if (is_gimple_assign (stmt)) |
463 { | |
464 enum tree_code rhs_code = gimple_assign_rhs_code (stmt); | |
145 | 465 tree rhs1 = gimple_assign_rhs1 (stmt); |
466 if (TREE_CODE_CLASS (rhs_code) == tcc_comparison | |
467 && rhs_code != EQ_EXPR | |
468 && rhs_code != NE_EXPR | |
469 && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) | |
470 && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (rhs1))) | |
0 | 471 gimple_set_no_warning (stmt, true); |
472 } | |
473 } | |
474 } | |
475 } | |
476 | |
477 /* Ensure that the latch and the preheader is simple (we know that they | |
478 are not now, since there was the loop exit condition. */ | |
479 split_edge (loop_preheader_edge (loop)); | |
480 split_edge (loop_latch_edge (loop)); | |
111 | 481 |
131 | 482 if (dump_file && (dump_flags & TDF_DETAILS)) |
483 { | |
484 if (do_while_loop_p (loop)) | |
485 fprintf (dump_file, "Loop %d is now do-while loop.\n", loop->num); | |
486 else | |
487 fprintf (dump_file, "Loop %d is still not do-while loop.\n", | |
488 loop->num); | |
489 } | |
490 | |
111 | 491 changed = true; |
0 | 492 } |
493 | |
111 | 494 if (changed) |
145 | 495 { |
496 update_ssa (TODO_update_ssa); | |
497 /* After updating SSA form perform CSE on the loop header | |
498 copies. This is esp. required for the pass before | |
499 vectorization since nothing cleans up copied exit tests | |
500 that can now be simplified. CSE from the entry of the | |
501 region we copied till all loop exit blocks but not | |
502 entering the loop itself. */ | |
503 for (unsigned i = 0; i < copied.length (); ++i) | |
504 { | |
505 edge entry = copied[i].first; | |
506 loop_p loop = copied[i].second; | |
507 vec<edge> exit_edges = get_loop_exit_edges (loop); | |
508 bitmap exit_bbs = BITMAP_ALLOC (NULL); | |
509 for (unsigned j = 0; j < exit_edges.length (); ++j) | |
510 bitmap_set_bit (exit_bbs, exit_edges[j]->dest->index); | |
511 bitmap_set_bit (exit_bbs, loop->header->index); | |
512 do_rpo_vn (cfun, entry, exit_bbs); | |
513 BITMAP_FREE (exit_bbs); | |
514 exit_edges.release (); | |
515 } | |
516 } | |
0 | 517 free (bbs); |
518 free (copied_bbs); | |
519 | |
111 | 520 return changed ? TODO_cleanup_cfg : 0; |
521 } | |
522 | |
523 /* Initialize the loop structures we need, and finalize after. */ | |
524 | |
525 unsigned int | |
526 pass_ch::execute (function *fun) | |
527 { | |
528 loop_optimizer_init (LOOPS_HAVE_PREHEADERS | |
131 | 529 | LOOPS_HAVE_SIMPLE_LATCHES |
530 | LOOPS_HAVE_RECORDED_EXITS); | |
111 | 531 |
532 unsigned int res = copy_headers (fun); | |
533 | |
0 | 534 loop_optimizer_finalize (); |
111 | 535 return res; |
0 | 536 } |
537 | |
111 | 538 /* Assume an earlier phase has already initialized all the loop structures that |
539 we need here (and perhaps others too), and that these will be finalized by | |
540 a later phase. */ | |
541 | |
542 unsigned int | |
543 pass_ch_vect::execute (function *fun) | |
0 | 544 { |
111 | 545 return copy_headers (fun); |
546 } | |
547 | |
548 /* Apply header copying according to a very simple test of do-while shape. */ | |
549 | |
550 bool | |
145 | 551 pass_ch::process_loop_p (class loop *loop) |
111 | 552 { |
553 return !do_while_loop_p (loop); | |
0 | 554 } |
555 | |
111 | 556 /* Apply header-copying to loops where we might enable vectorization. */ |
557 | |
558 bool | |
145 | 559 pass_ch_vect::process_loop_p (class loop *loop) |
0 | 560 { |
111 | 561 if (!flag_tree_loop_vectorize && !loop->force_vectorize) |
562 return false; | |
563 | |
564 if (loop->dont_vectorize) | |
565 return false; | |
566 | |
145 | 567 /* The vectorizer won't handle anything with multiple exits, so skip. */ |
111 | 568 edge exit = single_exit (loop); |
569 if (!exit) | |
570 return false; | |
571 | |
145 | 572 if (!do_while_loop_p (loop)) |
573 return true; | |
111 | 574 |
575 return false; | |
576 } | |
577 | |
578 } // anon namespace | |
579 | |
580 gimple_opt_pass * | |
581 make_pass_ch_vect (gcc::context *ctxt) | |
582 { | |
583 return new pass_ch_vect (ctxt); | |
584 } | |
585 | |
586 gimple_opt_pass * | |
587 make_pass_ch (gcc::context *ctxt) | |
588 { | |
589 return new pass_ch (ctxt); | |
590 } |