]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-loop-distribution.c
fix PR68343: disable fuse-*.c tests for isl 0.14 or earlier
[thirdparty/gcc.git] / gcc / tree-loop-distribution.c
CommitLineData
dea61d92 1/* Loop distribution.
818ab71a 2 Copyright (C) 2006-2016 Free Software Foundation, Inc.
dea61d92
SP
3 Contributed by Georges-Andre Silber <Georges-Andre.Silber@ensmp.fr>
4 and Sebastian Pop <sebastian.pop@amd.com>.
5
6This file is part of GCC.
b8698a0f 7
dea61d92
SP
8GCC is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3, or (at your option) any
11later version.
b8698a0f 12
dea61d92
SP
13GCC is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
b8698a0f 17
dea61d92
SP
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22/* This pass performs loop distribution: for example, the loop
23
24 |DO I = 2, N
25 | A(I) = B(I) + C
26 | D(I) = A(I-1)*E
27 |ENDDO
28
b8698a0f 29 is transformed to
dea61d92
SP
30
31 |DOALL I = 2, N
32 | A(I) = B(I) + C
33 |ENDDO
34 |
35 |DOALL I = 2, N
36 | D(I) = A(I-1)*E
37 |ENDDO
38
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. */
43
44#include "config.h"
45#include "system.h"
46#include "coretypes.h"
c7131fb2 47#include "backend.h"
40e23961 48#include "tree.h"
c7131fb2 49#include "gimple.h"
957060b5
AM
50#include "cfghooks.h"
51#include "tree-pass.h"
c7131fb2 52#include "ssa.h"
957060b5 53#include "gimple-pretty-print.h"
c7131fb2 54#include "fold-const.h"
60393bbc 55#include "cfganal.h"
5be5c238 56#include "gimple-iterator.h"
18f429e2 57#include "gimplify-me.h"
d8a2d370 58#include "stor-layout.h"
442b4905 59#include "tree-cfg.h"
e28030cf 60#include "tree-ssa-loop-manip.h"
442b4905
AM
61#include "tree-ssa-loop.h"
62#include "tree-into-ssa.h"
7a300452 63#include "tree-ssa.h"
dea61d92 64#include "cfgloop.h"
dea61d92 65#include "tree-scalar-evolution.h"
826a536d 66#include "tree-vectorizer.h"
80ab0b19
RB
67
68
69/* A Reduced Dependence Graph (RDG) vertex representing a statement. */
526ceb68 70struct rdg_vertex
80ab0b19
RB
71{
72 /* The statement represented by this vertex. */
355fe088 73 gimple *stmt;
80ab0b19
RB
74
75 /* Vector of data-references in this statement. */
76 vec<data_reference_p> datarefs;
77
78 /* True when the statement contains a write to memory. */
79 bool has_mem_write;
80
81 /* True when the statement contains a read from memory. */
82 bool has_mem_reads;
526ceb68 83};
80ab0b19
RB
84
85#define RDGV_STMT(V) ((struct rdg_vertex *) ((V)->data))->stmt
86#define RDGV_DATAREFS(V) ((struct rdg_vertex *) ((V)->data))->datarefs
87#define RDGV_HAS_MEM_WRITE(V) ((struct rdg_vertex *) ((V)->data))->has_mem_write
88#define RDGV_HAS_MEM_READS(V) ((struct rdg_vertex *) ((V)->data))->has_mem_reads
89#define RDG_STMT(RDG, I) RDGV_STMT (&(RDG->vertices[I]))
90#define RDG_DATAREFS(RDG, I) RDGV_DATAREFS (&(RDG->vertices[I]))
91#define RDG_MEM_WRITE_STMT(RDG, I) RDGV_HAS_MEM_WRITE (&(RDG->vertices[I]))
92#define RDG_MEM_READS_STMT(RDG, I) RDGV_HAS_MEM_READS (&(RDG->vertices[I]))
93
94/* Data dependence type. */
95
96enum rdg_dep_type
97{
98 /* Read After Write (RAW). */
99 flow_dd = 'f',
100
36875e8f
RB
101 /* Control dependence (execute conditional on). */
102 control_dd = 'c'
80ab0b19
RB
103};
104
105/* Dependence information attached to an edge of the RDG. */
106
526ceb68 107struct rdg_edge
80ab0b19
RB
108{
109 /* Type of the dependence. */
110 enum rdg_dep_type type;
526ceb68 111};
80ab0b19
RB
112
113#define RDGE_TYPE(E) ((struct rdg_edge *) ((E)->data))->type
80ab0b19 114
80ab0b19
RB
115/* Dump vertex I in RDG to FILE. */
116
117static void
118dump_rdg_vertex (FILE *file, struct graph *rdg, int i)
119{
120 struct vertex *v = &(rdg->vertices[i]);
121 struct graph_edge *e;
122
123 fprintf (file, "(vertex %d: (%s%s) (in:", i,
124 RDG_MEM_WRITE_STMT (rdg, i) ? "w" : "",
125 RDG_MEM_READS_STMT (rdg, i) ? "r" : "");
126
127 if (v->pred)
128 for (e = v->pred; e; e = e->pred_next)
129 fprintf (file, " %d", e->src);
130
131 fprintf (file, ") (out:");
132
133 if (v->succ)
134 for (e = v->succ; e; e = e->succ_next)
135 fprintf (file, " %d", e->dest);
136
137 fprintf (file, ")\n");
138 print_gimple_stmt (file, RDGV_STMT (v), 0, TDF_VOPS|TDF_MEMSYMS);
139 fprintf (file, ")\n");
140}
141
142/* Call dump_rdg_vertex on stderr. */
143
144DEBUG_FUNCTION void
145debug_rdg_vertex (struct graph *rdg, int i)
146{
147 dump_rdg_vertex (stderr, rdg, i);
148}
149
80ab0b19
RB
150/* Dump the reduced dependence graph RDG to FILE. */
151
152static void
153dump_rdg (FILE *file, struct graph *rdg)
154{
80ab0b19 155 fprintf (file, "(rdg\n");
2fd5894f
RB
156 for (int i = 0; i < rdg->n_vertices; i++)
157 dump_rdg_vertex (file, rdg, i);
80ab0b19 158 fprintf (file, ")\n");
80ab0b19
RB
159}
160
161/* Call dump_rdg on stderr. */
162
163DEBUG_FUNCTION void
164debug_rdg (struct graph *rdg)
165{
166 dump_rdg (stderr, rdg);
167}
168
169static void
170dot_rdg_1 (FILE *file, struct graph *rdg)
171{
172 int i;
174ec470
RB
173 pretty_printer buffer;
174 pp_needs_newline (&buffer) = false;
175 buffer.buffer->stream = file;
80ab0b19
RB
176
177 fprintf (file, "digraph RDG {\n");
178
179 for (i = 0; i < rdg->n_vertices; i++)
180 {
181 struct vertex *v = &(rdg->vertices[i]);
182 struct graph_edge *e;
183
174ec470
RB
184 fprintf (file, "%d [label=\"[%d] ", i, i);
185 pp_gimple_stmt_1 (&buffer, RDGV_STMT (v), 0, TDF_SLIM);
186 pp_flush (&buffer);
187 fprintf (file, "\"]\n");
188
80ab0b19
RB
189 /* Highlight reads from memory. */
190 if (RDG_MEM_READS_STMT (rdg, i))
191 fprintf (file, "%d [style=filled, fillcolor=green]\n", i);
192
193 /* Highlight stores to memory. */
194 if (RDG_MEM_WRITE_STMT (rdg, i))
195 fprintf (file, "%d [style=filled, fillcolor=red]\n", i);
196
197 if (v->succ)
198 for (e = v->succ; e; e = e->succ_next)
199 switch (RDGE_TYPE (e))
200 {
80ab0b19
RB
201 case flow_dd:
202 /* These are the most common dependences: don't print these. */
203 fprintf (file, "%d -> %d \n", i, e->dest);
204 break;
205
36875e8f
RB
206 case control_dd:
207 fprintf (file, "%d -> %d [label=control] \n", i, e->dest);
208 break;
209
80ab0b19
RB
210 default:
211 gcc_unreachable ();
212 }
213 }
214
215 fprintf (file, "}\n\n");
216}
217
218/* Display the Reduced Dependence Graph using dotty. */
219
220DEBUG_FUNCTION void
221dot_rdg (struct graph *rdg)
222{
174ec470 223 /* When debugging, you may want to enable the following code. */
b6d94045 224#ifdef HAVE_POPEN
c3284718 225 FILE *file = popen ("dot -Tx11", "w");
174ec470
RB
226 if (!file)
227 return;
80ab0b19 228 dot_rdg_1 (file, rdg);
174ec470
RB
229 fflush (file);
230 close (fileno (file));
231 pclose (file);
80ab0b19
RB
232#else
233 dot_rdg_1 (stderr, rdg);
234#endif
235}
236
237/* Returns the index of STMT in RDG. */
238
239static int
355fe088 240rdg_vertex_for_stmt (struct graph *rdg ATTRIBUTE_UNUSED, gimple *stmt)
80ab0b19
RB
241{
242 int index = gimple_uid (stmt);
243 gcc_checking_assert (index == -1 || RDG_STMT (rdg, index) == stmt);
244 return index;
245}
246
80ab0b19
RB
247/* Creates dependence edges in RDG for all the uses of DEF. IDEF is
248 the index of DEF in RDG. */
249
250static void
251create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef)
252{
253 use_operand_p imm_use_p;
254 imm_use_iterator iterator;
255
256 FOR_EACH_IMM_USE_FAST (imm_use_p, iterator, def)
257 {
258 struct graph_edge *e;
259 int use = rdg_vertex_for_stmt (rdg, USE_STMT (imm_use_p));
260
261 if (use < 0)
262 continue;
263
264 e = add_edge (rdg, idef, use);
265 e->data = XNEW (struct rdg_edge);
266 RDGE_TYPE (e) = flow_dd;
80ab0b19
RB
267 }
268}
269
36875e8f
RB
270/* Creates an edge for the control dependences of BB to the vertex V. */
271
272static void
273create_edge_for_control_dependence (struct graph *rdg, basic_block bb,
274 int v, control_dependences *cd)
275{
276 bitmap_iterator bi;
277 unsigned edge_n;
278 EXECUTE_IF_SET_IN_BITMAP (cd->get_edges_dependent_on (bb->index),
279 0, edge_n, bi)
280 {
281 basic_block cond_bb = cd->get_edge (edge_n)->src;
355fe088 282 gimple *stmt = last_stmt (cond_bb);
36875e8f
RB
283 if (stmt && is_ctrl_stmt (stmt))
284 {
285 struct graph_edge *e;
286 int c = rdg_vertex_for_stmt (rdg, stmt);
287 if (c < 0)
288 continue;
289
290 e = add_edge (rdg, c, v);
291 e->data = XNEW (struct rdg_edge);
292 RDGE_TYPE (e) = control_dd;
36875e8f
RB
293 }
294 }
295}
296
80ab0b19
RB
297/* Creates the edges of the reduced dependence graph RDG. */
298
299static void
447f3223 300create_rdg_flow_edges (struct graph *rdg)
80ab0b19
RB
301{
302 int i;
80ab0b19
RB
303 def_operand_p def_p;
304 ssa_op_iter iter;
305
80ab0b19
RB
306 for (i = 0; i < rdg->n_vertices; i++)
307 FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i),
308 iter, SSA_OP_DEF)
309 create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i);
447f3223 310}
36875e8f 311
447f3223
RB
312/* Creates the edges of the reduced dependence graph RDG. */
313
314static void
315create_rdg_cd_edges (struct graph *rdg, control_dependences *cd)
316{
317 int i;
318
319 for (i = 0; i < rdg->n_vertices; i++)
320 {
355fe088 321 gimple *stmt = RDG_STMT (rdg, i);
447f3223
RB
322 if (gimple_code (stmt) == GIMPLE_PHI)
323 {
324 edge_iterator ei;
325 edge e;
326 FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
36875e8f 327 create_edge_for_control_dependence (rdg, e->src, i, cd);
447f3223
RB
328 }
329 else
330 create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd);
331 }
80ab0b19
RB
332}
333
334/* Build the vertices of the reduced dependence graph RDG. Return false
335 if that failed. */
336
337static bool
355fe088 338create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts, loop_p loop,
80ab0b19
RB
339 vec<data_reference_p> *datarefs)
340{
341 int i;
355fe088 342 gimple *stmt;
80ab0b19
RB
343
344 FOR_EACH_VEC_ELT (stmts, i, stmt)
345 {
346 struct vertex *v = &(rdg->vertices[i]);
347
348 /* Record statement to vertex mapping. */
349 gimple_set_uid (stmt, i);
350
351 v->data = XNEW (struct rdg_vertex);
352 RDGV_STMT (v) = stmt;
353 RDGV_DATAREFS (v).create (0);
354 RDGV_HAS_MEM_WRITE (v) = false;
355 RDGV_HAS_MEM_READS (v) = false;
356 if (gimple_code (stmt) == GIMPLE_PHI)
357 continue;
358
359 unsigned drp = datarefs->length ();
360 if (!find_data_references_in_stmt (loop, stmt, datarefs))
361 return false;
362 for (unsigned j = drp; j < datarefs->length (); ++j)
363 {
364 data_reference_p dr = (*datarefs)[j];
365 if (DR_IS_READ (dr))
366 RDGV_HAS_MEM_READS (v) = true;
367 else
368 RDGV_HAS_MEM_WRITE (v) = true;
369 RDGV_DATAREFS (v).safe_push (dr);
370 }
371 }
372 return true;
373}
374
2fd5894f 375/* Initialize STMTS with all the statements of LOOP. The order in
80ab0b19
RB
376 which we discover statements is important as
377 generate_loops_for_partition is using the same traversal for
2fd5894f 378 identifying statements in loop copies. */
80ab0b19
RB
379
380static void
355fe088 381stmts_from_loop (struct loop *loop, vec<gimple *> *stmts)
80ab0b19
RB
382{
383 unsigned int i;
384 basic_block *bbs = get_loop_body_in_dom_order (loop);
385
386 for (i = 0; i < loop->num_nodes; i++)
387 {
388 basic_block bb = bbs[i];
80ab0b19 389
538dd0b7
DM
390 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
391 gsi_next (&bsi))
392 if (!virtual_operand_p (gimple_phi_result (bsi.phi ())))
393 stmts->safe_push (bsi.phi ());
80ab0b19 394
538dd0b7
DM
395 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
396 gsi_next (&bsi))
80ab0b19 397 {
355fe088 398 gimple *stmt = gsi_stmt (bsi);
80ab0b19
RB
399 if (gimple_code (stmt) != GIMPLE_LABEL && !is_gimple_debug (stmt))
400 stmts->safe_push (stmt);
401 }
402 }
403
404 free (bbs);
405}
406
80ab0b19
RB
407/* Free the reduced dependence graph RDG. */
408
409static void
410free_rdg (struct graph *rdg)
411{
412 int i;
413
414 for (i = 0; i < rdg->n_vertices; i++)
415 {
416 struct vertex *v = &(rdg->vertices[i]);
417 struct graph_edge *e;
418
419 for (e = v->succ; e; e = e->succ_next)
447f3223 420 free (e->data);
80ab0b19
RB
421
422 if (v->data)
423 {
424 gimple_set_uid (RDGV_STMT (v), -1);
425 free_data_refs (RDGV_DATAREFS (v));
426 free (v->data);
427 }
428 }
429
430 free_graph (rdg);
431}
432
433/* Build the Reduced Dependence Graph (RDG) with one vertex per
97463b2b 434 statement of the loop nest LOOP_NEST, and one edge per data dependence or
80ab0b19
RB
435 scalar dependence. */
436
437static struct graph *
36875e8f 438build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
80ab0b19
RB
439{
440 struct graph *rdg;
80ab0b19 441 vec<data_reference_p> datarefs;
80ab0b19 442
97463b2b 443 /* Create the RDG vertices from the stmts of the loop nest. */
355fe088 444 auto_vec<gimple *, 10> stmts;
97463b2b 445 stmts_from_loop (loop_nest[0], &stmts);
24f161fd 446 rdg = new_graph (stmts.length ());
80ab0b19 447 datarefs.create (10);
97463b2b 448 if (!create_rdg_vertices (rdg, stmts, loop_nest[0], &datarefs))
80ab0b19 449 {
97463b2b 450 datarefs.release ();
80ab0b19
RB
451 free_rdg (rdg);
452 return NULL;
453 }
454 stmts.release ();
97463b2b 455
447f3223
RB
456 create_rdg_flow_edges (rdg);
457 if (cd)
458 create_rdg_cd_edges (rdg, cd);
459
97463b2b 460 datarefs.release ();
80ab0b19
RB
461
462 return rdg;
463}
464
80ab0b19 465
dea61d92 466
b9fc0497 467enum partition_kind {
826a536d 468 PKIND_NORMAL, PKIND_MEMSET, PKIND_MEMCPY
b9fc0497 469};
30d55936 470
526ceb68 471struct partition
c61f8985
RG
472{
473 bitmap stmts;
80ab0b19 474 bitmap loops;
826a536d 475 bool reduction_p;
30d55936 476 enum partition_kind kind;
d0582dc1
RG
477 /* data-references a kind != PKIND_NORMAL partition is about. */
478 data_reference_p main_dr;
479 data_reference_p secondary_dr;
818625cf 480 tree niter;
d995e887 481 bool plus_one;
526ceb68 482};
c61f8985 483
c61f8985
RG
484
485/* Allocate and initialize a partition from BITMAP. */
486
526ceb68 487static partition *
80ab0b19 488partition_alloc (bitmap stmts, bitmap loops)
c61f8985 489{
526ceb68 490 partition *partition = XCNEW (struct partition);
c61f8985 491 partition->stmts = stmts ? stmts : BITMAP_ALLOC (NULL);
80ab0b19 492 partition->loops = loops ? loops : BITMAP_ALLOC (NULL);
826a536d 493 partition->reduction_p = false;
30d55936 494 partition->kind = PKIND_NORMAL;
c61f8985
RG
495 return partition;
496}
497
498/* Free PARTITION. */
499
500static void
526ceb68 501partition_free (partition *partition)
c61f8985
RG
502{
503 BITMAP_FREE (partition->stmts);
80ab0b19 504 BITMAP_FREE (partition->loops);
c61f8985
RG
505 free (partition);
506}
507
30d55936
RG
508/* Returns true if the partition can be generated as a builtin. */
509
510static bool
526ceb68 511partition_builtin_p (partition *partition)
30d55936 512{
826a536d 513 return partition->kind != PKIND_NORMAL;
30d55936 514}
c61f8985 515
826a536d 516/* Returns true if the partition contains a reduction. */
7ad672e4
RG
517
518static bool
526ceb68 519partition_reduction_p (partition *partition)
7ad672e4 520{
826a536d 521 return partition->reduction_p;
7ad672e4
RG
522}
523
826a536d
RB
524/* Merge PARTITION into the partition DEST. */
525
526static void
526ceb68 527partition_merge_into (partition *dest, partition *partition)
826a536d
RB
528{
529 dest->kind = PKIND_NORMAL;
530 bitmap_ior_into (dest->stmts, partition->stmts);
531 if (partition_reduction_p (partition))
532 dest->reduction_p = true;
533}
534
535
c07a8cb3
RG
536/* Returns true when DEF is an SSA_NAME defined in LOOP and used after
537 the LOOP. */
538
539static bool
540ssa_name_has_uses_outside_loop_p (tree def, loop_p loop)
541{
542 imm_use_iterator imm_iter;
543 use_operand_p use_p;
544
545 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def)
e665269a 546 {
355fe088 547 gimple *use_stmt = USE_STMT (use_p);
e665269a
RG
548 if (!is_gimple_debug (use_stmt)
549 && loop != loop_containing_stmt (use_stmt))
550 return true;
551 }
c07a8cb3
RG
552
553 return false;
554}
555
556/* Returns true when STMT defines a scalar variable used after the
88af7c1a 557 loop LOOP. */
c07a8cb3
RG
558
559static bool
355fe088 560stmt_has_scalar_dependences_outside_loop (loop_p loop, gimple *stmt)
c07a8cb3 561{
88af7c1a
RG
562 def_operand_p def_p;
563 ssa_op_iter op_iter;
c07a8cb3 564
9ca86fc3
RG
565 if (gimple_code (stmt) == GIMPLE_PHI)
566 return ssa_name_has_uses_outside_loop_p (gimple_phi_result (stmt), loop);
567
88af7c1a
RG
568 FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
569 if (ssa_name_has_uses_outside_loop_p (DEF_FROM_PTR (def_p), loop))
570 return true;
c07a8cb3 571
88af7c1a 572 return false;
c07a8cb3
RG
573}
574
dea61d92
SP
575/* Return a copy of LOOP placed before LOOP. */
576
577static struct loop *
578copy_loop_before (struct loop *loop)
579{
580 struct loop *res;
581 edge preheader = loop_preheader_edge (loop);
582
dea61d92 583 initialize_original_copy_tables ();
5ce9450f 584 res = slpeel_tree_duplicate_loop_to_edge_cfg (loop, NULL, preheader);
30d55936 585 gcc_assert (res != NULL);
dea61d92 586 free_original_copy_tables ();
2cfc56b9 587 delete_update_ssa ();
dea61d92
SP
588
589 return res;
590}
591
592/* Creates an empty basic block after LOOP. */
593
594static void
595create_bb_after_loop (struct loop *loop)
596{
597 edge exit = single_exit (loop);
598
599 if (!exit)
600 return;
601
602 split_edge (exit);
603}
604
605/* Generate code for PARTITION from the code in LOOP. The loop is
606 copied when COPY_P is true. All the statements not flagged in the
607 PARTITION bitmap are removed from the loop or from its copy. The
608 statements are indexed in sequence inside a basic block, and the
30d55936 609 basic blocks of a loop are taken in dom order. */
dea61d92 610
30d55936 611static void
526ceb68 612generate_loops_for_partition (struct loop *loop, partition *partition,
c61f8985 613 bool copy_p)
dea61d92 614{
2fd5894f 615 unsigned i;
dea61d92
SP
616 basic_block *bbs;
617
618 if (copy_p)
619 {
620 loop = copy_loop_before (loop);
30d55936 621 gcc_assert (loop != NULL);
dea61d92
SP
622 create_preheader (loop, CP_SIMPLE_PREHEADERS);
623 create_bb_after_loop (loop);
624 }
625
2fd5894f 626 /* Remove stmts not in the PARTITION bitmap. */
dea61d92
SP
627 bbs = get_loop_body_in_dom_order (loop);
628
b03c3082 629 if (MAY_HAVE_DEBUG_STMTS)
2fd5894f 630 for (i = 0; i < loop->num_nodes; i++)
b03c3082
JJ
631 {
632 basic_block bb = bbs[i];
633
538dd0b7
DM
634 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
635 gsi_next (&bsi))
2fd5894f 636 {
538dd0b7 637 gphi *phi = bsi.phi ();
2fd5894f
RB
638 if (!virtual_operand_p (gimple_phi_result (phi))
639 && !bitmap_bit_p (partition->stmts, gimple_uid (phi)))
640 reset_debug_uses (phi);
641 }
b03c3082 642
538dd0b7 643 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
b03c3082 644 {
355fe088 645 gimple *stmt = gsi_stmt (bsi);
b03c3082
JJ
646 if (gimple_code (stmt) != GIMPLE_LABEL
647 && !is_gimple_debug (stmt)
2fd5894f 648 && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
b03c3082
JJ
649 reset_debug_uses (stmt);
650 }
651 }
652
2fd5894f 653 for (i = 0; i < loop->num_nodes; i++)
dea61d92
SP
654 {
655 basic_block bb = bbs[i];
dea61d92 656
538dd0b7 657 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);)
2fd5894f 658 {
538dd0b7 659 gphi *phi = bsi.phi ();
2fd5894f
RB
660 if (!virtual_operand_p (gimple_phi_result (phi))
661 && !bitmap_bit_p (partition->stmts, gimple_uid (phi)))
2706a615 662 remove_phi_node (&bsi, true);
2fd5894f
RB
663 else
664 gsi_next (&bsi);
665 }
dea61d92 666
538dd0b7 667 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);)
2706a615 668 {
355fe088 669 gimple *stmt = gsi_stmt (bsi);
b03c3082
JJ
670 if (gimple_code (stmt) != GIMPLE_LABEL
671 && !is_gimple_debug (stmt)
2fd5894f 672 && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
2706a615 673 {
36875e8f
RB
674 /* Choose an arbitrary path through the empty CFG part
675 that this unnecessary control stmt controls. */
538dd0b7 676 if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
36875e8f 677 {
538dd0b7 678 gimple_cond_make_false (cond_stmt);
36875e8f
RB
679 update_stmt (stmt);
680 }
681 else if (gimple_code (stmt) == GIMPLE_SWITCH)
682 {
538dd0b7 683 gswitch *switch_stmt = as_a <gswitch *> (stmt);
36875e8f 684 gimple_switch_set_index
538dd0b7 685 (switch_stmt, CASE_LOW (gimple_switch_label (switch_stmt, 1)));
36875e8f
RB
686 update_stmt (stmt);
687 }
688 else
689 {
690 unlink_stmt_vdef (stmt);
691 gsi_remove (&bsi, true);
692 release_defs (stmt);
693 continue;
694 }
2706a615 695 }
36875e8f 696 gsi_next (&bsi);
2706a615 697 }
dea61d92
SP
698 }
699
700 free (bbs);
dea61d92
SP
701}
702
d0582dc1 703/* Build the size argument for a memory operation call. */
3661e899 704
d0582dc1 705static tree
d995e887
RB
706build_size_arg_loc (location_t loc, data_reference_p dr, tree nb_iter,
707 bool plus_one)
3661e899 708{
d995e887
RB
709 tree size = fold_convert_loc (loc, sizetype, nb_iter);
710 if (plus_one)
711 size = size_binop (PLUS_EXPR, size, size_one_node);
712 size = fold_build2_loc (loc, MULT_EXPR, sizetype, size,
d0582dc1 713 TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
d995e887
RB
714 size = fold_convert_loc (loc, size_type_node, size);
715 return size;
d0582dc1
RG
716}
717
718/* Build an address argument for a memory operation call. */
719
720static tree
721build_addr_arg_loc (location_t loc, data_reference_p dr, tree nb_bytes)
722{
723 tree addr_base;
724
725 addr_base = size_binop_loc (loc, PLUS_EXPR, DR_OFFSET (dr), DR_INIT (dr));
726 addr_base = fold_convert_loc (loc, sizetype, addr_base);
727
728 /* Test for a negative stride, iterating over every element. */
729 if (tree_int_cst_sgn (DR_STEP (dr)) == -1)
730 {
731 addr_base = size_binop_loc (loc, MINUS_EXPR, addr_base,
732 fold_convert_loc (loc, sizetype, nb_bytes));
733 addr_base = size_binop_loc (loc, PLUS_EXPR, addr_base,
734 TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
735 }
736
737 return fold_build_pointer_plus_loc (loc, DR_BASE_ADDRESS (dr), addr_base);
3661e899
TB
738}
739
401f3a81
JJ
740/* If VAL memory representation contains the same value in all bytes,
741 return that value, otherwise return -1.
742 E.g. for 0x24242424 return 0x24, for IEEE double
743 747708026454360457216.0 return 0x44, etc. */
744
745static int
746const_with_all_bytes_same (tree val)
747{
748 unsigned char buf[64];
749 int i, len;
750
751 if (integer_zerop (val)
752 || real_zerop (val)
753 || (TREE_CODE (val) == CONSTRUCTOR
754 && !TREE_CLOBBER_P (val)
755 && CONSTRUCTOR_NELTS (val) == 0))
756 return 0;
757
758 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
759 return -1;
760
761 len = native_encode_expr (val, buf, sizeof (buf));
762 if (len == 0)
763 return -1;
764 for (i = 1; i < len; i++)
765 if (buf[i] != buf[0])
766 return -1;
767 return buf[0];
768}
769
30d55936 770/* Generate a call to memset for PARTITION in LOOP. */
dea61d92 771
cfee318d 772static void
526ceb68 773generate_memset_builtin (struct loop *loop, partition *partition)
dea61d92 774{
30d55936 775 gimple_stmt_iterator gsi;
355fe088 776 gimple *stmt, *fn_call;
818625cf 777 tree mem, fn, nb_bytes;
30d55936 778 location_t loc;
b6dd5261 779 tree val;
30d55936 780
d0582dc1 781 stmt = DR_STMT (partition->main_dr);
30d55936 782 loc = gimple_location (stmt);
30d55936
RG
783
784 /* The new statements will be placed before LOOP. */
785 gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
dea61d92 786
d995e887
RB
787 nb_bytes = build_size_arg_loc (loc, partition->main_dr, partition->niter,
788 partition->plus_one);
d0582dc1
RG
789 nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
790 false, GSI_CONTINUE_LINKING);
791 mem = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
792 mem = force_gimple_operand_gsi (&gsi, mem, true, NULL_TREE,
793 false, GSI_CONTINUE_LINKING);
dea61d92 794
b6dd5261
RG
795 /* This exactly matches the pattern recognition in classify_partition. */
796 val = gimple_assign_rhs1 (stmt);
401f3a81
JJ
797 /* Handle constants like 0x15151515 and similarly
798 floating point constants etc. where all bytes are the same. */
799 int bytev = const_with_all_bytes_same (val);
800 if (bytev != -1)
801 val = build_int_cst (integer_type_node, bytev);
802 else if (TREE_CODE (val) == INTEGER_CST)
803 val = fold_convert (integer_type_node, val);
804 else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val)))
b6dd5261 805 {
b731b390 806 tree tem = make_ssa_name (integer_type_node);
355fe088 807 gimple *cstmt = gimple_build_assign (tem, NOP_EXPR, val);
401f3a81
JJ
808 gsi_insert_after (&gsi, cstmt, GSI_CONTINUE_LINKING);
809 val = tem;
b6dd5261
RG
810 }
811
e79983f4 812 fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
b6dd5261 813 fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes);
d0582dc1 814 gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
dea61d92
SP
815
816 if (dump_file && (dump_flags & TDF_DETAILS))
b6dd5261
RG
817 {
818 fprintf (dump_file, "generated memset");
401f3a81 819 if (bytev == 0)
b6dd5261 820 fprintf (dump_file, " zero\n");
b6dd5261
RG
821 else
822 fprintf (dump_file, "\n");
823 }
dea61d92
SP
824}
825
d0582dc1
RG
826/* Generate a call to memcpy for PARTITION in LOOP. */
827
828static void
526ceb68 829generate_memcpy_builtin (struct loop *loop, partition *partition)
d0582dc1
RG
830{
831 gimple_stmt_iterator gsi;
355fe088 832 gimple *stmt, *fn_call;
818625cf 833 tree dest, src, fn, nb_bytes;
d0582dc1
RG
834 location_t loc;
835 enum built_in_function kind;
836
837 stmt = DR_STMT (partition->main_dr);
838 loc = gimple_location (stmt);
d0582dc1
RG
839
840 /* The new statements will be placed before LOOP. */
841 gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
842
d995e887
RB
843 nb_bytes = build_size_arg_loc (loc, partition->main_dr, partition->niter,
844 partition->plus_one);
d0582dc1
RG
845 nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
846 false, GSI_CONTINUE_LINKING);
847 dest = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
848 src = build_addr_arg_loc (loc, partition->secondary_dr, nb_bytes);
849 if (ptr_derefs_may_alias_p (dest, src))
850 kind = BUILT_IN_MEMMOVE;
851 else
852 kind = BUILT_IN_MEMCPY;
853
854 dest = force_gimple_operand_gsi (&gsi, dest, true, NULL_TREE,
855 false, GSI_CONTINUE_LINKING);
856 src = force_gimple_operand_gsi (&gsi, src, true, NULL_TREE,
857 false, GSI_CONTINUE_LINKING);
858 fn = build_fold_addr_expr (builtin_decl_implicit (kind));
859 fn_call = gimple_build_call (fn, 3, dest, src, nb_bytes);
860 gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
861
862 if (dump_file && (dump_flags & TDF_DETAILS))
863 {
864 if (kind == BUILT_IN_MEMCPY)
865 fprintf (dump_file, "generated memcpy\n");
866 else
867 fprintf (dump_file, "generated memmove\n");
868 }
869}
870
30d55936 871/* Remove and destroy the loop LOOP. */
dea61d92 872
30d55936
RG
873static void
874destroy_loop (struct loop *loop)
dea61d92 875{
30d55936
RG
876 unsigned nbbs = loop->num_nodes;
877 edge exit = single_exit (loop);
878 basic_block src = loop_preheader_edge (loop)->src, dest = exit->dest;
dea61d92 879 basic_block *bbs;
30d55936 880 unsigned i;
dea61d92
SP
881
882 bbs = get_loop_body_in_dom_order (loop);
883
30d55936
RG
884 redirect_edge_pred (exit, src);
885 exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
886 exit->flags |= EDGE_FALLTHRU;
887 cancel_loop_tree (loop);
888 rescan_loop_exit (exit, false, true);
dea61d92 889
30d55936 890 for (i = 0; i < nbbs; i++)
c014f6f5
RG
891 {
892 /* We have made sure to not leave any dangling uses of SSA
893 names defined in the loop. With the exception of virtuals.
894 Make sure we replace all uses of virtual defs that will remain
895 outside of the loop with the bare symbol as delete_basic_block
896 will release them. */
538dd0b7
DM
897 for (gphi_iterator gsi = gsi_start_phis (bbs[i]); !gsi_end_p (gsi);
898 gsi_next (&gsi))
c014f6f5 899 {
538dd0b7 900 gphi *phi = gsi.phi ();
ea057359 901 if (virtual_operand_p (gimple_phi_result (phi)))
c014f6f5
RG
902 mark_virtual_phi_result_for_renaming (phi);
903 }
538dd0b7
DM
904 for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);
905 gsi_next (&gsi))
c014f6f5 906 {
355fe088 907 gimple *stmt = gsi_stmt (gsi);
c014f6f5
RG
908 tree vdef = gimple_vdef (stmt);
909 if (vdef && TREE_CODE (vdef) == SSA_NAME)
910 mark_virtual_operand_for_renaming (vdef);
911 }
912 delete_basic_block (bbs[i]);
913 }
dea61d92 914 free (bbs);
30d55936
RG
915
916 set_immediate_dominator (CDI_DOMINATORS, dest,
917 recompute_dominator (CDI_DOMINATORS, dest));
dea61d92
SP
918}
919
30d55936 920/* Generates code for PARTITION. */
dea61d92 921
30d55936 922static void
d0582dc1 923generate_code_for_partition (struct loop *loop,
526ceb68 924 partition *partition, bool copy_p)
dea61d92 925{
30d55936
RG
926 switch (partition->kind)
927 {
826a536d
RB
928 case PKIND_NORMAL:
929 /* Reductions all have to be in the last partition. */
930 gcc_assert (!partition_reduction_p (partition)
931 || !copy_p);
932 generate_loops_for_partition (loop, partition, copy_p);
933 return;
934
30d55936 935 case PKIND_MEMSET:
d0582dc1 936 generate_memset_builtin (loop, partition);
d0582dc1
RG
937 break;
938
939 case PKIND_MEMCPY:
940 generate_memcpy_builtin (loop, partition);
30d55936
RG
941 break;
942
943 default:
944 gcc_unreachable ();
945 }
dea61d92 946
826a536d
RB
947 /* Common tail for partitions we turn into a call. If this was the last
948 partition for which we generate code, we have to destroy the loop. */
949 if (!copy_p)
950 destroy_loop (loop);
dea61d92
SP
951}
952
dea61d92 953
24f161fd
RB
954/* Returns a partition with all the statements needed for computing
955 the vertex V of the RDG, also including the loop exit conditions. */
dea61d92 956
526ceb68 957static partition *
24f161fd 958build_rdg_partition_for_vertex (struct graph *rdg, int v)
dea61d92 959{
526ceb68 960 partition *partition = partition_alloc (NULL, NULL);
00f96dc9 961 auto_vec<int, 3> nodes;
24f161fd 962 unsigned i;
dea61d92
SP
963 int x;
964
174ec470 965 graphds_dfs (rdg, &v, 1, &nodes, false, NULL);
dea61d92 966
9771b263 967 FOR_EACH_VEC_ELT (nodes, i, x)
24f161fd
RB
968 {
969 bitmap_set_bit (partition->stmts, x);
970 bitmap_set_bit (partition->loops,
971 loop_containing_stmt (RDG_STMT (rdg, x))->num);
972 }
dea61d92 973
dea61d92
SP
974 return partition;
975}
976
30d55936
RG
977/* Classifies the builtin kind we can generate for PARTITION of RDG and LOOP.
978 For the moment we detect only the memset zero pattern. */
cfee318d 979
30d55936 980static void
526ceb68 981classify_partition (loop_p loop, struct graph *rdg, partition *partition)
cfee318d 982{
cfee318d 983 bitmap_iterator bi;
30d55936
RG
984 unsigned i;
985 tree nb_iter;
d0582dc1 986 data_reference_p single_load, single_store;
b9fc0497 987 bool volatiles_p = false;
d995e887 988 bool plus_one = false;
30d55936
RG
989
990 partition->kind = PKIND_NORMAL;
d0582dc1
RG
991 partition->main_dr = NULL;
992 partition->secondary_dr = NULL;
818625cf 993 partition->niter = NULL_TREE;
d995e887 994 partition->plus_one = false;
30d55936 995
c61f8985 996 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
30d55936 997 {
355fe088 998 gimple *stmt = RDG_STMT (rdg, i);
30d55936
RG
999
1000 if (gimple_has_volatile_ops (stmt))
b9fc0497 1001 volatiles_p = true;
cfee318d 1002
826a536d 1003 /* If the stmt has uses outside of the loop mark it as reduction. */
9ca86fc3 1004 if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
30d55936 1005 {
826a536d 1006 partition->reduction_p = true;
30d55936
RG
1007 return;
1008 }
1009 }
1010
b9fc0497
RB
1011 /* Perform general partition disqualification for builtins. */
1012 if (volatiles_p
1013 || !flag_tree_loop_distribute_patterns)
1014 return;
1015
d0582dc1
RG
1016 /* Detect memset and memcpy. */
1017 single_load = NULL;
1018 single_store = NULL;
30d55936
RG
1019 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
1020 {
355fe088 1021 gimple *stmt = RDG_STMT (rdg, i);
d0582dc1
RG
1022 data_reference_p dr;
1023 unsigned j;
30d55936
RG
1024
1025 if (gimple_code (stmt) == GIMPLE_PHI)
1026 continue;
1027
1028 /* Any scalar stmts are ok. */
1029 if (!gimple_vuse (stmt))
1030 continue;
1031
d0582dc1
RG
1032 /* Otherwise just regular loads/stores. */
1033 if (!gimple_assign_single_p (stmt))
1034 return;
1035
1036 /* But exactly one store and/or load. */
9771b263 1037 for (j = 0; RDG_DATAREFS (rdg, i).iterate (j, &dr); ++j)
30d55936 1038 {
d0582dc1
RG
1039 if (DR_IS_READ (dr))
1040 {
1041 if (single_load != NULL)
1042 return;
1043 single_load = dr;
1044 }
1045 else
1046 {
1047 if (single_store != NULL)
1048 return;
1049 single_store = dr;
1050 }
30d55936 1051 }
30d55936
RG
1052 }
1053
818625cf
RB
1054 if (!single_store)
1055 return;
1056
d995e887 1057 nb_iter = number_of_latch_executions (loop);
818625cf
RB
1058 if (!nb_iter || nb_iter == chrec_dont_know)
1059 return;
d995e887
RB
1060 if (dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src,
1061 gimple_bb (DR_STMT (single_store))))
1062 plus_one = true;
818625cf 1063
d0582dc1
RG
1064 if (single_store && !single_load)
1065 {
355fe088 1066 gimple *stmt = DR_STMT (single_store);
d0582dc1 1067 tree rhs = gimple_assign_rhs1 (stmt);
401f3a81
JJ
1068 if (const_with_all_bytes_same (rhs) == -1
1069 && (!INTEGRAL_TYPE_P (TREE_TYPE (rhs))
1070 || (TYPE_MODE (TREE_TYPE (rhs))
1071 != TYPE_MODE (unsigned_char_type_node))))
d0582dc1
RG
1072 return;
1073 if (TREE_CODE (rhs) == SSA_NAME
1074 && !SSA_NAME_IS_DEFAULT_DEF (rhs)
1075 && flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
1076 return;
ca406576
RB
1077 if (!adjacent_dr_p (single_store)
1078 || !dominated_by_p (CDI_DOMINATORS,
1079 loop->latch, gimple_bb (stmt)))
d0582dc1
RG
1080 return;
1081 partition->kind = PKIND_MEMSET;
1082 partition->main_dr = single_store;
818625cf 1083 partition->niter = nb_iter;
d995e887 1084 partition->plus_one = plus_one;
d0582dc1
RG
1085 }
1086 else if (single_store && single_load)
1087 {
355fe088
TS
1088 gimple *store = DR_STMT (single_store);
1089 gimple *load = DR_STMT (single_load);
d0582dc1
RG
1090 /* Direct aggregate copy or via an SSA name temporary. */
1091 if (load != store
1092 && gimple_assign_lhs (load) != gimple_assign_rhs1 (store))
1093 return;
1094 if (!adjacent_dr_p (single_store)
1095 || !adjacent_dr_p (single_load)
1096 || !operand_equal_p (DR_STEP (single_store),
ca406576
RB
1097 DR_STEP (single_load), 0)
1098 || !dominated_by_p (CDI_DOMINATORS,
1099 loop->latch, gimple_bb (store)))
d0582dc1 1100 return;
f20132e7
RG
1101 /* Now check that if there is a dependence this dependence is
1102 of a suitable form for memmove. */
6e1aa848 1103 vec<loop_p> loops = vNULL;
f20132e7 1104 ddr_p ddr;
9771b263 1105 loops.safe_push (loop);
f20132e7
RG
1106 ddr = initialize_data_dependence_relation (single_load, single_store,
1107 loops);
1108 compute_affine_dependence (ddr, loop);
f20132e7
RG
1109 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
1110 {
1111 free_dependence_relation (ddr);
9771b263 1112 loops.release ();
f20132e7
RG
1113 return;
1114 }
1115 if (DDR_ARE_DEPENDENT (ddr) != chrec_known)
1116 {
1117 if (DDR_NUM_DIST_VECTS (ddr) == 0)
1118 {
1119 free_dependence_relation (ddr);
9771b263 1120 loops.release ();
f20132e7
RG
1121 return;
1122 }
1123 lambda_vector dist_v;
9771b263 1124 FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v)
f20132e7
RG
1125 {
1126 int dist = dist_v[index_in_loop_nest (loop->num,
1127 DDR_LOOP_NEST (ddr))];
1128 if (dist > 0 && !DDR_REVERSED_P (ddr))
1129 {
1130 free_dependence_relation (ddr);
9771b263 1131 loops.release ();
f20132e7
RG
1132 return;
1133 }
1134 }
1135 }
b7ce70b3 1136 free_dependence_relation (ddr);
9771b263 1137 loops.release ();
d0582dc1
RG
1138 partition->kind = PKIND_MEMCPY;
1139 partition->main_dr = single_store;
1140 partition->secondary_dr = single_load;
818625cf 1141 partition->niter = nb_iter;
d995e887 1142 partition->plus_one = plus_one;
d0582dc1 1143 }
cfee318d
SP
1144}
1145
1fa0c180
RG
1146/* For a data reference REF, return the declaration of its base
1147 address or NULL_TREE if the base is not determined. */
1148
1149static tree
1150ref_base_address (data_reference_p dr)
1151{
1152 tree base_address = DR_BASE_ADDRESS (dr);
1153 if (base_address
1154 && TREE_CODE (base_address) == ADDR_EXPR)
1155 return TREE_OPERAND (base_address, 0);
1156
1157 return base_address;
1158}
1159
cfee318d
SP
1160/* Returns true when PARTITION1 and PARTITION2 have similar memory
1161 accesses in RDG. */
1162
1163static bool
526ceb68
TS
1164similar_memory_accesses (struct graph *rdg, partition *partition1,
1165 partition *partition2)
cfee318d 1166{
1fa0c180 1167 unsigned i, j, k, l;
cfee318d 1168 bitmap_iterator bi, bj;
1fa0c180
RG
1169 data_reference_p ref1, ref2;
1170
1171 /* First check whether in the intersection of the two partitions are
1172 any loads or stores. Common loads are the situation that happens
1173 most often. */
1174 EXECUTE_IF_AND_IN_BITMAP (partition1->stmts, partition2->stmts, 0, i, bi)
1175 if (RDG_MEM_WRITE_STMT (rdg, i)
1176 || RDG_MEM_READS_STMT (rdg, i))
1177 return true;
cfee318d 1178
1fa0c180 1179 /* Then check all data-references against each other. */
c61f8985 1180 EXECUTE_IF_SET_IN_BITMAP (partition1->stmts, 0, i, bi)
cfee318d
SP
1181 if (RDG_MEM_WRITE_STMT (rdg, i)
1182 || RDG_MEM_READS_STMT (rdg, i))
c61f8985 1183 EXECUTE_IF_SET_IN_BITMAP (partition2->stmts, 0, j, bj)
cfee318d
SP
1184 if (RDG_MEM_WRITE_STMT (rdg, j)
1185 || RDG_MEM_READS_STMT (rdg, j))
1fa0c180 1186 {
9771b263 1187 FOR_EACH_VEC_ELT (RDG_DATAREFS (rdg, i), k, ref1)
1fa0c180
RG
1188 {
1189 tree base1 = ref_base_address (ref1);
1190 if (base1)
9771b263 1191 FOR_EACH_VEC_ELT (RDG_DATAREFS (rdg, j), l, ref2)
1fa0c180
RG
1192 if (base1 == ref_base_address (ref2))
1193 return true;
1194 }
1195 }
cfee318d
SP
1196
1197 return false;
1198}
1199
dea61d92
SP
1200/* Aggregate several components into a useful partition that is
1201 registered in the PARTITIONS vector. Partitions will be
1202 distributed in different loops. */
1203
1204static void
83a95546 1205rdg_build_partitions (struct graph *rdg,
355fe088 1206 vec<gimple *> starting_stmts,
526ceb68 1207 vec<partition *> *partitions)
dea61d92 1208{
83a95546 1209 bitmap processed = BITMAP_ALLOC (NULL);
2fd5894f 1210 int i;
355fe088 1211 gimple *stmt;
dea61d92 1212
2fd5894f 1213 FOR_EACH_VEC_ELT (starting_stmts, i, stmt)
dea61d92 1214 {
2fd5894f
RB
1215 int v = rdg_vertex_for_stmt (rdg, stmt);
1216
1217 if (dump_file && (dump_flags & TDF_DETAILS))
1218 fprintf (dump_file,
1219 "ldist asked to generate code for vertex %d\n", v);
b8698a0f 1220
24f161fd
RB
1221 /* If the vertex is already contained in another partition so
1222 is the partition rooted at it. */
dea61d92
SP
1223 if (bitmap_bit_p (processed, v))
1224 continue;
b8698a0f 1225
526ceb68 1226 partition *partition = build_rdg_partition_for_vertex (rdg, v);
24f161fd 1227 bitmap_ior_into (processed, partition->stmts);
dea61d92 1228
826a536d 1229 if (dump_file && (dump_flags & TDF_DETAILS))
dea61d92 1230 {
826a536d
RB
1231 fprintf (dump_file, "ldist useful partition:\n");
1232 dump_bitmap (dump_file, partition->stmts);
dea61d92 1233 }
826a536d
RB
1234
1235 partitions->safe_push (partition);
dea61d92
SP
1236 }
1237
83a95546
RB
1238 /* All vertices should have been assigned to at least one partition now,
1239 other than vertices belonging to dead code. */
dea61d92 1240
83a95546 1241 BITMAP_FREE (processed);
dea61d92
SP
1242}
1243
1244/* Dump to FILE the PARTITIONS. */
1245
1246static void
526ceb68 1247dump_rdg_partitions (FILE *file, vec<partition *> partitions)
dea61d92
SP
1248{
1249 int i;
526ceb68 1250 partition *partition;
dea61d92 1251
9771b263 1252 FOR_EACH_VEC_ELT (partitions, i, partition)
c61f8985 1253 debug_bitmap_file (file, partition->stmts);
dea61d92
SP
1254}
1255
1256/* Debug PARTITIONS. */
526ceb68 1257extern void debug_rdg_partitions (vec<partition *> );
dea61d92 1258
24e47c76 1259DEBUG_FUNCTION void
526ceb68 1260debug_rdg_partitions (vec<partition *> partitions)
dea61d92
SP
1261{
1262 dump_rdg_partitions (stderr, partitions);
1263}
1264
2b8aee8e
SP
1265/* Returns the number of read and write operations in the RDG. */
1266
1267static int
1268number_of_rw_in_rdg (struct graph *rdg)
1269{
1270 int i, res = 0;
1271
1272 for (i = 0; i < rdg->n_vertices; i++)
1273 {
1274 if (RDG_MEM_WRITE_STMT (rdg, i))
1275 ++res;
1276
1277 if (RDG_MEM_READS_STMT (rdg, i))
1278 ++res;
1279 }
1280
1281 return res;
1282}
1283
1284/* Returns the number of read and write operations in a PARTITION of
1285 the RDG. */
1286
1287static int
526ceb68 1288number_of_rw_in_partition (struct graph *rdg, partition *partition)
2b8aee8e
SP
1289{
1290 int res = 0;
1291 unsigned i;
1292 bitmap_iterator ii;
1293
c61f8985 1294 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, ii)
2b8aee8e
SP
1295 {
1296 if (RDG_MEM_WRITE_STMT (rdg, i))
1297 ++res;
1298
1299 if (RDG_MEM_READS_STMT (rdg, i))
1300 ++res;
1301 }
1302
1303 return res;
1304}
1305
1306/* Returns true when one of the PARTITIONS contains all the read or
1307 write operations of RDG. */
1308
1309static bool
9771b263 1310partition_contains_all_rw (struct graph *rdg,
526ceb68 1311 vec<partition *> partitions)
2b8aee8e
SP
1312{
1313 int i;
526ceb68 1314 partition *partition;
2b8aee8e
SP
1315 int nrw = number_of_rw_in_rdg (rdg);
1316
9771b263 1317 FOR_EACH_VEC_ELT (partitions, i, partition)
2b8aee8e
SP
1318 if (nrw == number_of_rw_in_partition (rdg, partition))
1319 return true;
1320
1321 return false;
1322}
1323
447f3223
RB
1324/* Compute partition dependence created by the data references in DRS1
1325 and DRS2 and modify and return DIR according to that. */
1326
1327static int
1328pg_add_dependence_edges (struct graph *rdg, vec<loop_p> loops, int dir,
1329 vec<data_reference_p> drs1,
1330 vec<data_reference_p> drs2)
1331{
1332 data_reference_p dr1, dr2;
1333
1334 /* dependence direction - 0 is no dependence, -1 is back,
1335 1 is forth, 2 is both (we can stop then, merging will occur). */
1336 for (int ii = 0; drs1.iterate (ii, &dr1); ++ii)
1337 for (int jj = 0; drs2.iterate (jj, &dr2); ++jj)
1338 {
62e22fcb 1339 data_reference_p saved_dr1 = dr1;
2cf19e26 1340 int this_dir = 1;
447f3223
RB
1341 ddr_p ddr;
1342 /* Re-shuffle data-refs to be in dominator order. */
1343 if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
1344 > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
1345 {
6b4db501 1346 std::swap (dr1, dr2);
447f3223
RB
1347 this_dir = -this_dir;
1348 }
1349 ddr = initialize_data_dependence_relation (dr1, dr2, loops);
1350 compute_affine_dependence (ddr, loops[0]);
1351 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
1352 this_dir = 2;
1353 else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
1354 {
1355 if (DDR_REVERSED_P (ddr))
1356 {
6b4db501 1357 std::swap (dr1, dr2);
447f3223
RB
1358 this_dir = -this_dir;
1359 }
1360 /* Known dependences can still be unordered througout the
1361 iteration space, see gcc.dg/tree-ssa/ldist-16.c. */
2cf19e26 1362 if (DDR_NUM_DIST_VECTS (ddr) != 1)
447f3223 1363 this_dir = 2;
2cf19e26
RB
1364 /* If the overlap is exact preserve stmt order. */
1365 else if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0), 1))
1366 ;
1367 else
1368 {
1369 /* Else as the distance vector is lexicographic positive
1370 swap the dependence direction. */
1371 this_dir = -this_dir;
1372 }
447f3223
RB
1373 }
1374 else
1375 this_dir = 0;
1376 free_dependence_relation (ddr);
1377 if (dir == 0)
1378 dir = this_dir;
1379 else if (dir != this_dir)
1380 return 2;
62e22fcb
RB
1381 /* Shuffle "back" dr1. */
1382 dr1 = saved_dr1;
447f3223
RB
1383 }
1384 return dir;
1385}
1386
1387/* Compare postorder number of the partition graph vertices V1 and V2. */
1388
1389static int
1390pgcmp (const void *v1_, const void *v2_)
1391{
1392 const vertex *v1 = (const vertex *)v1_;
1393 const vertex *v2 = (const vertex *)v2_;
1394 return v2->post - v1->post;
1395}
2fd5894f
RB
1396
1397/* Distributes the code from LOOP in such a way that producer
1398 statements are placed before consumer statements. Tries to separate
1399 only the statements from STMTS into separate loops.
1400 Returns the number of distributed loops. */
dea61d92
SP
1401
1402static int
355fe088 1403distribute_loop (struct loop *loop, vec<gimple *> stmts,
826a536d 1404 control_dependences *cd, int *nb_calls)
dea61d92 1405{
2fd5894f 1406 struct graph *rdg;
526ceb68 1407 partition *partition;
be6b029b 1408 bool any_builtin;
2fd5894f 1409 int i, nbp;
447f3223
RB
1410 graph *pg = NULL;
1411 int num_sccs = 1;
dea61d92 1412
826a536d 1413 *nb_calls = 0;
00f96dc9 1414 auto_vec<loop_p, 3> loop_nest;
2fd5894f 1415 if (!find_loop_nest (loop, &loop_nest))
07687835 1416 return 0;
2fd5894f 1417
36875e8f 1418 rdg = build_rdg (loop_nest, cd);
2fd5894f
RB
1419 if (!rdg)
1420 {
1421 if (dump_file && (dump_flags & TDF_DETAILS))
1422 fprintf (dump_file,
1423 "Loop %d not distributed: failed to build the RDG.\n",
1424 loop->num);
1425
2fd5894f
RB
1426 return 0;
1427 }
1428
1429 if (dump_file && (dump_flags & TDF_DETAILS))
1430 dump_rdg (dump_file, rdg);
1431
526ceb68 1432 auto_vec<struct partition *, 3> partitions;
2fd5894f 1433 rdg_build_partitions (rdg, stmts, &partitions);
dea61d92 1434
be6b029b 1435 any_builtin = false;
9771b263 1436 FOR_EACH_VEC_ELT (partitions, i, partition)
be6b029b
RG
1437 {
1438 classify_partition (loop, rdg, partition);
1439 any_builtin |= partition_builtin_p (partition);
1440 }
30d55936 1441
447f3223
RB
1442 /* If we are only distributing patterns but did not detect any,
1443 simply bail out. */
9fed7f3a
RB
1444 if (!flag_tree_loop_distribution
1445 && !any_builtin)
1446 {
1447 nbp = 0;
1448 goto ldist_done;
1449 }
1450
447f3223
RB
1451 /* If we are only distributing patterns fuse all partitions that
1452 were not classified as builtins. This also avoids chopping
1453 a loop into pieces, separated by builtin calls. That is, we
1454 only want no or a single loop body remaining. */
526ceb68 1455 struct partition *into;
447f3223
RB
1456 if (!flag_tree_loop_distribution)
1457 {
1458 for (i = 0; partitions.iterate (i, &into); ++i)
1459 if (!partition_builtin_p (into))
1460 break;
1461 for (++i; partitions.iterate (i, &partition); ++i)
1462 if (!partition_builtin_p (partition))
1463 {
1464 if (dump_file && (dump_flags & TDF_DETAILS))
1465 {
1466 fprintf (dump_file, "fusing non-builtin partitions\n");
1467 dump_bitmap (dump_file, into->stmts);
1468 dump_bitmap (dump_file, partition->stmts);
1469 }
1470 partition_merge_into (into, partition);
1471 partitions.unordered_remove (i);
1472 partition_free (partition);
1473 i--;
1474 }
1475 }
1476
1477 /* Due to limitations in the transform phase we have to fuse all
1478 reduction partitions into the last partition so the existing
1479 loop will contain all loop-closed PHI nodes. */
1480 for (i = 0; partitions.iterate (i, &into); ++i)
1481 if (partition_reduction_p (into))
1482 break;
1483 for (i = i + 1; partitions.iterate (i, &partition); ++i)
1484 if (partition_reduction_p (partition))
1485 {
1486 if (dump_file && (dump_flags & TDF_DETAILS))
1487 {
1488 fprintf (dump_file, "fusing partitions\n");
1489 dump_bitmap (dump_file, into->stmts);
1490 dump_bitmap (dump_file, partition->stmts);
1491 fprintf (dump_file, "because they have reductions\n");
1492 }
1493 partition_merge_into (into, partition);
1494 partitions.unordered_remove (i);
1495 partition_free (partition);
1496 i--;
1497 }
1498
9fed7f3a
RB
1499 /* Apply our simple cost model - fuse partitions with similar
1500 memory accesses. */
9fed7f3a
RB
1501 for (i = 0; partitions.iterate (i, &into); ++i)
1502 {
1503 if (partition_builtin_p (into))
1504 continue;
1505 for (int j = i + 1;
1506 partitions.iterate (j, &partition); ++j)
1507 {
1508 if (!partition_builtin_p (partition)
1509 && similar_memory_accesses (rdg, into, partition))
1510 {
1511 if (dump_file && (dump_flags & TDF_DETAILS))
1512 {
1513 fprintf (dump_file, "fusing partitions\n");
1514 dump_bitmap (dump_file, into->stmts);
1515 dump_bitmap (dump_file, partition->stmts);
1516 fprintf (dump_file, "because they have similar "
1517 "memory accesses\n");
1518 }
826a536d 1519 partition_merge_into (into, partition);
447f3223 1520 partitions.unordered_remove (j);
9fed7f3a
RB
1521 partition_free (partition);
1522 j--;
1523 }
1524 }
1525 }
1526
447f3223
RB
1527 /* Build the partition dependency graph. */
1528 if (partitions.length () > 1)
c014f6f5 1529 {
447f3223
RB
1530 pg = new_graph (partitions.length ());
1531 struct pgdata {
526ceb68 1532 struct partition *partition;
447f3223
RB
1533 vec<data_reference_p> writes;
1534 vec<data_reference_p> reads;
1535 };
1536#define PGDATA(i) ((pgdata *)(pg->vertices[i].data))
1537 for (i = 0; partitions.iterate (i, &partition); ++i)
1538 {
1539 vertex *v = &pg->vertices[i];
1540 pgdata *data = new pgdata;
1541 data_reference_p dr;
1542 /* FIXME - leaks. */
1543 v->data = data;
1544 bitmap_iterator bi;
1545 unsigned j;
1546 data->partition = partition;
1547 data->reads = vNULL;
1548 data->writes = vNULL;
1549 EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, j, bi)
1550 for (int k = 0; RDG_DATAREFS (rdg, j).iterate (k, &dr); ++k)
1551 if (DR_IS_READ (dr))
1552 data->reads.safe_push (dr);
1553 else
1554 data->writes.safe_push (dr);
1555 }
526ceb68 1556 struct partition *partition1, *partition2;
447f3223
RB
1557 for (i = 0; partitions.iterate (i, &partition1); ++i)
1558 for (int j = i + 1; partitions.iterate (j, &partition2); ++j)
1559 {
1560 /* dependence direction - 0 is no dependence, -1 is back,
1561 1 is forth, 2 is both (we can stop then, merging will occur). */
1562 int dir = 0;
1563 dir = pg_add_dependence_edges (rdg, loop_nest, dir,
1564 PGDATA(i)->writes,
1565 PGDATA(j)->reads);
1566 if (dir != 2)
1567 dir = pg_add_dependence_edges (rdg, loop_nest, dir,
1568 PGDATA(i)->reads,
1569 PGDATA(j)->writes);
1570 if (dir != 2)
1571 dir = pg_add_dependence_edges (rdg, loop_nest, dir,
1572 PGDATA(i)->writes,
1573 PGDATA(j)->writes);
1574 if (dir == 1 || dir == 2)
1575 add_edge (pg, i, j);
1576 if (dir == -1 || dir == 2)
1577 add_edge (pg, j, i);
1578 }
1579
1580 /* Add edges to the reduction partition (if any) to force it last. */
1581 unsigned j;
1582 for (j = 0; partitions.iterate (j, &partition); ++j)
1583 if (partition_reduction_p (partition))
1584 break;
1585 if (j < partitions.length ())
38ad2d07 1586 {
447f3223
RB
1587 for (unsigned i = 0; partitions.iterate (i, &partition); ++i)
1588 if (i != j)
1589 add_edge (pg, i, j);
1590 }
1591
1592 /* Compute partitions we cannot separate and fuse them. */
1593 num_sccs = graphds_scc (pg, NULL);
1594 for (i = 0; i < num_sccs; ++i)
1595 {
526ceb68 1596 struct partition *first;
447f3223
RB
1597 int j;
1598 for (j = 0; partitions.iterate (j, &first); ++j)
1599 if (pg->vertices[j].component == i)
38ad2d07 1600 break;
447f3223
RB
1601 for (j = j + 1; partitions.iterate (j, &partition); ++j)
1602 if (pg->vertices[j].component == i)
38ad2d07 1603 {
447f3223
RB
1604 if (dump_file && (dump_flags & TDF_DETAILS))
1605 {
1606 fprintf (dump_file, "fusing partitions\n");
1607 dump_bitmap (dump_file, first->stmts);
1608 dump_bitmap (dump_file, partition->stmts);
1609 fprintf (dump_file, "because they are in the same "
1610 "dependence SCC\n");
1611 }
1612 partition_merge_into (first, partition);
1613 partitions[j] = NULL;
5eb010bc 1614 partition_free (partition);
447f3223 1615 PGDATA (j)->partition = NULL;
38ad2d07 1616 }
38ad2d07 1617 }
30d55936 1618
447f3223
RB
1619 /* Now order the remaining nodes in postorder. */
1620 qsort (pg->vertices, pg->n_vertices, sizeof (vertex), pgcmp);
1621 partitions.truncate (0);
1622 for (i = 0; i < pg->n_vertices; ++i)
b9fc0497 1623 {
447f3223
RB
1624 pgdata *data = PGDATA (i);
1625 if (data->partition)
1626 partitions.safe_push (data->partition);
1627 data->reads.release ();
1628 data->writes.release ();
1629 delete data;
b9fc0497 1630 }
447f3223
RB
1631 gcc_assert (partitions.length () == (unsigned)num_sccs);
1632 free_graph (pg);
b9fc0497
RB
1633 }
1634
9771b263 1635 nbp = partitions.length ();
a4293fa6 1636 if (nbp == 0
9771b263
DN
1637 || (nbp == 1 && !partition_builtin_p (partitions[0]))
1638 || (nbp > 1 && partition_contains_all_rw (rdg, partitions)))
c014f6f5
RG
1639 {
1640 nbp = 0;
1641 goto ldist_done;
1642 }
dea61d92
SP
1643
1644 if (dump_file && (dump_flags & TDF_DETAILS))
1645 dump_rdg_partitions (dump_file, partitions);
1646
9771b263 1647 FOR_EACH_VEC_ELT (partitions, i, partition)
826a536d
RB
1648 {
1649 if (partition_builtin_p (partition))
1650 (*nb_calls)++;
1651 generate_code_for_partition (loop, partition, i < nbp - 1);
1652 }
dea61d92 1653
dea61d92
SP
1654 ldist_done:
1655
9771b263 1656 FOR_EACH_VEC_ELT (partitions, i, partition)
c61f8985 1657 partition_free (partition);
dea61d92 1658
dea61d92 1659 free_rdg (rdg);
826a536d 1660 return nbp - *nb_calls;
dea61d92
SP
1661}
1662
1663/* Distribute all loops in the current function. */
1664
be55bfe6
TS
1665namespace {
1666
1667const pass_data pass_data_loop_distribution =
1668{
1669 GIMPLE_PASS, /* type */
1670 "ldist", /* name */
1671 OPTGROUP_LOOP, /* optinfo_flags */
be55bfe6
TS
1672 TV_TREE_LOOP_DISTRIBUTION, /* tv_id */
1673 ( PROP_cfg | PROP_ssa ), /* properties_required */
1674 0, /* properties_provided */
1675 0, /* properties_destroyed */
1676 0, /* todo_flags_start */
3bea341f 1677 0, /* todo_flags_finish */
be55bfe6
TS
1678};
1679
1680class pass_loop_distribution : public gimple_opt_pass
1681{
1682public:
1683 pass_loop_distribution (gcc::context *ctxt)
1684 : gimple_opt_pass (pass_data_loop_distribution, ctxt)
1685 {}
1686
1687 /* opt_pass methods: */
1688 virtual bool gate (function *)
1689 {
1690 return flag_tree_loop_distribution
1691 || flag_tree_loop_distribute_patterns;
1692 }
1693
1694 virtual unsigned int execute (function *);
1695
1696}; // class pass_loop_distribution
1697
1698unsigned int
1699pass_loop_distribution::execute (function *fun)
dea61d92
SP
1700{
1701 struct loop *loop;
c014f6f5 1702 bool changed = false;
1fa0c180 1703 basic_block bb;
36875e8f 1704 control_dependences *cd = NULL;
1fa0c180 1705
be55bfe6 1706 FOR_ALL_BB_FN (bb, fun)
1fa0c180
RG
1707 {
1708 gimple_stmt_iterator gsi;
1709 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1710 gimple_set_uid (gsi_stmt (gsi), -1);
1711 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1712 gimple_set_uid (gsi_stmt (gsi), -1);
1713 }
dea61d92 1714
c014f6f5
RG
1715 /* We can at the moment only distribute non-nested loops, thus restrict
1716 walking to innermost loops. */
f0bd40b1 1717 FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
dea61d92 1718 {
355fe088 1719 auto_vec<gimple *> work_list;
be6b029b 1720 basic_block *bbs;
0e20c89f 1721 int num = loop->num;
be6b029b 1722 unsigned int i;
a3357f7d
RG
1723
1724 /* If the loop doesn't have a single exit we will fail anyway,
1725 so do that early. */
1726 if (!single_exit (loop))
1727 continue;
dea61d92 1728
f56f2d33
JH
1729 /* Only optimize hot loops. */
1730 if (!optimize_loop_for_speed_p (loop))
1731 continue;
1732
be6b029b
RG
1733 /* Initialize the worklist with stmts we seed the partitions with. */
1734 bbs = get_loop_body_in_dom_order (loop);
1735 for (i = 0; i < loop->num_nodes; ++i)
1736 {
538dd0b7
DM
1737 for (gphi_iterator gsi = gsi_start_phis (bbs[i]);
1738 !gsi_end_p (gsi);
1739 gsi_next (&gsi))
deb6c11a 1740 {
538dd0b7 1741 gphi *phi = gsi.phi ();
deb6c11a
RB
1742 if (virtual_operand_p (gimple_phi_result (phi)))
1743 continue;
1744 /* Distribute stmts which have defs that are used outside of
be55bfe6 1745 the loop. */
deb6c11a
RB
1746 if (!stmt_has_scalar_dependences_outside_loop (loop, phi))
1747 continue;
1748 work_list.safe_push (phi);
1749 }
538dd0b7
DM
1750 for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]);
1751 !gsi_end_p (gsi);
1752 gsi_next (&gsi))
be6b029b 1753 {
355fe088 1754 gimple *stmt = gsi_stmt (gsi);
83a95546
RB
1755
1756 /* If there is a stmt with side-effects bail out - we
be55bfe6 1757 cannot and should not distribute this loop. */
83a95546
RB
1758 if (gimple_has_side_effects (stmt))
1759 {
1760 work_list.truncate (0);
1761 goto out;
1762 }
1763
b9fc0497 1764 /* Distribute stmts which have defs that are used outside of
be55bfe6 1765 the loop. */
b9fc0497
RB
1766 if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
1767 ;
1768 /* Otherwise only distribute stores for now. */
e179190c 1769 else if (!gimple_vdef (stmt))
be6b029b
RG
1770 continue;
1771
9771b263 1772 work_list.safe_push (stmt);
be6b029b
RG
1773 }
1774 }
83a95546 1775out:
be6b029b 1776 free (bbs);
c014f6f5 1777
826a536d
RB
1778 int nb_generated_loops = 0;
1779 int nb_generated_calls = 0;
1780 location_t loc = find_loop_location (loop);
9771b263 1781 if (work_list.length () > 0)
36875e8f
RB
1782 {
1783 if (!cd)
1784 {
ca406576 1785 calculate_dominance_info (CDI_DOMINATORS);
36875e8f
RB
1786 calculate_dominance_info (CDI_POST_DOMINATORS);
1787 cd = new control_dependences (create_edge_list ());
1788 free_dominance_info (CDI_POST_DOMINATORS);
1789 }
826a536d
RB
1790 nb_generated_loops = distribute_loop (loop, work_list, cd,
1791 &nb_generated_calls);
36875e8f 1792 }
c014f6f5 1793
826a536d 1794 if (nb_generated_loops + nb_generated_calls > 0)
dea61d92 1795 {
826a536d
RB
1796 changed = true;
1797 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
1798 loc, "Loop %d distributed: split to %d loops "
1799 "and %d library calls.\n",
1800 num, nb_generated_loops, nb_generated_calls);
dea61d92 1801 }
826a536d
RB
1802 else if (dump_file && (dump_flags & TDF_DETAILS))
1803 fprintf (dump_file, "Loop %d is the same.\n", num);
dea61d92
SP
1804 }
1805
36875e8f
RB
1806 if (cd)
1807 delete cd;
1808
c014f6f5
RG
1809 if (changed)
1810 {
d0ed943c
RB
1811 /* Cached scalar evolutions now may refer to wrong or non-existing
1812 loops. */
1813 scev_reset_htab ();
be55bfe6 1814 mark_virtual_operands_for_renaming (fun);
c014f6f5
RG
1815 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
1816 }
1817
b2b29377 1818 checking_verify_loop_structure ();
c014f6f5 1819
5006671f 1820 return 0;
dea61d92
SP
1821}
1822
27a4cd48
DM
1823} // anon namespace
1824
1825gimple_opt_pass *
1826make_pass_loop_distribution (gcc::context *ctxt)
1827{
1828 return new pass_loop_distribution (ctxt);
1829}