]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ddg.c
Change copyright header to refer to version 3 of the GNU General Public License and...
[thirdparty/gcc.git] / gcc / ddg.c
1 /* DDG - Data Dependence Graph implementation.
2 Copyright (C) 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4 Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 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.
17
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/>. */
21
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "toplev.h"
28 #include "rtl.h"
29 #include "tm_p.h"
30 #include "hard-reg-set.h"
31 #include "regs.h"
32 #include "function.h"
33 #include "flags.h"
34 #include "insn-config.h"
35 #include "insn-attr.h"
36 #include "except.h"
37 #include "recog.h"
38 #include "sched-int.h"
39 #include "target.h"
40 #include "cfglayout.h"
41 #include "cfgloop.h"
42 #include "sbitmap.h"
43 #include "expr.h"
44 #include "bitmap.h"
45 #include "ddg.h"
46
47 /* A flag indicating that a ddg edge belongs to an SCC or not. */
48 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
49
50 /* Forward declarations. */
51 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
52 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
53 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
54 static void create_ddg_dependence (ddg_ptr, ddg_node_ptr, ddg_node_ptr, dep_t);
55 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
56 dep_type, dep_data_type, int);
57 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
58 dep_data_type, int, int);
59 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
60 \f
61 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
62 static bool mem_ref_p;
63
64 /* Auxiliary function for mem_read_insn_p. */
65 static int
66 mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
67 {
68 if (MEM_P (*x))
69 mem_ref_p = true;
70 return 0;
71 }
72
73 /* Auxiliary function for mem_read_insn_p. */
74 static void
75 mark_mem_use_1 (rtx *x, void *data)
76 {
77 for_each_rtx (x, mark_mem_use, data);
78 }
79
80 /* Returns nonzero if INSN reads from memory. */
81 static bool
82 mem_read_insn_p (rtx insn)
83 {
84 mem_ref_p = false;
85 note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
86 return mem_ref_p;
87 }
88
89 static void
90 mark_mem_store (rtx loc, rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
91 {
92 if (MEM_P (loc))
93 mem_ref_p = true;
94 }
95
96 /* Returns nonzero if INSN writes to memory. */
97 static bool
98 mem_write_insn_p (rtx insn)
99 {
100 mem_ref_p = false;
101 note_stores (PATTERN (insn), mark_mem_store, NULL);
102 return mem_ref_p;
103 }
104
105 /* Returns nonzero if X has access to memory. */
106 static bool
107 rtx_mem_access_p (rtx x)
108 {
109 int i, j;
110 const char *fmt;
111 enum rtx_code code;
112
113 if (x == 0)
114 return false;
115
116 if (MEM_P (x))
117 return true;
118
119 code = GET_CODE (x);
120 fmt = GET_RTX_FORMAT (code);
121 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
122 {
123 if (fmt[i] == 'e')
124 {
125 if (rtx_mem_access_p (XEXP (x, i)))
126 return true;
127 }
128 else if (fmt[i] == 'E')
129 for (j = 0; j < XVECLEN (x, i); j++)
130 {
131 if (rtx_mem_access_p (XVECEXP (x, i, j)))
132 return true;
133 }
134 }
135 return false;
136 }
137
138 /* Returns nonzero if INSN reads to or writes from memory. */
139 static bool
140 mem_access_insn_p (rtx insn)
141 {
142 return rtx_mem_access_p (PATTERN (insn));
143 }
144
145 /* Computes the dependence parameters (latency, distance etc.), creates
146 a ddg_edge and adds it to the given DDG. */
147 static void
148 create_ddg_dependence (ddg_ptr g, ddg_node_ptr src_node,
149 ddg_node_ptr dest_node, dep_t link)
150 {
151 ddg_edge_ptr e;
152 int latency, distance = 0;
153 int interloop = (src_node->cuid >= dest_node->cuid);
154 dep_type t = TRUE_DEP;
155 dep_data_type dt = (mem_access_insn_p (src_node->insn)
156 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
157 : REG_DEP);
158
159 /* For now we don't have an exact calculation of the distance,
160 so assume 1 conservatively. */
161 if (interloop)
162 distance = 1;
163
164 gcc_assert (link);
165
166 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
167 if (DEP_KIND (link) == REG_DEP_ANTI)
168 t = ANTI_DEP;
169 else if (DEP_KIND (link) == REG_DEP_OUTPUT)
170 t = OUTPUT_DEP;
171 latency = dep_cost (link);
172
173 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
174
175 if (interloop)
176 {
177 /* Some interloop dependencies are relaxed:
178 1. Every insn is output dependent on itself; ignore such deps.
179 2. Every true/flow dependence is an anti dependence in the
180 opposite direction with distance 1; such register deps
181 will be removed by renaming if broken --- ignore them. */
182 if (!(t == OUTPUT_DEP && src_node == dest_node)
183 && !(t == ANTI_DEP && dt == REG_DEP))
184 add_backarc_to_ddg (g, e);
185 else
186 free (e);
187 }
188 else if (t == ANTI_DEP && dt == REG_DEP)
189 free (e); /* We can fix broken anti register deps using reg-moves. */
190 else
191 add_edge_to_ddg (g, e);
192 }
193
194 /* The same as the above function, but it doesn't require a link parameter. */
195 static void
196 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
197 dep_type d_t, dep_data_type d_dt, int distance)
198 {
199 ddg_edge_ptr e;
200 int l;
201 enum reg_note dep_kind;
202 struct _dep _dep, *dep = &_dep;
203
204 if (d_t == ANTI_DEP)
205 dep_kind = REG_DEP_ANTI;
206 else if (d_t == OUTPUT_DEP)
207 dep_kind = REG_DEP_OUTPUT;
208 else
209 {
210 gcc_assert (d_t == TRUE_DEP);
211
212 dep_kind = REG_DEP_TRUE;
213 }
214
215 init_dep (dep, from->insn, to->insn, dep_kind);
216
217 l = dep_cost (dep);
218
219 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
220 if (distance > 0)
221 add_backarc_to_ddg (g, e);
222 else
223 add_edge_to_ddg (g, e);
224 }
225
226 \f
227 /* Given a downwards exposed register def RD, add inter-loop true dependences
228 for all its uses in the next iteration, and an output dependence to the
229 first def of the next iteration. */
230 static void
231 add_deps_for_def (ddg_ptr g, struct df_ref *rd)
232 {
233 int regno = DF_REF_REGNO (rd);
234 struct df_ru_bb_info *bb_info = DF_RU_BB_INFO (g->bb);
235 struct df_link *r_use;
236 int use_before_def = false;
237 rtx def_insn = DF_REF_INSN (rd);
238 ddg_node_ptr src_node = get_node_of_insn (g, def_insn);
239
240 /* Create and inter-loop true dependence between RD and each of its uses
241 that is upwards exposed in RD's block. */
242 for (r_use = DF_REF_CHAIN (rd); r_use != NULL; r_use = r_use->next)
243 {
244 if (bitmap_bit_p (bb_info->gen, r_use->ref->id))
245 {
246 rtx use_insn = DF_REF_INSN (r_use->ref);
247 ddg_node_ptr dest_node = get_node_of_insn (g, use_insn);
248
249 gcc_assert (src_node && dest_node);
250
251 /* Any such upwards exposed use appears before the rd def. */
252 use_before_def = true;
253 create_ddg_dep_no_link (g, src_node, dest_node, TRUE_DEP,
254 REG_DEP, 1);
255 }
256 }
257
258 /* Create an inter-loop output dependence between RD (which is the
259 last def in its block, being downwards exposed) and the first def
260 in its block. Avoid creating a self output dependence. Avoid creating
261 an output dependence if there is a dependence path between the two defs
262 starting with a true dependence followed by an anti dependence (i.e. if
263 there is a use between the two defs. */
264 if (! use_before_def)
265 {
266 struct df_ref *def = df_bb_regno_first_def_find (g->bb, regno);
267 int i;
268 ddg_node_ptr dest_node;
269
270 if (!def || rd->id == def->id)
271 return;
272
273 /* Check if there are uses after RD. */
274 for (i = src_node->cuid + 1; i < g->num_nodes; i++)
275 if (df_find_use (g->nodes[i].insn, DF_REF_REG (rd)))
276 return;
277
278 dest_node = get_node_of_insn (g, def->insn);
279 create_ddg_dep_no_link (g, src_node, dest_node, OUTPUT_DEP, REG_DEP, 1);
280 }
281 }
282
283 /* Given a register USE, add an inter-loop anti dependence to the first
284 (nearest BLOCK_BEGIN) def of the next iteration, unless USE is followed
285 by a def in the block. */
286 static void
287 add_deps_for_use (ddg_ptr g, struct df_ref *use)
288 {
289 int i;
290 int regno = DF_REF_REGNO (use);
291 struct df_ref *first_def = df_bb_regno_first_def_find (g->bb, regno);
292 ddg_node_ptr use_node;
293 ddg_node_ptr def_node;
294 struct df_rd_bb_info *bb_info;
295
296 bb_info = DF_RD_BB_INFO (g->bb);
297
298 if (!first_def)
299 return;
300
301 use_node = get_node_of_insn (g, use->insn);
302 def_node = get_node_of_insn (g, first_def->insn);
303
304 gcc_assert (use_node && def_node);
305
306 /* Make sure there are no defs after USE. */
307 for (i = use_node->cuid + 1; i < g->num_nodes; i++)
308 if (df_find_def (g->nodes[i].insn, DF_REF_REG (use)))
309 return;
310 /* We must not add ANTI dep when there is an intra-loop TRUE dep in
311 the opposite direction. If the first_def reaches the USE then there is
312 such a dep. */
313 if (! bitmap_bit_p (bb_info->gen, first_def->id))
314 create_ddg_dep_no_link (g, use_node, def_node, ANTI_DEP, REG_DEP, 1);
315 }
316
317 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
318 static void
319 build_inter_loop_deps (ddg_ptr g)
320 {
321 unsigned rd_num, u_num;
322 struct df_rd_bb_info *rd_bb_info;
323 struct df_ru_bb_info *ru_bb_info;
324 bitmap_iterator bi;
325
326 rd_bb_info = DF_RD_BB_INFO (g->bb);
327
328 /* Find inter-loop output and true deps by connecting downward exposed defs
329 to the first def of the BB and to upwards exposed uses. */
330 EXECUTE_IF_SET_IN_BITMAP (rd_bb_info->gen, 0, rd_num, bi)
331 {
332 struct df_ref *rd = DF_DEFS_GET (rd_num);
333
334 add_deps_for_def (g, rd);
335 }
336
337 ru_bb_info = DF_RU_BB_INFO (g->bb);
338
339 /* Find inter-loop anti deps. We are interested in uses of the block that
340 appear below all defs; this implies that these uses are killed. */
341 EXECUTE_IF_SET_IN_BITMAP (ru_bb_info->kill, 0, u_num, bi)
342 {
343 struct df_ref *use = DF_USES_GET (u_num);
344 if (!(DF_REF_FLAGS (use) & DF_REF_IN_NOTE))
345 /* We are interested in uses of this BB. */
346 if (BLOCK_FOR_INSN (use->insn) == g->bb)
347 add_deps_for_use (g, use);
348 }
349 }
350
351 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
352 to ddg G. */
353 static void
354 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
355 {
356 if (mem_write_insn_p (from->insn))
357 {
358 if (mem_read_insn_p (to->insn))
359 create_ddg_dep_no_link (g, from, to, TRUE_DEP, MEM_DEP, 1);
360 else if (from->cuid != to->cuid)
361 create_ddg_dep_no_link (g, from, to, OUTPUT_DEP, MEM_DEP, 1);
362 }
363 else
364 {
365 if (mem_read_insn_p (to->insn))
366 return;
367 else if (from->cuid != to->cuid)
368 {
369 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
370 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
371 }
372 }
373
374 }
375
376 /* Perform intra-block Data Dependency analysis and connect the nodes in
377 the DDG. We assume the loop has a single basic block. */
378 static void
379 build_intra_loop_deps (ddg_ptr g)
380 {
381 int i;
382 /* Hold the dependency analysis state during dependency calculations. */
383 struct deps tmp_deps;
384 rtx head, tail;
385 dep_link_t link;
386
387 /* Build the dependence information, using the sched_analyze function. */
388 init_deps_global ();
389 init_deps (&tmp_deps);
390
391 /* Do the intra-block data dependence analysis for the given block. */
392 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
393 sched_analyze (&tmp_deps, head, tail);
394
395 /* Build intra-loop data dependencies using the scheduler dependency
396 analysis. */
397 for (i = 0; i < g->num_nodes; i++)
398 {
399 ddg_node_ptr dest_node = &g->nodes[i];
400
401 if (! INSN_P (dest_node->insn))
402 continue;
403
404 FOR_EACH_DEP_LINK (link, INSN_BACK_DEPS (dest_node->insn))
405 {
406 dep_t dep = DEP_LINK_DEP (link);
407 ddg_node_ptr src_node = get_node_of_insn (g, DEP_PRO (dep));
408
409 if (!src_node)
410 continue;
411
412 add_forw_dep (link);
413 create_ddg_dependence (g, src_node, dest_node, dep);
414 }
415
416 /* If this insn modifies memory, add an edge to all insns that access
417 memory. */
418 if (mem_access_insn_p (dest_node->insn))
419 {
420 int j;
421
422 for (j = 0; j <= i; j++)
423 {
424 ddg_node_ptr j_node = &g->nodes[j];
425 if (mem_access_insn_p (j_node->insn))
426 /* Don't bother calculating inter-loop dep if an intra-loop dep
427 already exists. */
428 if (! TEST_BIT (dest_node->successors, j))
429 add_inter_loop_mem_dep (g, dest_node, j_node);
430 }
431 }
432 }
433
434 /* Free the INSN_LISTs. */
435 finish_deps_global ();
436 free_deps (&tmp_deps);
437 }
438
439
440 /* Given a basic block, create its DDG and return a pointer to a variable
441 of ddg type that represents it.
442 Initialize the ddg structure fields to the appropriate values. */
443 ddg_ptr
444 create_ddg (basic_block bb, int closing_branch_deps)
445 {
446 ddg_ptr g;
447 rtx insn, first_note;
448 int i;
449 int num_nodes = 0;
450
451 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
452
453 g->bb = bb;
454 g->closing_branch_deps = closing_branch_deps;
455
456 /* Count the number of insns in the BB. */
457 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
458 insn = NEXT_INSN (insn))
459 {
460 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
461 continue;
462
463 if (mem_read_insn_p (insn))
464 g->num_loads++;
465 if (mem_write_insn_p (insn))
466 g->num_stores++;
467 num_nodes++;
468 }
469
470 /* There is nothing to do for this BB. */
471 if (num_nodes <= 1)
472 {
473 free (g);
474 return NULL;
475 }
476
477 /* Allocate the nodes array, and initialize the nodes. */
478 g->num_nodes = num_nodes;
479 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
480 g->closing_branch = NULL;
481 i = 0;
482 first_note = NULL_RTX;
483 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
484 insn = NEXT_INSN (insn))
485 {
486 if (! INSN_P (insn))
487 {
488 if (! first_note && NOTE_P (insn)
489 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
490 first_note = insn;
491 continue;
492 }
493 if (JUMP_P (insn))
494 {
495 gcc_assert (!g->closing_branch);
496 g->closing_branch = &g->nodes[i];
497 }
498 else if (GET_CODE (PATTERN (insn)) == USE)
499 {
500 if (! first_note)
501 first_note = insn;
502 continue;
503 }
504
505 g->nodes[i].cuid = i;
506 g->nodes[i].successors = sbitmap_alloc (num_nodes);
507 sbitmap_zero (g->nodes[i].successors);
508 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
509 sbitmap_zero (g->nodes[i].predecessors);
510 g->nodes[i].first_note = (first_note ? first_note : insn);
511 g->nodes[i++].insn = insn;
512 first_note = NULL_RTX;
513 }
514
515 /* We must have found a branch in DDG. */
516 gcc_assert (g->closing_branch);
517
518
519 /* Build the data dependency graph. */
520 build_intra_loop_deps (g);
521 build_inter_loop_deps (g);
522 return g;
523 }
524
525 /* Free all the memory allocated for the DDG. */
526 void
527 free_ddg (ddg_ptr g)
528 {
529 int i;
530
531 if (!g)
532 return;
533
534 for (i = 0; i < g->num_nodes; i++)
535 {
536 ddg_edge_ptr e = g->nodes[i].out;
537
538 while (e)
539 {
540 ddg_edge_ptr next = e->next_out;
541
542 free (e);
543 e = next;
544 }
545 sbitmap_free (g->nodes[i].successors);
546 sbitmap_free (g->nodes[i].predecessors);
547 }
548 if (g->num_backarcs > 0)
549 free (g->backarcs);
550 free (g->nodes);
551 free (g);
552 }
553
554 void
555 print_ddg_edge (FILE *file, ddg_edge_ptr e)
556 {
557 char dep_c;
558
559 switch (e->type)
560 {
561 case OUTPUT_DEP :
562 dep_c = 'O';
563 break;
564 case ANTI_DEP :
565 dep_c = 'A';
566 break;
567 default:
568 dep_c = 'T';
569 }
570
571 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
572 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
573 }
574
575 /* Print the DDG nodes with there in/out edges to the dump file. */
576 void
577 print_ddg (FILE *file, ddg_ptr g)
578 {
579 int i;
580
581 for (i = 0; i < g->num_nodes; i++)
582 {
583 ddg_edge_ptr e;
584
585 print_rtl_single (file, g->nodes[i].insn);
586 fprintf (file, "OUT ARCS: ");
587 for (e = g->nodes[i].out; e; e = e->next_out)
588 print_ddg_edge (file, e);
589
590 fprintf (file, "\nIN ARCS: ");
591 for (e = g->nodes[i].in; e; e = e->next_in)
592 print_ddg_edge (file, e);
593
594 fprintf (file, "\n");
595 }
596 }
597
598 /* Print the given DDG in VCG format. */
599 void
600 vcg_print_ddg (FILE *file, ddg_ptr g)
601 {
602 int src_cuid;
603
604 fprintf (file, "graph: {\n");
605 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
606 {
607 ddg_edge_ptr e;
608 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
609
610 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
611 print_rtl_single (file, g->nodes[src_cuid].insn);
612 fprintf (file, "\"}\n");
613 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
614 {
615 int dst_uid = INSN_UID (e->dest->insn);
616 int dst_cuid = e->dest->cuid;
617
618 /* Give the backarcs a different color. */
619 if (e->distance > 0)
620 fprintf (file, "backedge: {color: red ");
621 else
622 fprintf (file, "edge: { ");
623
624 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
625 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
626 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
627 }
628 }
629 fprintf (file, "}\n");
630 }
631
632 /* Dump the sccs in SCCS. */
633 void
634 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
635 {
636 unsigned int u = 0;
637 sbitmap_iterator sbi;
638 int i;
639
640 if (!file)
641 return;
642
643 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
644 for (i = 0; i < sccs->num_sccs; i++)
645 {
646 fprintf (file, "SCC number: %d\n", i);
647 EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
648 {
649 fprintf (file, "insn num %d\n", u);
650 print_rtl_single (file, g->nodes[u].insn);
651 }
652 }
653 fprintf (file, "\n");
654 }
655
656 /* Create an edge and initialize it with given values. */
657 static ddg_edge_ptr
658 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
659 dep_type t, dep_data_type dt, int l, int d)
660 {
661 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
662
663 e->src = src;
664 e->dest = dest;
665 e->type = t;
666 e->data_type = dt;
667 e->latency = l;
668 e->distance = d;
669 e->next_in = e->next_out = NULL;
670 e->aux.info = 0;
671 return e;
672 }
673
674 /* Add the given edge to the in/out linked lists of the DDG nodes. */
675 static void
676 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
677 {
678 ddg_node_ptr src = e->src;
679 ddg_node_ptr dest = e->dest;
680
681 /* Should have allocated the sbitmaps. */
682 gcc_assert (src->successors && dest->predecessors);
683
684 SET_BIT (src->successors, dest->cuid);
685 SET_BIT (dest->predecessors, src->cuid);
686 e->next_in = dest->in;
687 dest->in = e;
688 e->next_out = src->out;
689 src->out = e;
690 }
691
692
693 \f
694 /* Algorithm for computing the recurrence_length of an scc. We assume at
695 for now that cycles in the data dependence graph contain a single backarc.
696 This simplifies the algorithm, and can be generalized later. */
697 static void
698 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
699 {
700 int j;
701 int result = -1;
702
703 for (j = 0; j < scc->num_backarcs; j++)
704 {
705 ddg_edge_ptr backarc = scc->backarcs[j];
706 int length;
707 int distance = backarc->distance;
708 ddg_node_ptr src = backarc->dest;
709 ddg_node_ptr dest = backarc->src;
710
711 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
712 if (length < 0 )
713 {
714 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
715 continue;
716 }
717 length += backarc->latency;
718 result = MAX (result, (length / distance));
719 }
720 scc->recurrence_length = result;
721 }
722
723 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
724 and mark edges that belong to this scc as IN_SCC. */
725 static ddg_scc_ptr
726 create_scc (ddg_ptr g, sbitmap nodes)
727 {
728 ddg_scc_ptr scc;
729 unsigned int u = 0;
730 sbitmap_iterator sbi;
731
732 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
733 scc->backarcs = NULL;
734 scc->num_backarcs = 0;
735 scc->nodes = sbitmap_alloc (g->num_nodes);
736 sbitmap_copy (scc->nodes, nodes);
737
738 /* Mark the backarcs that belong to this SCC. */
739 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
740 {
741 ddg_edge_ptr e;
742 ddg_node_ptr n = &g->nodes[u];
743
744 for (e = n->out; e; e = e->next_out)
745 if (TEST_BIT (nodes, e->dest->cuid))
746 {
747 e->aux.count = IN_SCC;
748 if (e->distance > 0)
749 add_backarc_to_scc (scc, e);
750 }
751 }
752
753 set_recurrence_length (scc, g);
754 return scc;
755 }
756
757 /* Cleans the memory allocation of a given SCC. */
758 static void
759 free_scc (ddg_scc_ptr scc)
760 {
761 if (!scc)
762 return;
763
764 sbitmap_free (scc->nodes);
765 if (scc->num_backarcs > 0)
766 free (scc->backarcs);
767 free (scc);
768 }
769
770
771 /* Add a given edge known to be a backarc to the given DDG. */
772 static void
773 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
774 {
775 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
776
777 add_edge_to_ddg (g, e);
778 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
779 g->backarcs[g->num_backarcs++] = e;
780 }
781
782 /* Add backarc to an SCC. */
783 static void
784 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
785 {
786 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
787
788 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
789 scc->backarcs[scc->num_backarcs++] = e;
790 }
791
792 /* Add the given SCC to the DDG. */
793 static void
794 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
795 {
796 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
797
798 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
799 g->sccs[g->num_sccs++] = scc;
800 }
801
802 /* Given the instruction INSN return the node that represents it. */
803 ddg_node_ptr
804 get_node_of_insn (ddg_ptr g, rtx insn)
805 {
806 int i;
807
808 for (i = 0; i < g->num_nodes; i++)
809 if (insn == g->nodes[i].insn)
810 return &g->nodes[i];
811 return NULL;
812 }
813
814 /* Given a set OPS of nodes in the DDG, find the set of their successors
815 which are not in OPS, and set their bits in SUCC. Bits corresponding to
816 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
817 void
818 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
819 {
820 unsigned int i = 0;
821 sbitmap_iterator sbi;
822
823 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
824 {
825 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
826 sbitmap_a_or_b (succ, succ, node_succ);
827 };
828
829 /* We want those that are not in ops. */
830 sbitmap_difference (succ, succ, ops);
831 }
832
833 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
834 which are not in OPS, and set their bits in PREDS. Bits corresponding to
835 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
836 void
837 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
838 {
839 unsigned int i = 0;
840 sbitmap_iterator sbi;
841
842 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
843 {
844 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
845 sbitmap_a_or_b (preds, preds, node_preds);
846 };
847
848 /* We want those that are not in ops. */
849 sbitmap_difference (preds, preds, ops);
850 }
851
852
853 /* Compare function to be passed to qsort to order the backarcs in descending
854 recMII order. */
855 static int
856 compare_sccs (const void *s1, const void *s2)
857 {
858 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
859 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
860 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
861
862 }
863
864 /* Order the backarcs in descending recMII order using compare_sccs. */
865 static void
866 order_sccs (ddg_all_sccs_ptr g)
867 {
868 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
869 (int (*) (const void *, const void *)) compare_sccs);
870 }
871
872 #ifdef ENABLE_CHECKING
873 /* Check that every node in SCCS belongs to exactly one strongly connected
874 component and that no element of SCCS is empty. */
875 static void
876 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
877 {
878 int i = 0;
879 sbitmap tmp = sbitmap_alloc (num_nodes);
880
881 sbitmap_zero (tmp);
882 for (i = 0; i < sccs->num_sccs; i++)
883 {
884 gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes));
885 /* Verify that every node in sccs is in exactly one strongly
886 connected component. */
887 gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes));
888 sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes);
889 }
890 sbitmap_free (tmp);
891 }
892 #endif
893
894 /* Perform the Strongly Connected Components decomposing algorithm on the
895 DDG and return DDG_ALL_SCCS structure that contains them. */
896 ddg_all_sccs_ptr
897 create_ddg_all_sccs (ddg_ptr g)
898 {
899 int i;
900 int num_nodes = g->num_nodes;
901 sbitmap from = sbitmap_alloc (num_nodes);
902 sbitmap to = sbitmap_alloc (num_nodes);
903 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
904 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
905 xmalloc (sizeof (struct ddg_all_sccs));
906
907 sccs->ddg = g;
908 sccs->sccs = NULL;
909 sccs->num_sccs = 0;
910
911 for (i = 0; i < g->num_backarcs; i++)
912 {
913 ddg_scc_ptr scc;
914 ddg_edge_ptr backarc = g->backarcs[i];
915 ddg_node_ptr src = backarc->src;
916 ddg_node_ptr dest = backarc->dest;
917
918 /* If the backarc already belongs to an SCC, continue. */
919 if (backarc->aux.count == IN_SCC)
920 continue;
921
922 sbitmap_zero (scc_nodes);
923 sbitmap_zero (from);
924 sbitmap_zero (to);
925 SET_BIT (from, dest->cuid);
926 SET_BIT (to, src->cuid);
927
928 if (find_nodes_on_paths (scc_nodes, g, from, to))
929 {
930 scc = create_scc (g, scc_nodes);
931 add_scc_to_ddg (sccs, scc);
932 }
933 }
934 order_sccs (sccs);
935 sbitmap_free (from);
936 sbitmap_free (to);
937 sbitmap_free (scc_nodes);
938 #ifdef ENABLE_CHECKING
939 check_sccs (sccs, num_nodes);
940 #endif
941 return sccs;
942 }
943
944 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
945 void
946 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
947 {
948 int i;
949
950 if (!all_sccs)
951 return;
952
953 for (i = 0; i < all_sccs->num_sccs; i++)
954 free_scc (all_sccs->sccs[i]);
955
956 free (all_sccs);
957 }
958
959 \f
960 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
961 nodes - find all nodes that lie on paths from FROM to TO (not excluding
962 nodes from FROM and TO). Return nonzero if nodes exist. */
963 int
964 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
965 {
966 int answer;
967 int change;
968 unsigned int u = 0;
969 int num_nodes = g->num_nodes;
970 sbitmap_iterator sbi;
971
972 sbitmap workset = sbitmap_alloc (num_nodes);
973 sbitmap reachable_from = sbitmap_alloc (num_nodes);
974 sbitmap reach_to = sbitmap_alloc (num_nodes);
975 sbitmap tmp = sbitmap_alloc (num_nodes);
976
977 sbitmap_copy (reachable_from, from);
978 sbitmap_copy (tmp, from);
979
980 change = 1;
981 while (change)
982 {
983 change = 0;
984 sbitmap_copy (workset, tmp);
985 sbitmap_zero (tmp);
986 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
987 {
988 ddg_edge_ptr e;
989 ddg_node_ptr u_node = &g->nodes[u];
990
991 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
992 {
993 ddg_node_ptr v_node = e->dest;
994 int v = v_node->cuid;
995
996 if (!TEST_BIT (reachable_from, v))
997 {
998 SET_BIT (reachable_from, v);
999 SET_BIT (tmp, v);
1000 change = 1;
1001 }
1002 }
1003 }
1004 }
1005
1006 sbitmap_copy (reach_to, to);
1007 sbitmap_copy (tmp, to);
1008
1009 change = 1;
1010 while (change)
1011 {
1012 change = 0;
1013 sbitmap_copy (workset, tmp);
1014 sbitmap_zero (tmp);
1015 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1016 {
1017 ddg_edge_ptr e;
1018 ddg_node_ptr u_node = &g->nodes[u];
1019
1020 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1021 {
1022 ddg_node_ptr v_node = e->src;
1023 int v = v_node->cuid;
1024
1025 if (!TEST_BIT (reach_to, v))
1026 {
1027 SET_BIT (reach_to, v);
1028 SET_BIT (tmp, v);
1029 change = 1;
1030 }
1031 }
1032 }
1033 }
1034
1035 answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
1036 sbitmap_free (workset);
1037 sbitmap_free (reachable_from);
1038 sbitmap_free (reach_to);
1039 sbitmap_free (tmp);
1040 return answer;
1041 }
1042
1043
1044 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1045 at-least as large as the count of U_NODE plus the latency between them.
1046 Sets a bit in TMP for each successor whose count was changed (increased).
1047 Returns nonzero if any count was changed. */
1048 static int
1049 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1050 {
1051 ddg_edge_ptr e;
1052 int result = 0;
1053
1054 for (e = u_node->out; e; e = e->next_out)
1055 {
1056 ddg_node_ptr v_node = e->dest;
1057 int v = v_node->cuid;
1058
1059 if (TEST_BIT (nodes, v)
1060 && (e->distance == 0)
1061 && (v_node->aux.count < u_node->aux.count + e->latency))
1062 {
1063 v_node->aux.count = u_node->aux.count + e->latency;
1064 SET_BIT (tmp, v);
1065 result = 1;
1066 }
1067 }
1068 return result;
1069 }
1070
1071
1072 /* Find the length of a longest path from SRC to DEST in G,
1073 going only through NODES, and disregarding backarcs. */
1074 int
1075 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1076 {
1077 int i;
1078 unsigned int u = 0;
1079 int change = 1;
1080 int result;
1081 int num_nodes = g->num_nodes;
1082 sbitmap workset = sbitmap_alloc (num_nodes);
1083 sbitmap tmp = sbitmap_alloc (num_nodes);
1084
1085
1086 /* Data will hold the distance of the longest path found so far from
1087 src to each node. Initialize to -1 = less than minimum. */
1088 for (i = 0; i < g->num_nodes; i++)
1089 g->nodes[i].aux.count = -1;
1090 g->nodes[src].aux.count = 0;
1091
1092 sbitmap_zero (tmp);
1093 SET_BIT (tmp, src);
1094
1095 while (change)
1096 {
1097 sbitmap_iterator sbi;
1098
1099 change = 0;
1100 sbitmap_copy (workset, tmp);
1101 sbitmap_zero (tmp);
1102 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1103 {
1104 ddg_node_ptr u_node = &g->nodes[u];
1105
1106 change |= update_dist_to_successors (u_node, nodes, tmp);
1107 }
1108 }
1109 result = g->nodes[dest].aux.count;
1110 sbitmap_free (workset);
1111 sbitmap_free (tmp);
1112 return result;
1113 }