Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-ssa-loop-ch.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Loop header copying on trees. | 1 /* Loop header copying on trees. |
2 Copyright (C) 2004-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2004-2020 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it | 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 | 7 under the terms of the GNU General Public License as published by the |
31 #include "tree-into-ssa.h" | 31 #include "tree-into-ssa.h" |
32 #include "cfgloop.h" | 32 #include "cfgloop.h" |
33 #include "tree-inline.h" | 33 #include "tree-inline.h" |
34 #include "tree-ssa-scopedtables.h" | 34 #include "tree-ssa-scopedtables.h" |
35 #include "tree-ssa-threadedge.h" | 35 #include "tree-ssa-threadedge.h" |
36 #include "params.h" | 36 #include "tree-ssa-sccvn.h" |
37 #include "tree-phinodes.h" | |
38 #include "ssa-iterators.h" | |
37 | 39 |
38 /* Duplicates headers of loops if they are small enough, so that the statements | 40 /* Duplicates headers of loops if they are small enough, so that the statements |
39 in the loop body are always executed when the loop is entered. This | 41 in the loop body are always executed when the loop is entered. This |
40 increases effectiveness of code motion optimizations, and reduces the need | 42 increases effectiveness of code motion optimizations, and reduces the need |
41 for loop preconditioning. */ | 43 for loop preconditioning. */ |
43 /* Check whether we should duplicate HEADER of LOOP. At most *LIMIT | 45 /* Check whether we should duplicate HEADER of LOOP. At most *LIMIT |
44 instructions should be duplicated, limit is decreased by the actual | 46 instructions should be duplicated, limit is decreased by the actual |
45 amount. */ | 47 amount. */ |
46 | 48 |
47 static bool | 49 static bool |
48 should_duplicate_loop_header_p (basic_block header, struct loop *loop, | 50 should_duplicate_loop_header_p (basic_block header, class loop *loop, |
49 int *limit) | 51 int *limit) |
50 { | 52 { |
51 gimple_stmt_iterator bsi; | 53 gimple_stmt_iterator bsi; |
52 gimple *last; | |
53 | 54 |
54 gcc_assert (!header->aux); | 55 gcc_assert (!header->aux); |
55 | 56 |
56 /* Loop header copying usually increases size of the code. This used not to | 57 /* Loop header copying usually increases size of the code. This used not to |
57 be true, since quite often it is possible to verify that the condition is | 58 be true, since quite often it is possible to verify that the condition is |
96 " Not duplicating bb %i: it has mutiple predecestors.\n", | 97 " Not duplicating bb %i: it has mutiple predecestors.\n", |
97 header->index); | 98 header->index); |
98 return false; | 99 return false; |
99 } | 100 } |
100 | 101 |
101 last = last_stmt (header); | 102 gcond *last = safe_dyn_cast <gcond *> (last_stmt (header)); |
102 if (gimple_code (last) != GIMPLE_COND) | 103 if (!last) |
103 { | 104 { |
104 if (dump_file && (dump_flags & TDF_DETAILS)) | 105 if (dump_file && (dump_flags & TDF_DETAILS)) |
105 fprintf (dump_file, | 106 fprintf (dump_file, |
106 " Not duplicating bb %i: it does not end by conditional.\n", | 107 " Not duplicating bb %i: it does not end by conditional.\n", |
107 header->index); | 108 header->index); |
108 return false; | 109 return false; |
109 } | 110 } |
110 | 111 |
111 /* Count number of instructions and punt on calls. */ | 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. */ | |
112 for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi)) | 127 for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi)) |
113 { | 128 { |
114 last = gsi_stmt (bsi); | 129 gimple *last = gsi_stmt (bsi); |
115 | 130 |
116 if (gimple_code (last) == GIMPLE_LABEL) | 131 if (gimple_code (last) == GIMPLE_LABEL) |
117 continue; | 132 continue; |
118 | 133 |
119 if (is_gimple_debug (last)) | 134 if (is_gimple_debug (last)) |
139 fprintf (dump_file, | 154 fprintf (dump_file, |
140 " Not duplicating bb %i contains too many insns.\n", | 155 " Not duplicating bb %i contains too many insns.\n", |
141 header->index); | 156 header->index); |
142 return false; | 157 return false; |
143 } | 158 } |
144 } | 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 } | |
181 } | |
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 | |
145 if (dump_file && (dump_flags & TDF_DETAILS)) | 205 if (dump_file && (dump_flags & TDF_DETAILS)) |
146 fprintf (dump_file, " Will duplicate bb %i\n", header->index); | 206 fprintf (dump_file, " Will duplicate bb %i\n", header->index); |
147 return true; | 207 return true; |
148 } | 208 } |
149 | 209 |
150 /* Checks whether LOOP is a do-while style loop. */ | 210 /* Checks whether LOOP is a do-while style loop. */ |
151 | 211 |
152 static bool | 212 static bool |
153 do_while_loop_p (struct loop *loop) | 213 do_while_loop_p (class loop *loop) |
154 { | 214 { |
155 gimple *stmt = last_stmt (loop->latch); | 215 gimple *stmt = last_stmt (loop->latch); |
156 | 216 |
157 /* If the latch of the loop is not empty, it is not a do-while loop. */ | 217 /* If the latch of the loop is not empty, it is not a do-while loop. */ |
158 if (stmt | 218 if (stmt |
205 | 265 |
206 /* Copies headers of all loops in FUN for which process_loop_p is true. */ | 266 /* Copies headers of all loops in FUN for which process_loop_p is true. */ |
207 unsigned int copy_headers (function *fun); | 267 unsigned int copy_headers (function *fun); |
208 | 268 |
209 /* Return true to copy headers of LOOP or false to skip. */ | 269 /* Return true to copy headers of LOOP or false to skip. */ |
210 virtual bool process_loop_p (struct loop *loop) = 0; | 270 virtual bool process_loop_p (class loop *loop) = 0; |
211 }; | 271 }; |
212 | 272 |
213 const pass_data pass_data_ch = | 273 const pass_data pass_data_ch = |
214 { | 274 { |
215 GIMPLE_PASS, /* type */ | 275 GIMPLE_PASS, /* type */ |
238 | 298 |
239 opt_pass * clone () { return new pass_ch (m_ctxt); } | 299 opt_pass * clone () { return new pass_ch (m_ctxt); } |
240 | 300 |
241 protected: | 301 protected: |
242 /* ch_base method: */ | 302 /* ch_base method: */ |
243 virtual bool process_loop_p (struct loop *loop); | 303 virtual bool process_loop_p (class loop *loop); |
244 }; // class pass_ch | 304 }; // class pass_ch |
245 | 305 |
246 const pass_data pass_data_ch_vect = | 306 const pass_data pass_data_ch_vect = |
247 { | 307 { |
248 GIMPLE_PASS, /* type */ | 308 GIMPLE_PASS, /* type */ |
276 /* Just copy headers, no initialization/finalization of loop structures. */ | 336 /* Just copy headers, no initialization/finalization of loop structures. */ |
277 virtual unsigned int execute (function *); | 337 virtual unsigned int execute (function *); |
278 | 338 |
279 protected: | 339 protected: |
280 /* ch_base method: */ | 340 /* ch_base method: */ |
281 virtual bool process_loop_p (struct loop *loop); | 341 virtual bool process_loop_p (class loop *loop); |
282 }; // class pass_ch_vect | 342 }; // class pass_ch_vect |
283 | 343 |
284 /* For all loops, copy the condition at the end of the loop body in front | 344 /* For all loops, copy the condition at the end of the loop body in front |
285 of the loop. This is beneficial since it increases efficiency of | 345 of the loop. This is beneficial since it increases efficiency of |
286 code motion optimizations. It also saves one jump on entry to the loop. */ | 346 code motion optimizations. It also saves one jump on entry to the loop. */ |
287 | 347 |
288 unsigned int | 348 unsigned int |
289 ch_base::copy_headers (function *fun) | 349 ch_base::copy_headers (function *fun) |
290 { | 350 { |
291 struct loop *loop; | 351 class loop *loop; |
292 basic_block header; | 352 basic_block header; |
293 edge exit, entry; | 353 edge exit, entry; |
294 basic_block *bbs, *copied_bbs; | 354 basic_block *bbs, *copied_bbs; |
295 unsigned n_bbs; | 355 unsigned n_bbs; |
296 unsigned bbs_size; | 356 unsigned bbs_size; |
297 bool changed = false; | 357 bool changed = false; |
298 | 358 |
299 if (number_of_loops (fun) <= 1) | 359 if (number_of_loops (fun) <= 1) |
300 return 0; | 360 return 0; |
301 | 361 |
302 bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun)); | 362 bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun)); |
303 copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun)); | 363 copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun)); |
304 bbs_size = n_basic_blocks_for_fn (fun); | 364 bbs_size = n_basic_blocks_for_fn (fun); |
305 | 365 |
366 auto_vec<std::pair<edge, loop_p> > copied; | |
367 | |
306 FOR_EACH_LOOP (loop, 0) | 368 FOR_EACH_LOOP (loop, 0) |
307 { | 369 { |
308 int initial_limit = PARAM_VALUE (PARAM_MAX_LOOP_HEADER_INSNS); | 370 int initial_limit = param_max_loop_header_insns; |
309 int remaining_limit = initial_limit; | 371 int remaining_limit = initial_limit; |
310 if (dump_file && (dump_flags & TDF_DETAILS)) | 372 if (dump_file && (dump_flags & TDF_DETAILS)) |
311 fprintf (dump_file, | 373 fprintf (dump_file, |
312 "Analyzing loop %i\n", loop->num); | 374 "Analyzing loop %i\n", loop->num); |
313 | 375 |
338 else | 400 else |
339 exit = EDGE_SUCC (header, 1); | 401 exit = EDGE_SUCC (header, 1); |
340 bbs[n_bbs++] = header; | 402 bbs[n_bbs++] = header; |
341 gcc_assert (bbs_size > n_bbs); | 403 gcc_assert (bbs_size > n_bbs); |
342 header = exit->dest; | 404 header = exit->dest; |
343 /* Make sure to stop copying after we copied the first exit test. | |
344 Without further heuristics we do not want to rotate the loop | |
345 any further. */ | |
346 if (loop_exits_from_bb_p (loop, exit->src)) | |
347 break; | |
348 } | 405 } |
349 | 406 |
350 if (!exit) | 407 if (!exit) |
351 continue; | 408 continue; |
352 | 409 |
369 true)) | 426 true)) |
370 { | 427 { |
371 fprintf (dump_file, "Duplication failed.\n"); | 428 fprintf (dump_file, "Duplication failed.\n"); |
372 continue; | 429 continue; |
373 } | 430 } |
431 copied.safe_push (std::make_pair (entry, loop)); | |
374 | 432 |
375 /* If the loop has the form "for (i = j; i < j + 10; i++)" then | 433 /* If the loop has the form "for (i = j; i < j + 10; i++)" then |
376 this copying can introduce a case where we rely on undefined | 434 this copying can introduce a case where we rely on undefined |
377 signed overflow to eliminate the preheader condition, because | 435 signed overflow to eliminate the preheader condition, because |
378 we assume that "j < j + 10" is true. We don't want to warn | 436 we assume that "j < j + 10" is true. We don't want to warn |
391 !gsi_end_p (bsi); | 449 !gsi_end_p (bsi); |
392 gsi_next (&bsi)) | 450 gsi_next (&bsi)) |
393 { | 451 { |
394 gimple *stmt = gsi_stmt (bsi); | 452 gimple *stmt = gsi_stmt (bsi); |
395 if (gimple_code (stmt) == GIMPLE_COND) | 453 if (gimple_code (stmt) == GIMPLE_COND) |
396 gimple_set_no_warning (stmt, true); | 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 } | |
397 else if (is_gimple_assign (stmt)) | 462 else if (is_gimple_assign (stmt)) |
398 { | 463 { |
399 enum tree_code rhs_code = gimple_assign_rhs_code (stmt); | 464 enum tree_code rhs_code = gimple_assign_rhs_code (stmt); |
400 if (TREE_CODE_CLASS (rhs_code) == tcc_comparison) | 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))) | |
401 gimple_set_no_warning (stmt, true); | 471 gimple_set_no_warning (stmt, true); |
402 } | 472 } |
403 } | 473 } |
404 } | 474 } |
405 } | 475 } |
420 | 490 |
421 changed = true; | 491 changed = true; |
422 } | 492 } |
423 | 493 |
424 if (changed) | 494 if (changed) |
425 update_ssa (TODO_update_ssa); | 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 } | |
426 free (bbs); | 517 free (bbs); |
427 free (copied_bbs); | 518 free (copied_bbs); |
428 | 519 |
429 return changed ? TODO_cleanup_cfg : 0; | 520 return changed ? TODO_cleanup_cfg : 0; |
430 } | 521 } |
455 } | 546 } |
456 | 547 |
457 /* Apply header copying according to a very simple test of do-while shape. */ | 548 /* Apply header copying according to a very simple test of do-while shape. */ |
458 | 549 |
459 bool | 550 bool |
460 pass_ch::process_loop_p (struct loop *loop) | 551 pass_ch::process_loop_p (class loop *loop) |
461 { | 552 { |
462 return !do_while_loop_p (loop); | 553 return !do_while_loop_p (loop); |
463 } | 554 } |
464 | 555 |
465 /* Apply header-copying to loops where we might enable vectorization. */ | 556 /* Apply header-copying to loops where we might enable vectorization. */ |
466 | 557 |
467 bool | 558 bool |
468 pass_ch_vect::process_loop_p (struct loop *loop) | 559 pass_ch_vect::process_loop_p (class loop *loop) |
469 { | 560 { |
470 if (!flag_tree_loop_vectorize && !loop->force_vectorize) | 561 if (!flag_tree_loop_vectorize && !loop->force_vectorize) |
471 return false; | 562 return false; |
472 | 563 |
473 if (loop->dont_vectorize) | 564 if (loop->dont_vectorize) |
474 return false; | 565 return false; |
475 | 566 |
476 if (!do_while_loop_p (loop)) | 567 /* The vectorizer won't handle anything with multiple exits, so skip. */ |
477 return true; | |
478 | |
479 /* The vectorizer won't handle anything with multiple exits, so skip. */ | |
480 edge exit = single_exit (loop); | 568 edge exit = single_exit (loop); |
481 if (!exit) | 569 if (!exit) |
482 return false; | 570 return false; |
483 | 571 |
484 /* Copy headers iff there looks to be code in the loop after the exit block, | 572 if (!do_while_loop_p (loop)) |
485 i.e. the exit block has an edge to another block (besides the latch, | 573 return true; |
486 which should be empty). */ | |
487 edge_iterator ei; | |
488 edge e; | |
489 FOR_EACH_EDGE (e, ei, exit->src->succs) | |
490 if (!loop_exit_edge_p (loop, e) | |
491 && e->dest != loop->header | |
492 && e->dest != loop->latch) | |
493 return true; | |
494 | 574 |
495 return false; | 575 return false; |
496 } | 576 } |
497 | 577 |
498 } // anon namespace | 578 } // anon namespace |