* gcc.dg/pr27095.c: For Epiphany, add -mshort-calls.
[official-gcc.git] / gcc / tree-loop-distribution.c
blob13b78cc37d2f713c4d219d158d103f938e30c5e0
1 /* Loop distribution.
2 Copyright (C) 2006-2013 Free Software Foundation, Inc.
3 Contributed by Georges-Andre Silber <Georges-Andre.Silber@ensmp.fr>
4 and Sebastian Pop <sebastian.pop@amd.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3, or (at your option) any
11 later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* This pass performs loop distribution: for example, the loop
24 |DO I = 2, N
25 | A(I) = B(I) + C
26 | D(I) = A(I-1)*E
27 |ENDDO
29 is transformed to
31 |DOALL I = 2, N
32 | A(I) = B(I) + C
33 |ENDDO
35 |DOALL I = 2, N
36 | D(I) = A(I-1)*E
37 |ENDDO
39 This pass uses an RDG, Reduced Dependence Graph built on top of the
40 data dependence relations. The RDG is then topologically sorted to
41 obtain a map of information producers/consumers based on which it
42 generates the new loops. */
44 #include "config.h"
45 #include "system.h"
46 #include "coretypes.h"
47 #include "tree-flow.h"
48 #include "cfgloop.h"
49 #include "tree-chrec.h"
50 #include "tree-data-ref.h"
51 #include "tree-scalar-evolution.h"
52 #include "tree-pass.h"
54 enum partition_kind {
55 PKIND_NORMAL, PKIND_REDUCTION, PKIND_MEMSET, PKIND_MEMCPY
58 typedef struct partition_s
60 bitmap stmts;
61 bool has_writes;
62 enum partition_kind kind;
63 /* data-references a kind != PKIND_NORMAL partition is about. */
64 data_reference_p main_dr;
65 data_reference_p secondary_dr;
66 } *partition_t;
69 /* Allocate and initialize a partition from BITMAP. */
71 static partition_t
72 partition_alloc (bitmap stmts)
74 partition_t partition = XCNEW (struct partition_s);
75 partition->stmts = stmts ? stmts : BITMAP_ALLOC (NULL);
76 partition->has_writes = false;
77 partition->kind = PKIND_NORMAL;
78 return partition;
81 /* Free PARTITION. */
83 static void
84 partition_free (partition_t partition)
86 BITMAP_FREE (partition->stmts);
87 free (partition);
90 /* Returns true if the partition can be generated as a builtin. */
92 static bool
93 partition_builtin_p (partition_t partition)
95 return partition->kind > PKIND_REDUCTION;
98 /* Returns true if the partition has an writes. */
100 static bool
101 partition_has_writes (partition_t partition)
103 return partition->has_writes;
106 /* If bit I is not set, it means that this node represents an
107 operation that has already been performed, and that should not be
108 performed again. This is the subgraph of remaining important
109 computations that is passed to the DFS algorithm for avoiding to
110 include several times the same stores in different loops. */
111 static bitmap remaining_stmts;
113 /* A node of the RDG is marked in this bitmap when it has as a
114 predecessor a node that writes to memory. */
115 static bitmap upstream_mem_writes;
117 /* Returns true when DEF is an SSA_NAME defined in LOOP and used after
118 the LOOP. */
120 static bool
121 ssa_name_has_uses_outside_loop_p (tree def, loop_p loop)
123 imm_use_iterator imm_iter;
124 use_operand_p use_p;
126 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def)
128 gimple use_stmt = USE_STMT (use_p);
129 if (!is_gimple_debug (use_stmt)
130 && loop != loop_containing_stmt (use_stmt))
131 return true;
134 return false;
137 /* Returns true when STMT defines a scalar variable used after the
138 loop LOOP. */
140 static bool
141 stmt_has_scalar_dependences_outside_loop (loop_p loop, gimple stmt)
143 def_operand_p def_p;
144 ssa_op_iter op_iter;
146 if (gimple_code (stmt) == GIMPLE_PHI)
147 return ssa_name_has_uses_outside_loop_p (gimple_phi_result (stmt), loop);
149 FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
150 if (ssa_name_has_uses_outside_loop_p (DEF_FROM_PTR (def_p), loop))
151 return true;
153 return false;
156 /* Return a copy of LOOP placed before LOOP. */
158 static struct loop *
159 copy_loop_before (struct loop *loop)
161 struct loop *res;
162 edge preheader = loop_preheader_edge (loop);
164 initialize_original_copy_tables ();
165 res = slpeel_tree_duplicate_loop_to_edge_cfg (loop, preheader);
166 gcc_assert (res != NULL);
167 free_original_copy_tables ();
168 delete_update_ssa ();
170 return res;
173 /* Creates an empty basic block after LOOP. */
175 static void
176 create_bb_after_loop (struct loop *loop)
178 edge exit = single_exit (loop);
180 if (!exit)
181 return;
183 split_edge (exit);
186 /* Generate code for PARTITION from the code in LOOP. The loop is
187 copied when COPY_P is true. All the statements not flagged in the
188 PARTITION bitmap are removed from the loop or from its copy. The
189 statements are indexed in sequence inside a basic block, and the
190 basic blocks of a loop are taken in dom order. */
192 static void
193 generate_loops_for_partition (struct loop *loop, partition_t partition,
194 bool copy_p)
196 unsigned i, x;
197 gimple_stmt_iterator bsi;
198 basic_block *bbs;
200 if (copy_p)
202 loop = copy_loop_before (loop);
203 gcc_assert (loop != NULL);
204 create_preheader (loop, CP_SIMPLE_PREHEADERS);
205 create_bb_after_loop (loop);
208 /* Remove stmts not in the PARTITION bitmap. The order in which we
209 visit the phi nodes and the statements is exactly as in
210 stmts_from_loop. */
211 bbs = get_loop_body_in_dom_order (loop);
213 if (MAY_HAVE_DEBUG_STMTS)
214 for (x = 0, i = 0; i < loop->num_nodes; i++)
216 basic_block bb = bbs[i];
218 for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
219 if (!bitmap_bit_p (partition->stmts, x++))
220 reset_debug_uses (gsi_stmt (bsi));
222 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
224 gimple stmt = gsi_stmt (bsi);
225 if (gimple_code (stmt) != GIMPLE_LABEL
226 && !is_gimple_debug (stmt)
227 && !bitmap_bit_p (partition->stmts, x++))
228 reset_debug_uses (stmt);
232 for (x = 0, i = 0; i < loop->num_nodes; i++)
234 basic_block bb = bbs[i];
236 for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi);)
237 if (!bitmap_bit_p (partition->stmts, x++))
239 gimple phi = gsi_stmt (bsi);
240 if (virtual_operand_p (gimple_phi_result (phi)))
241 mark_virtual_phi_result_for_renaming (phi);
242 remove_phi_node (&bsi, true);
244 else
245 gsi_next (&bsi);
247 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi);)
249 gimple stmt = gsi_stmt (bsi);
250 if (gimple_code (stmt) != GIMPLE_LABEL
251 && !is_gimple_debug (stmt)
252 && !bitmap_bit_p (partition->stmts, x++))
254 unlink_stmt_vdef (stmt);
255 gsi_remove (&bsi, true);
256 release_defs (stmt);
258 else
259 gsi_next (&bsi);
263 free (bbs);
266 /* Build the size argument for a memory operation call. */
268 static tree
269 build_size_arg_loc (location_t loc, data_reference_p dr, tree nb_iter)
271 tree size;
272 size = fold_build2_loc (loc, MULT_EXPR, sizetype,
273 fold_convert_loc (loc, sizetype, nb_iter),
274 TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
275 return fold_convert_loc (loc, size_type_node, size);
278 /* Build an address argument for a memory operation call. */
280 static tree
281 build_addr_arg_loc (location_t loc, data_reference_p dr, tree nb_bytes)
283 tree addr_base;
285 addr_base = size_binop_loc (loc, PLUS_EXPR, DR_OFFSET (dr), DR_INIT (dr));
286 addr_base = fold_convert_loc (loc, sizetype, addr_base);
288 /* Test for a negative stride, iterating over every element. */
289 if (tree_int_cst_sgn (DR_STEP (dr)) == -1)
291 addr_base = size_binop_loc (loc, MINUS_EXPR, addr_base,
292 fold_convert_loc (loc, sizetype, nb_bytes));
293 addr_base = size_binop_loc (loc, PLUS_EXPR, addr_base,
294 TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
297 return fold_build_pointer_plus_loc (loc, DR_BASE_ADDRESS (dr), addr_base);
300 /* If VAL memory representation contains the same value in all bytes,
301 return that value, otherwise return -1.
302 E.g. for 0x24242424 return 0x24, for IEEE double
303 747708026454360457216.0 return 0x44, etc. */
305 static int
306 const_with_all_bytes_same (tree val)
308 unsigned char buf[64];
309 int i, len;
311 if (integer_zerop (val)
312 || real_zerop (val)
313 || (TREE_CODE (val) == CONSTRUCTOR
314 && !TREE_CLOBBER_P (val)
315 && CONSTRUCTOR_NELTS (val) == 0))
316 return 0;
318 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
319 return -1;
321 len = native_encode_expr (val, buf, sizeof (buf));
322 if (len == 0)
323 return -1;
324 for (i = 1; i < len; i++)
325 if (buf[i] != buf[0])
326 return -1;
327 return buf[0];
330 /* Generate a call to memset for PARTITION in LOOP. */
332 static void
333 generate_memset_builtin (struct loop *loop, partition_t partition)
335 gimple_stmt_iterator gsi;
336 gimple stmt, fn_call;
337 tree nb_iter, mem, fn, nb_bytes;
338 location_t loc;
339 tree val;
341 stmt = DR_STMT (partition->main_dr);
342 loc = gimple_location (stmt);
343 if (gimple_bb (stmt) == loop->latch)
344 nb_iter = number_of_latch_executions (loop);
345 else
346 nb_iter = number_of_exit_cond_executions (loop);
348 /* The new statements will be placed before LOOP. */
349 gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
351 nb_bytes = build_size_arg_loc (loc, partition->main_dr, nb_iter);
352 nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
353 false, GSI_CONTINUE_LINKING);
354 mem = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
355 mem = force_gimple_operand_gsi (&gsi, mem, true, NULL_TREE,
356 false, GSI_CONTINUE_LINKING);
358 /* This exactly matches the pattern recognition in classify_partition. */
359 val = gimple_assign_rhs1 (stmt);
360 /* Handle constants like 0x15151515 and similarly
361 floating point constants etc. where all bytes are the same. */
362 int bytev = const_with_all_bytes_same (val);
363 if (bytev != -1)
364 val = build_int_cst (integer_type_node, bytev);
365 else if (TREE_CODE (val) == INTEGER_CST)
366 val = fold_convert (integer_type_node, val);
367 else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val)))
369 gimple cstmt;
370 tree tem = make_ssa_name (integer_type_node, NULL);
371 cstmt = gimple_build_assign_with_ops (NOP_EXPR, tem, val, NULL_TREE);
372 gsi_insert_after (&gsi, cstmt, GSI_CONTINUE_LINKING);
373 val = tem;
376 fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
377 fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes);
378 gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
380 if (dump_file && (dump_flags & TDF_DETAILS))
382 fprintf (dump_file, "generated memset");
383 if (bytev == 0)
384 fprintf (dump_file, " zero\n");
385 else
386 fprintf (dump_file, "\n");
390 /* Generate a call to memcpy for PARTITION in LOOP. */
392 static void
393 generate_memcpy_builtin (struct loop *loop, partition_t partition)
395 gimple_stmt_iterator gsi;
396 gimple stmt, fn_call;
397 tree nb_iter, dest, src, fn, nb_bytes;
398 location_t loc;
399 enum built_in_function kind;
401 stmt = DR_STMT (partition->main_dr);
402 loc = gimple_location (stmt);
403 if (gimple_bb (stmt) == loop->latch)
404 nb_iter = number_of_latch_executions (loop);
405 else
406 nb_iter = number_of_exit_cond_executions (loop);
408 /* The new statements will be placed before LOOP. */
409 gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
411 nb_bytes = build_size_arg_loc (loc, partition->main_dr, nb_iter);
412 nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
413 false, GSI_CONTINUE_LINKING);
414 dest = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
415 src = build_addr_arg_loc (loc, partition->secondary_dr, nb_bytes);
416 if (ptr_derefs_may_alias_p (dest, src))
417 kind = BUILT_IN_MEMMOVE;
418 else
419 kind = BUILT_IN_MEMCPY;
421 dest = force_gimple_operand_gsi (&gsi, dest, true, NULL_TREE,
422 false, GSI_CONTINUE_LINKING);
423 src = force_gimple_operand_gsi (&gsi, src, true, NULL_TREE,
424 false, GSI_CONTINUE_LINKING);
425 fn = build_fold_addr_expr (builtin_decl_implicit (kind));
426 fn_call = gimple_build_call (fn, 3, dest, src, nb_bytes);
427 gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
429 if (dump_file && (dump_flags & TDF_DETAILS))
431 if (kind == BUILT_IN_MEMCPY)
432 fprintf (dump_file, "generated memcpy\n");
433 else
434 fprintf (dump_file, "generated memmove\n");
438 /* Remove and destroy the loop LOOP. */
440 static void
441 destroy_loop (struct loop *loop)
443 unsigned nbbs = loop->num_nodes;
444 edge exit = single_exit (loop);
445 basic_block src = loop_preheader_edge (loop)->src, dest = exit->dest;
446 basic_block *bbs;
447 unsigned i;
449 bbs = get_loop_body_in_dom_order (loop);
451 redirect_edge_pred (exit, src);
452 exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
453 exit->flags |= EDGE_FALLTHRU;
454 cancel_loop_tree (loop);
455 rescan_loop_exit (exit, false, true);
457 for (i = 0; i < nbbs; i++)
459 /* We have made sure to not leave any dangling uses of SSA
460 names defined in the loop. With the exception of virtuals.
461 Make sure we replace all uses of virtual defs that will remain
462 outside of the loop with the bare symbol as delete_basic_block
463 will release them. */
464 gimple_stmt_iterator gsi;
465 for (gsi = gsi_start_phis (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
467 gimple phi = gsi_stmt (gsi);
468 if (virtual_operand_p (gimple_phi_result (phi)))
469 mark_virtual_phi_result_for_renaming (phi);
471 for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
473 gimple stmt = gsi_stmt (gsi);
474 tree vdef = gimple_vdef (stmt);
475 if (vdef && TREE_CODE (vdef) == SSA_NAME)
476 mark_virtual_operand_for_renaming (vdef);
478 delete_basic_block (bbs[i]);
480 free (bbs);
482 set_immediate_dominator (CDI_DOMINATORS, dest,
483 recompute_dominator (CDI_DOMINATORS, dest));
486 /* Generates code for PARTITION. */
488 static void
489 generate_code_for_partition (struct loop *loop,
490 partition_t partition, bool copy_p)
492 switch (partition->kind)
494 case PKIND_MEMSET:
495 generate_memset_builtin (loop, partition);
496 /* If this is the last partition for which we generate code, we have
497 to destroy the loop. */
498 if (!copy_p)
499 destroy_loop (loop);
500 break;
502 case PKIND_MEMCPY:
503 generate_memcpy_builtin (loop, partition);
504 /* If this is the last partition for which we generate code, we have
505 to destroy the loop. */
506 if (!copy_p)
507 destroy_loop (loop);
508 break;
510 case PKIND_REDUCTION:
511 /* Reductions all have to be in the last partition. */
512 gcc_assert (!copy_p);
513 case PKIND_NORMAL:
514 generate_loops_for_partition (loop, partition, copy_p);
515 break;
517 default:
518 gcc_unreachable ();
523 /* Returns true if the node V of RDG cannot be recomputed. */
525 static bool
526 rdg_cannot_recompute_vertex_p (struct graph *rdg, int v)
528 if (RDG_MEM_WRITE_STMT (rdg, v))
529 return true;
531 return false;
534 /* Returns true when the vertex V has already been generated in the
535 current partition (V is in PROCESSED), or when V belongs to another
536 partition and cannot be recomputed (V is not in REMAINING_STMTS). */
538 static inline bool
539 already_processed_vertex_p (bitmap processed, int v)
541 return (bitmap_bit_p (processed, v)
542 || !bitmap_bit_p (remaining_stmts, v));
545 /* Returns NULL when there is no anti-dependence among the successors
546 of vertex V, otherwise returns the edge with the anti-dep. */
548 static struct graph_edge *
549 has_anti_dependence (struct vertex *v)
551 struct graph_edge *e;
553 if (v->succ)
554 for (e = v->succ; e; e = e->succ_next)
555 if (RDGE_TYPE (e) == anti_dd)
556 return e;
558 return NULL;
561 /* Returns true when V has an anti-dependence edge among its successors. */
563 static bool
564 predecessor_has_mem_write (struct graph *rdg, struct vertex *v)
566 struct graph_edge *e;
568 if (v->pred)
569 for (e = v->pred; e; e = e->pred_next)
570 if (bitmap_bit_p (upstream_mem_writes, e->src)
571 /* Don't consider flow channels: a write to memory followed
572 by a read from memory. These channels allow the split of
573 the RDG in different partitions. */
574 && !RDG_MEM_WRITE_STMT (rdg, e->src))
575 return true;
577 return false;
580 /* Initializes the upstream_mem_writes bitmap following the
581 information from RDG. */
583 static void
584 mark_nodes_having_upstream_mem_writes (struct graph *rdg)
586 int v, x;
587 bitmap seen = BITMAP_ALLOC (NULL);
589 for (v = rdg->n_vertices - 1; v >= 0; v--)
590 if (!bitmap_bit_p (seen, v))
592 unsigned i;
593 vec<int> nodes;
594 nodes.create (3);
596 graphds_dfs (rdg, &v, 1, &nodes, false, NULL);
598 FOR_EACH_VEC_ELT (nodes, i, x)
600 if (!bitmap_set_bit (seen, x))
601 continue;
603 if (RDG_MEM_WRITE_STMT (rdg, x)
604 || predecessor_has_mem_write (rdg, &(rdg->vertices[x]))
605 /* In anti dependences the read should occur before
606 the write, this is why both the read and the write
607 should be placed in the same partition. */
608 || has_anti_dependence (&(rdg->vertices[x])))
610 bitmap_set_bit (upstream_mem_writes, x);
614 nodes.release ();
618 /* Returns true when vertex u has a memory write node as a predecessor
619 in RDG. */
621 static bool
622 has_upstream_mem_writes (int u)
624 return bitmap_bit_p (upstream_mem_writes, u);
627 static void rdg_flag_vertex_and_dependent (struct graph *, int, partition_t,
628 bitmap, bitmap);
630 /* Flag the uses of U stopping following the information from
631 upstream_mem_writes. */
633 static void
634 rdg_flag_uses (struct graph *rdg, int u, partition_t partition, bitmap loops,
635 bitmap processed)
637 use_operand_p use_p;
638 struct vertex *x = &(rdg->vertices[u]);
639 gimple stmt = RDGV_STMT (x);
640 struct graph_edge *anti_dep = has_anti_dependence (x);
642 /* Keep in the same partition the destination of an antidependence,
643 because this is a store to the exact same location. Putting this
644 in another partition is bad for cache locality. */
645 if (anti_dep)
647 int v = anti_dep->dest;
649 if (!already_processed_vertex_p (processed, v))
650 rdg_flag_vertex_and_dependent (rdg, v, partition, loops,
651 processed);
654 if (gimple_code (stmt) != GIMPLE_PHI)
656 if ((use_p = gimple_vuse_op (stmt)) != NULL_USE_OPERAND_P)
658 tree use = USE_FROM_PTR (use_p);
660 if (TREE_CODE (use) == SSA_NAME
661 && !SSA_NAME_IS_DEFAULT_DEF (use))
663 gimple def_stmt = SSA_NAME_DEF_STMT (use);
664 int v = rdg_vertex_for_stmt (rdg, def_stmt);
666 if (v >= 0
667 && !already_processed_vertex_p (processed, v))
668 rdg_flag_vertex_and_dependent (rdg, v, partition, loops,
669 processed);
674 if (is_gimple_assign (stmt) && has_upstream_mem_writes (u))
676 tree op0 = gimple_assign_lhs (stmt);
678 /* Scalar channels don't have enough space for transmitting data
679 between tasks, unless we add more storage by privatizing. */
680 if (is_gimple_reg (op0))
682 use_operand_p use_p;
683 imm_use_iterator iter;
685 FOR_EACH_IMM_USE_FAST (use_p, iter, op0)
687 int v = rdg_vertex_for_stmt (rdg, USE_STMT (use_p));
689 if (!already_processed_vertex_p (processed, v))
690 rdg_flag_vertex_and_dependent (rdg, v, partition, loops,
691 processed);
697 /* Flag V from RDG as part of PARTITION, and also flag its loop number
698 in LOOPS. */
700 static void
701 rdg_flag_vertex (struct graph *rdg, int v, partition_t partition, bitmap loops)
703 struct loop *loop;
705 if (!bitmap_set_bit (partition->stmts, v))
706 return;
708 loop = loop_containing_stmt (RDG_STMT (rdg, v));
709 bitmap_set_bit (loops, loop->num);
711 if (rdg_cannot_recompute_vertex_p (rdg, v))
713 partition->has_writes = true;
714 bitmap_clear_bit (remaining_stmts, v);
718 /* Flag in the bitmap PARTITION the vertex V and all its predecessors.
719 Also flag their loop number in LOOPS. */
721 static void
722 rdg_flag_vertex_and_dependent (struct graph *rdg, int v, partition_t partition,
723 bitmap loops, bitmap processed)
725 unsigned i;
726 vec<int> nodes;
727 nodes.create (3);
728 int x;
730 bitmap_set_bit (processed, v);
731 rdg_flag_uses (rdg, v, partition, loops, processed);
732 graphds_dfs (rdg, &v, 1, &nodes, false, remaining_stmts);
733 rdg_flag_vertex (rdg, v, partition, loops);
735 FOR_EACH_VEC_ELT (nodes, i, x)
736 if (!already_processed_vertex_p (processed, x))
737 rdg_flag_vertex_and_dependent (rdg, x, partition, loops, processed);
739 nodes.release ();
742 /* Initialize CONDS with all the condition statements from the basic
743 blocks of LOOP. */
745 static void
746 collect_condition_stmts (struct loop *loop, vec<gimple> *conds)
748 unsigned i;
749 edge e;
750 vec<edge> exits = get_loop_exit_edges (loop);
752 FOR_EACH_VEC_ELT (exits, i, e)
754 gimple cond = last_stmt (e->src);
756 if (cond)
757 conds->safe_push (cond);
760 exits.release ();
763 /* Add to PARTITION all the exit condition statements for LOOPS
764 together with all their dependent statements determined from
765 RDG. */
767 static void
768 rdg_flag_loop_exits (struct graph *rdg, bitmap loops, partition_t partition,
769 bitmap processed)
771 unsigned i;
772 bitmap_iterator bi;
773 vec<gimple> conds;
774 conds.create (3);
776 EXECUTE_IF_SET_IN_BITMAP (loops, 0, i, bi)
777 collect_condition_stmts (get_loop (cfun, i), &conds);
779 while (!conds.is_empty ())
781 gimple cond = conds.pop ();
782 int v = rdg_vertex_for_stmt (rdg, cond);
783 bitmap new_loops = BITMAP_ALLOC (NULL);
785 if (!already_processed_vertex_p (processed, v))
786 rdg_flag_vertex_and_dependent (rdg, v, partition, new_loops, processed);
788 EXECUTE_IF_SET_IN_BITMAP (new_loops, 0, i, bi)
789 if (bitmap_set_bit (loops, i))
790 collect_condition_stmts (get_loop (cfun, i), &conds);
792 BITMAP_FREE (new_loops);
795 conds.release ();
798 /* Returns a bitmap in which all the statements needed for computing
799 the strongly connected component C of the RDG are flagged, also
800 including the loop exit conditions. */
802 static partition_t
803 build_rdg_partition_for_component (struct graph *rdg, rdgc c)
805 int i, v;
806 partition_t partition = partition_alloc (NULL);
807 bitmap loops = BITMAP_ALLOC (NULL);
808 bitmap processed = BITMAP_ALLOC (NULL);
810 FOR_EACH_VEC_ELT (c->vertices, i, v)
811 if (!already_processed_vertex_p (processed, v))
812 rdg_flag_vertex_and_dependent (rdg, v, partition, loops, processed);
814 rdg_flag_loop_exits (rdg, loops, partition, processed);
816 BITMAP_FREE (processed);
817 BITMAP_FREE (loops);
818 return partition;
821 /* Free memory for COMPONENTS. */
823 static void
824 free_rdg_components (vec<rdgc> components)
826 int i;
827 rdgc x;
829 FOR_EACH_VEC_ELT (components, i, x)
831 x->vertices.release ();
832 free (x);
835 components.release ();
838 /* Build the COMPONENTS vector with the strongly connected components
839 of RDG in which the STARTING_VERTICES occur. */
841 static void
842 rdg_build_components (struct graph *rdg, vec<int> starting_vertices,
843 vec<rdgc> *components)
845 int i, v;
846 bitmap saved_components = BITMAP_ALLOC (NULL);
847 int n_components = graphds_scc (rdg, NULL);
848 /* ??? Macros cannot process template types with more than one
849 argument, so we need this typedef. */
850 typedef vec<int> vec_int_heap;
851 vec<int> *all_components = XNEWVEC (vec_int_heap, n_components);
853 for (i = 0; i < n_components; i++)
854 all_components[i].create (3);
856 for (i = 0; i < rdg->n_vertices; i++)
857 all_components[rdg->vertices[i].component].safe_push (i);
859 FOR_EACH_VEC_ELT (starting_vertices, i, v)
861 int c = rdg->vertices[v].component;
863 if (bitmap_set_bit (saved_components, c))
865 rdgc x = XCNEW (struct rdg_component);
866 x->num = c;
867 x->vertices = all_components[c];
869 components->safe_push (x);
873 for (i = 0; i < n_components; i++)
874 if (!bitmap_bit_p (saved_components, i))
875 all_components[i].release ();
877 free (all_components);
878 BITMAP_FREE (saved_components);
881 /* Classifies the builtin kind we can generate for PARTITION of RDG and LOOP.
882 For the moment we detect only the memset zero pattern. */
884 static void
885 classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
887 bitmap_iterator bi;
888 unsigned i;
889 tree nb_iter;
890 data_reference_p single_load, single_store;
891 bool volatiles_p = false;
893 partition->kind = PKIND_NORMAL;
894 partition->main_dr = NULL;
895 partition->secondary_dr = NULL;
897 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
899 gimple stmt = RDG_STMT (rdg, i);
901 if (gimple_has_volatile_ops (stmt))
902 volatiles_p = true;
904 /* If the stmt has uses outside of the loop fail.
905 ??? If the stmt is generated in another partition that
906 is not created as builtin we can ignore this. */
907 if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
909 if (dump_file && (dump_flags & TDF_DETAILS))
910 fprintf (dump_file, "not generating builtin, partition has "
911 "scalar uses outside of the loop\n");
912 partition->kind = PKIND_REDUCTION;
913 return;
917 /* Perform general partition disqualification for builtins. */
918 if (volatiles_p
919 || !flag_tree_loop_distribute_patterns)
920 return;
922 nb_iter = number_of_exit_cond_executions (loop);
923 if (!nb_iter || nb_iter == chrec_dont_know)
924 return;
926 /* Detect memset and memcpy. */
927 single_load = NULL;
928 single_store = NULL;
929 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
931 gimple stmt = RDG_STMT (rdg, i);
932 data_reference_p dr;
933 unsigned j;
935 if (gimple_code (stmt) == GIMPLE_PHI)
936 continue;
938 /* Any scalar stmts are ok. */
939 if (!gimple_vuse (stmt))
940 continue;
942 /* Otherwise just regular loads/stores. */
943 if (!gimple_assign_single_p (stmt))
944 return;
946 /* But exactly one store and/or load. */
947 for (j = 0; RDG_DATAREFS (rdg, i).iterate (j, &dr); ++j)
949 if (DR_IS_READ (dr))
951 if (single_load != NULL)
952 return;
953 single_load = dr;
955 else
957 if (single_store != NULL)
958 return;
959 single_store = dr;
964 if (single_store && !single_load)
966 gimple stmt = DR_STMT (single_store);
967 tree rhs = gimple_assign_rhs1 (stmt);
968 if (const_with_all_bytes_same (rhs) == -1
969 && (!INTEGRAL_TYPE_P (TREE_TYPE (rhs))
970 || (TYPE_MODE (TREE_TYPE (rhs))
971 != TYPE_MODE (unsigned_char_type_node))))
972 return;
973 if (TREE_CODE (rhs) == SSA_NAME
974 && !SSA_NAME_IS_DEFAULT_DEF (rhs)
975 && flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
976 return;
977 if (!adjacent_dr_p (single_store))
978 return;
979 partition->kind = PKIND_MEMSET;
980 partition->main_dr = single_store;
982 else if (single_store && single_load)
984 gimple store = DR_STMT (single_store);
985 gimple load = DR_STMT (single_load);
986 /* Direct aggregate copy or via an SSA name temporary. */
987 if (load != store
988 && gimple_assign_lhs (load) != gimple_assign_rhs1 (store))
989 return;
990 if (!adjacent_dr_p (single_store)
991 || !adjacent_dr_p (single_load)
992 || !operand_equal_p (DR_STEP (single_store),
993 DR_STEP (single_load), 0))
994 return;
995 /* Now check that if there is a dependence this dependence is
996 of a suitable form for memmove. */
997 vec<loop_p> loops = vNULL;
998 ddr_p ddr;
999 loops.safe_push (loop);
1000 ddr = initialize_data_dependence_relation (single_load, single_store,
1001 loops);
1002 compute_affine_dependence (ddr, loop);
1003 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
1005 free_dependence_relation (ddr);
1006 loops.release ();
1007 return;
1009 if (DDR_ARE_DEPENDENT (ddr) != chrec_known)
1011 if (DDR_NUM_DIST_VECTS (ddr) == 0)
1013 free_dependence_relation (ddr);
1014 loops.release ();
1015 return;
1017 lambda_vector dist_v;
1018 FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v)
1020 int dist = dist_v[index_in_loop_nest (loop->num,
1021 DDR_LOOP_NEST (ddr))];
1022 if (dist > 0 && !DDR_REVERSED_P (ddr))
1024 free_dependence_relation (ddr);
1025 loops.release ();
1026 return;
1030 free_dependence_relation (ddr);
1031 loops.release ();
1032 partition->kind = PKIND_MEMCPY;
1033 partition->main_dr = single_store;
1034 partition->secondary_dr = single_load;
1038 /* For a data reference REF, return the declaration of its base
1039 address or NULL_TREE if the base is not determined. */
1041 static tree
1042 ref_base_address (data_reference_p dr)
1044 tree base_address = DR_BASE_ADDRESS (dr);
1045 if (base_address
1046 && TREE_CODE (base_address) == ADDR_EXPR)
1047 return TREE_OPERAND (base_address, 0);
1049 return base_address;
1052 /* Returns true when PARTITION1 and PARTITION2 have similar memory
1053 accesses in RDG. */
1055 static bool
1056 similar_memory_accesses (struct graph *rdg, partition_t partition1,
1057 partition_t partition2)
1059 unsigned i, j, k, l;
1060 bitmap_iterator bi, bj;
1061 data_reference_p ref1, ref2;
1063 /* First check whether in the intersection of the two partitions are
1064 any loads or stores. Common loads are the situation that happens
1065 most often. */
1066 EXECUTE_IF_AND_IN_BITMAP (partition1->stmts, partition2->stmts, 0, i, bi)
1067 if (RDG_MEM_WRITE_STMT (rdg, i)
1068 || RDG_MEM_READS_STMT (rdg, i))
1069 return true;
1071 /* Then check all data-references against each other. */
1072 EXECUTE_IF_SET_IN_BITMAP (partition1->stmts, 0, i, bi)
1073 if (RDG_MEM_WRITE_STMT (rdg, i)
1074 || RDG_MEM_READS_STMT (rdg, i))
1075 EXECUTE_IF_SET_IN_BITMAP (partition2->stmts, 0, j, bj)
1076 if (RDG_MEM_WRITE_STMT (rdg, j)
1077 || RDG_MEM_READS_STMT (rdg, j))
1079 FOR_EACH_VEC_ELT (RDG_DATAREFS (rdg, i), k, ref1)
1081 tree base1 = ref_base_address (ref1);
1082 if (base1)
1083 FOR_EACH_VEC_ELT (RDG_DATAREFS (rdg, j), l, ref2)
1084 if (base1 == ref_base_address (ref2))
1085 return true;
1089 return false;
1092 /* Aggregate several components into a useful partition that is
1093 registered in the PARTITIONS vector. Partitions will be
1094 distributed in different loops. */
1096 static void
1097 rdg_build_partitions (struct graph *rdg, vec<rdgc> components,
1098 vec<int> *other_stores,
1099 vec<partition_t> *partitions, bitmap processed)
1101 int i;
1102 rdgc x;
1103 partition_t partition = partition_alloc (NULL);
1105 FOR_EACH_VEC_ELT (components, i, x)
1107 partition_t np;
1108 int v = x->vertices[0];
1110 if (bitmap_bit_p (processed, v))
1111 continue;
1113 np = build_rdg_partition_for_component (rdg, x);
1114 bitmap_ior_into (partition->stmts, np->stmts);
1115 partition->has_writes = partition_has_writes (np);
1116 bitmap_ior_into (processed, np->stmts);
1117 partition_free (np);
1119 if (partition_has_writes (partition))
1121 if (dump_file && (dump_flags & TDF_DETAILS))
1123 fprintf (dump_file, "ldist useful partition:\n");
1124 dump_bitmap (dump_file, partition->stmts);
1127 partitions->safe_push (partition);
1128 partition = partition_alloc (NULL);
1132 /* Add the nodes from the RDG that were not marked as processed, and
1133 that are used outside the current loop. These are scalar
1134 computations that are not yet part of previous partitions. */
1135 for (i = 0; i < rdg->n_vertices; i++)
1136 if (!bitmap_bit_p (processed, i)
1137 && rdg_defs_used_in_other_loops_p (rdg, i))
1138 other_stores->safe_push (i);
1140 /* If there are still statements left in the OTHER_STORES array,
1141 create other components and partitions with these stores and
1142 their dependences. */
1143 if (other_stores->length () > 0)
1145 vec<rdgc> comps;
1146 comps.create (3);
1147 vec<int> foo;
1148 foo.create (3);
1150 rdg_build_components (rdg, *other_stores, &comps);
1151 rdg_build_partitions (rdg, comps, &foo, partitions, processed);
1153 foo.release ();
1154 free_rdg_components (comps);
1157 /* If there is something left in the last partition, save it. */
1158 if (bitmap_count_bits (partition->stmts) > 0)
1159 partitions->safe_push (partition);
1160 else
1161 partition_free (partition);
1164 /* Dump to FILE the PARTITIONS. */
1166 static void
1167 dump_rdg_partitions (FILE *file, vec<partition_t> partitions)
1169 int i;
1170 partition_t partition;
1172 FOR_EACH_VEC_ELT (partitions, i, partition)
1173 debug_bitmap_file (file, partition->stmts);
1176 /* Debug PARTITIONS. */
1177 extern void debug_rdg_partitions (vec<partition_t> );
1179 DEBUG_FUNCTION void
1180 debug_rdg_partitions (vec<partition_t> partitions)
1182 dump_rdg_partitions (stderr, partitions);
1185 /* Returns the number of read and write operations in the RDG. */
1187 static int
1188 number_of_rw_in_rdg (struct graph *rdg)
1190 int i, res = 0;
1192 for (i = 0; i < rdg->n_vertices; i++)
1194 if (RDG_MEM_WRITE_STMT (rdg, i))
1195 ++res;
1197 if (RDG_MEM_READS_STMT (rdg, i))
1198 ++res;
1201 return res;
1204 /* Returns the number of read and write operations in a PARTITION of
1205 the RDG. */
1207 static int
1208 number_of_rw_in_partition (struct graph *rdg, partition_t partition)
1210 int res = 0;
1211 unsigned i;
1212 bitmap_iterator ii;
1214 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, ii)
1216 if (RDG_MEM_WRITE_STMT (rdg, i))
1217 ++res;
1219 if (RDG_MEM_READS_STMT (rdg, i))
1220 ++res;
1223 return res;
1226 /* Returns true when one of the PARTITIONS contains all the read or
1227 write operations of RDG. */
1229 static bool
1230 partition_contains_all_rw (struct graph *rdg,
1231 vec<partition_t> partitions)
1233 int i;
1234 partition_t partition;
1235 int nrw = number_of_rw_in_rdg (rdg);
1237 FOR_EACH_VEC_ELT (partitions, i, partition)
1238 if (nrw == number_of_rw_in_partition (rdg, partition))
1239 return true;
1241 return false;
1244 /* Generate code from STARTING_VERTICES in RDG. Returns the number of
1245 distributed loops. */
1247 static int
1248 ldist_gen (struct loop *loop, struct graph *rdg,
1249 vec<int> starting_vertices)
1251 int i, nbp;
1252 vec<rdgc> components;
1253 components.create (3);
1254 vec<partition_t> partitions;
1255 partitions.create (3);
1256 vec<int> other_stores;
1257 other_stores.create (3);
1258 partition_t partition;
1259 bitmap processed = BITMAP_ALLOC (NULL);
1260 bool any_builtin;
1262 remaining_stmts = BITMAP_ALLOC (NULL);
1263 upstream_mem_writes = BITMAP_ALLOC (NULL);
1265 for (i = 0; i < rdg->n_vertices; i++)
1267 bitmap_set_bit (remaining_stmts, i);
1269 /* Save in OTHER_STORES all the memory writes that are not in
1270 STARTING_VERTICES. */
1271 if (RDG_MEM_WRITE_STMT (rdg, i))
1273 int v;
1274 unsigned j;
1275 bool found = false;
1277 FOR_EACH_VEC_ELT (starting_vertices, j, v)
1278 if (i == v)
1280 found = true;
1281 break;
1284 if (!found)
1285 other_stores.safe_push (i);
1289 mark_nodes_having_upstream_mem_writes (rdg);
1290 rdg_build_components (rdg, starting_vertices, &components);
1291 rdg_build_partitions (rdg, components, &other_stores, &partitions,
1292 processed);
1293 BITMAP_FREE (processed);
1295 any_builtin = false;
1296 FOR_EACH_VEC_ELT (partitions, i, partition)
1298 classify_partition (loop, rdg, partition);
1299 any_builtin |= partition_builtin_p (partition);
1302 /* If we are only distributing patterns fuse all partitions that
1303 were not properly classified as builtins. Else fuse partitions
1304 with similar memory accesses. */
1305 if (!flag_tree_loop_distribution)
1307 partition_t into;
1308 /* If we did not detect any builtin simply bail out. */
1309 if (!any_builtin)
1311 nbp = 0;
1312 goto ldist_done;
1314 /* Only fuse adjacent non-builtin partitions, see PR53616.
1315 ??? Use dependence information to improve partition ordering. */
1316 i = 0;
1319 for (; partitions.iterate (i, &into); ++i)
1320 if (!partition_builtin_p (into))
1321 break;
1322 for (++i; partitions.iterate (i, &partition); ++i)
1323 if (!partition_builtin_p (partition))
1325 bitmap_ior_into (into->stmts, partition->stmts);
1326 if (partition->kind == PKIND_REDUCTION)
1327 into->kind = PKIND_REDUCTION;
1328 partitions.ordered_remove (i);
1329 partition_free (partition);
1330 i--;
1332 else
1333 break;
1335 while ((unsigned) i < partitions.length ());
1337 else
1339 partition_t into;
1340 int j;
1341 for (i = 0; partitions.iterate (i, &into); ++i)
1343 if (partition_builtin_p (into))
1344 continue;
1345 for (j = i + 1;
1346 partitions.iterate (j, &partition); ++j)
1348 if (!partition_builtin_p (partition)
1349 /* ??? The following is horribly inefficient,
1350 we are re-computing and analyzing data-references
1351 of the stmts in the partitions all the time. */
1352 && similar_memory_accesses (rdg, into, partition))
1354 if (dump_file && (dump_flags & TDF_DETAILS))
1356 fprintf (dump_file, "fusing partitions\n");
1357 dump_bitmap (dump_file, into->stmts);
1358 dump_bitmap (dump_file, partition->stmts);
1359 fprintf (dump_file, "because they have similar "
1360 "memory accesses\n");
1362 bitmap_ior_into (into->stmts, partition->stmts);
1363 if (partition->kind == PKIND_REDUCTION)
1364 into->kind = PKIND_REDUCTION;
1365 partitions.ordered_remove (j);
1366 partition_free (partition);
1367 j--;
1373 /* Fuse all reduction partitions into the last. */
1374 if (partitions.length () > 1)
1376 partition_t into = partitions.last ();
1377 for (i = partitions.length () - 2; i >= 0; --i)
1379 partition_t what = partitions[i];
1380 if (what->kind == PKIND_REDUCTION)
1382 if (dump_file && (dump_flags & TDF_DETAILS))
1384 fprintf (dump_file, "fusing partitions\n");
1385 dump_bitmap (dump_file, into->stmts);
1386 dump_bitmap (dump_file, what->stmts);
1387 fprintf (dump_file, "because the latter has reductions\n");
1389 bitmap_ior_into (into->stmts, what->stmts);
1390 into->kind = PKIND_REDUCTION;
1391 partitions.ordered_remove (i);
1392 partition_free (what);
1397 nbp = partitions.length ();
1398 if (nbp == 0
1399 || (nbp == 1 && !partition_builtin_p (partitions[0]))
1400 || (nbp > 1 && partition_contains_all_rw (rdg, partitions)))
1402 nbp = 0;
1403 goto ldist_done;
1406 if (dump_file && (dump_flags & TDF_DETAILS))
1407 dump_rdg_partitions (dump_file, partitions);
1409 FOR_EACH_VEC_ELT (partitions, i, partition)
1410 generate_code_for_partition (loop, partition, i < nbp - 1);
1412 ldist_done:
1414 BITMAP_FREE (remaining_stmts);
1415 BITMAP_FREE (upstream_mem_writes);
1417 FOR_EACH_VEC_ELT (partitions, i, partition)
1418 partition_free (partition);
1420 other_stores.release ();
1421 partitions.release ();
1422 free_rdg_components (components);
1423 return nbp;
1426 /* Distributes the code from LOOP in such a way that producer
1427 statements are placed before consumer statements. When STMTS is
1428 NULL, performs the maximal distribution, if STMTS is not NULL,
1429 tries to separate only these statements from the LOOP's body.
1430 Returns the number of distributed loops. */
1432 static int
1433 distribute_loop (struct loop *loop, vec<gimple> stmts)
1435 int res = 0;
1436 struct graph *rdg;
1437 gimple s;
1438 unsigned i;
1439 vec<int> vertices;
1440 vec<ddr_p> dependence_relations;
1441 vec<data_reference_p> datarefs;
1442 vec<loop_p> loop_nest;
1444 datarefs.create (10);
1445 dependence_relations.create (100);
1446 loop_nest.create (3);
1447 rdg = build_rdg (loop, &loop_nest, &dependence_relations, &datarefs);
1449 if (!rdg)
1451 if (dump_file && (dump_flags & TDF_DETAILS))
1452 fprintf (dump_file,
1453 "FIXME: Loop %d not distributed: failed to build the RDG.\n",
1454 loop->num);
1456 free_dependence_relations (dependence_relations);
1457 free_data_refs (datarefs);
1458 loop_nest.release ();
1459 return res;
1462 vertices.create (3);
1464 if (dump_file && (dump_flags & TDF_DETAILS))
1465 dump_rdg (dump_file, rdg);
1467 FOR_EACH_VEC_ELT (stmts, i, s)
1469 int v = rdg_vertex_for_stmt (rdg, s);
1471 if (v >= 0)
1473 vertices.safe_push (v);
1475 if (dump_file && (dump_flags & TDF_DETAILS))
1476 fprintf (dump_file,
1477 "ldist asked to generate code for vertex %d\n", v);
1481 res = ldist_gen (loop, rdg, vertices);
1482 vertices.release ();
1483 free_rdg (rdg);
1484 free_dependence_relations (dependence_relations);
1485 free_data_refs (datarefs);
1486 loop_nest.release ();
1487 return res;
1490 /* Distribute all loops in the current function. */
1492 static unsigned int
1493 tree_loop_distribution (void)
1495 struct loop *loop;
1496 loop_iterator li;
1497 bool changed = false;
1498 basic_block bb;
1500 FOR_ALL_BB (bb)
1502 gimple_stmt_iterator gsi;
1503 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1504 gimple_set_uid (gsi_stmt (gsi), -1);
1505 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1506 gimple_set_uid (gsi_stmt (gsi), -1);
1509 /* We can at the moment only distribute non-nested loops, thus restrict
1510 walking to innermost loops. */
1511 FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
1513 vec<gimple> work_list = vNULL;
1514 basic_block *bbs;
1515 int num = loop->num;
1516 int nb_generated_loops = 0;
1517 unsigned int i;
1519 /* If the loop doesn't have a single exit we will fail anyway,
1520 so do that early. */
1521 if (!single_exit (loop))
1522 continue;
1524 /* Only optimize hot loops. */
1525 if (!optimize_loop_for_speed_p (loop))
1526 continue;
1528 /* Only distribute loops with a header and latch for now. */
1529 if (loop->num_nodes > 2)
1530 continue;
1532 /* Initialize the worklist with stmts we seed the partitions with. */
1533 bbs = get_loop_body_in_dom_order (loop);
1534 for (i = 0; i < loop->num_nodes; ++i)
1536 gimple_stmt_iterator gsi;
1537 for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
1539 gimple stmt = gsi_stmt (gsi);
1540 /* Distribute stmts which have defs that are used outside of
1541 the loop. */
1542 if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
1544 /* Otherwise only distribute stores for now. */
1545 else if (!gimple_assign_single_p (stmt)
1546 || is_gimple_reg (gimple_assign_lhs (stmt)))
1547 continue;
1549 work_list.safe_push (stmt);
1552 free (bbs);
1554 if (work_list.length () > 0)
1555 nb_generated_loops = distribute_loop (loop, work_list);
1557 if (nb_generated_loops > 0)
1558 changed = true;
1560 if (dump_file && (dump_flags & TDF_DETAILS))
1562 if (nb_generated_loops > 1)
1563 fprintf (dump_file, "Loop %d distributed: split to %d loops.\n",
1564 num, nb_generated_loops);
1565 else
1566 fprintf (dump_file, "Loop %d is the same.\n", num);
1569 work_list.release ();
1572 if (changed)
1574 mark_virtual_operands_for_renaming (cfun);
1575 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
1578 #ifdef ENABLE_CHECKING
1579 verify_loop_structure ();
1580 #endif
1582 return 0;
1585 static bool
1586 gate_tree_loop_distribution (void)
1588 return flag_tree_loop_distribution
1589 || flag_tree_loop_distribute_patterns;
1592 struct gimple_opt_pass pass_loop_distribution =
1595 GIMPLE_PASS,
1596 "ldist", /* name */
1597 OPTGROUP_LOOP, /* optinfo_flags */
1598 gate_tree_loop_distribution, /* gate */
1599 tree_loop_distribution, /* execute */
1600 NULL, /* sub */
1601 NULL, /* next */
1602 0, /* static_pass_number */
1603 TV_TREE_LOOP_DISTRIBUTION, /* tv_id */
1604 PROP_cfg | PROP_ssa, /* properties_required */
1605 0, /* properties_provided */
1606 0, /* properties_destroyed */
1607 0, /* todo_flags_start */
1608 TODO_verify_ssa /* todo_flags_finish */