quick commit
[official-gcc.git] / gcc / ddg.c
blob07dcde02d261e8aa87177ea6620a264d4007b9c7
1 /* DDG - Data Dependence Graph implementation.
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
6 This file is part of GCC.
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.
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.
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/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "diagnostic-core.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"
47 #ifdef INSN_SCHEDULING
49 /* A flag indicating that a ddg edge belongs to an SCC or not. */
50 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
52 /* Forward declarations. */
53 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
54 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
55 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
56 static void create_ddg_dep_from_intra_loop_link (ddg_ptr, ddg_node_ptr,
57 ddg_node_ptr, dep_t);
58 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
59 dep_type, dep_data_type, int);
60 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
61 dep_data_type, int, int);
62 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
64 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
65 static bool mem_ref_p;
67 /* Auxiliary function for mem_read_insn_p. */
68 static int
69 mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
71 if (MEM_P (*x))
72 mem_ref_p = true;
73 return 0;
76 /* Auxiliary function for mem_read_insn_p. */
77 static void
78 mark_mem_use_1 (rtx *x, void *data)
80 for_each_rtx (x, mark_mem_use, data);
83 /* Returns nonzero if INSN reads from memory. */
84 static bool
85 mem_read_insn_p (rtx insn)
87 mem_ref_p = false;
88 note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
89 return mem_ref_p;
92 static void
93 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
95 if (MEM_P (loc))
96 mem_ref_p = true;
99 /* Returns nonzero if INSN writes to memory. */
100 static bool
101 mem_write_insn_p (rtx insn)
103 mem_ref_p = false;
104 note_stores (PATTERN (insn), mark_mem_store, NULL);
105 return mem_ref_p;
108 /* Returns nonzero if X has access to memory. */
109 static bool
110 rtx_mem_access_p (rtx x)
112 int i, j;
113 const char *fmt;
114 enum rtx_code code;
116 if (x == 0)
117 return false;
119 if (MEM_P (x))
120 return true;
122 code = GET_CODE (x);
123 fmt = GET_RTX_FORMAT (code);
124 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
126 if (fmt[i] == 'e')
128 if (rtx_mem_access_p (XEXP (x, i)))
129 return true;
131 else if (fmt[i] == 'E')
132 for (j = 0; j < XVECLEN (x, i); j++)
134 if (rtx_mem_access_p (XVECEXP (x, i, j)))
135 return true;
138 return false;
141 /* Returns nonzero if INSN reads to or writes from memory. */
142 static bool
143 mem_access_insn_p (rtx insn)
145 return rtx_mem_access_p (PATTERN (insn));
148 /* Computes the dependence parameters (latency, distance etc.), creates
149 a ddg_edge and adds it to the given DDG. */
150 static void
151 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
152 ddg_node_ptr dest_node, dep_t link)
154 ddg_edge_ptr e;
155 int latency, distance = 0;
156 dep_type t = TRUE_DEP;
157 dep_data_type dt = (mem_access_insn_p (src_node->insn)
158 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
159 : REG_DEP);
160 gcc_assert (src_node->cuid < dest_node->cuid);
161 gcc_assert (link);
163 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
164 if (DEP_TYPE (link) == REG_DEP_ANTI)
165 t = ANTI_DEP;
166 else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
167 t = OUTPUT_DEP;
169 gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
170 gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
172 /* We currently choose not to create certain anti-deps edges and
173 compensate for that by generating reg-moves based on the life-range
174 analysis. The anti-deps that will be deleted are the ones which
175 have true-deps edges in the opposite direction (in other words
176 the kernel has only one def of the relevant register). TODO:
177 support the removal of all anti-deps edges, i.e. including those
178 whose register has multiple defs in the loop. */
179 if (flag_modulo_sched_allow_regmoves && (t == ANTI_DEP && dt == REG_DEP))
181 rtx set;
183 set = single_set (dest_node->insn);
184 /* TODO: Handle registers that REG_P is not true for them, i.e.
185 subregs and special registers. */
186 if (set && REG_P (SET_DEST (set)))
188 int regno = REGNO (SET_DEST (set));
189 df_ref first_def;
190 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
192 first_def = df_bb_regno_first_def_find (g->bb, regno);
193 gcc_assert (first_def);
195 if (bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)))
196 return;
200 latency = dep_cost (link);
201 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
202 add_edge_to_ddg (g, e);
205 /* The same as the above function, but it doesn't require a link parameter. */
206 static void
207 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
208 dep_type d_t, dep_data_type d_dt, int distance)
210 ddg_edge_ptr e;
211 int l;
212 enum reg_note dep_kind;
213 struct _dep _dep, *dep = &_dep;
215 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
216 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
218 if (d_t == ANTI_DEP)
219 dep_kind = REG_DEP_ANTI;
220 else if (d_t == OUTPUT_DEP)
221 dep_kind = REG_DEP_OUTPUT;
222 else
224 gcc_assert (d_t == TRUE_DEP);
226 dep_kind = REG_DEP_TRUE;
229 init_dep (dep, from->insn, to->insn, dep_kind);
231 l = dep_cost (dep);
233 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
234 if (distance > 0)
235 add_backarc_to_ddg (g, e);
236 else
237 add_edge_to_ddg (g, e);
241 /* Given a downwards exposed register def LAST_DEF (which is the last
242 definition of that register in the bb), add inter-loop true dependences
243 to all its uses in the next iteration, an output dependence to the
244 first def of the same register (possibly itself) in the next iteration
245 and anti-dependences from its uses in the current iteration to the
246 first definition in the next iteration. */
247 static void
248 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
250 int regno = DF_REF_REGNO (last_def);
251 struct df_link *r_use;
252 int has_use_in_bb_p = false;
253 rtx def_insn = DF_REF_INSN (last_def);
254 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
255 ddg_node_ptr use_node;
256 #ifdef ENABLE_CHECKING
257 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
258 #endif
259 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
261 gcc_assert (last_def_node);
262 gcc_assert (first_def);
264 #ifdef ENABLE_CHECKING
265 if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
266 gcc_assert (!bitmap_bit_p (&bb_info->gen,
267 DF_REF_ID (first_def)));
268 #endif
270 /* Create inter-loop true dependences and anti dependences. */
271 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
273 rtx use_insn = DF_REF_INSN (r_use->ref);
275 if (BLOCK_FOR_INSN (use_insn) != g->bb)
276 continue;
278 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
279 use_node = get_node_of_insn (g, use_insn);
280 gcc_assert (use_node);
281 has_use_in_bb_p = true;
282 if (use_node->cuid <= last_def_node->cuid)
284 /* Add true deps from last_def to it's uses in the next
285 iteration. Any such upwards exposed use appears before
286 the last_def def. */
287 create_ddg_dep_no_link (g, last_def_node, use_node,
288 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
289 REG_DEP, 1);
291 else if (!DEBUG_INSN_P (use_insn))
293 /* Add anti deps from last_def's uses in the current iteration
294 to the first def in the next iteration. We do not add ANTI
295 dep when there is an intra-loop TRUE dep in the opposite
296 direction, but use regmoves to fix such disregarded ANTI
297 deps when broken. If the first_def reaches the USE then
298 there is such a dep. */
299 ddg_node_ptr first_def_node = get_node_of_insn (g,
300 DF_REF_INSN (first_def));
302 gcc_assert (first_def_node);
304 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
305 || !flag_modulo_sched_allow_regmoves)
306 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
307 REG_DEP, 1);
311 /* Create an inter-loop output dependence between LAST_DEF (which is the
312 last def in its block, being downwards exposed) and the first def in
313 its block. Avoid creating a self output dependence. Avoid creating
314 an output dependence if there is a dependence path between the two
315 defs starting with a true dependence to a use which can be in the
316 next iteration; followed by an anti dependence of that use to the
317 first def (i.e. if there is a use between the two defs.) */
318 if (!has_use_in_bb_p)
320 ddg_node_ptr dest_node;
322 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
323 return;
325 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
326 gcc_assert (dest_node);
327 create_ddg_dep_no_link (g, last_def_node, dest_node,
328 OUTPUT_DEP, REG_DEP, 1);
331 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
332 static void
333 build_inter_loop_deps (ddg_ptr g)
335 unsigned rd_num;
336 struct df_rd_bb_info *rd_bb_info;
337 bitmap_iterator bi;
339 rd_bb_info = DF_RD_BB_INFO (g->bb);
341 /* Find inter-loop register output, true and anti deps. */
342 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
344 df_ref rd = DF_DEFS_GET (rd_num);
346 add_cross_iteration_register_deps (g, rd);
351 static int
352 walk_mems_2 (rtx *x, rtx mem)
354 if (MEM_P (*x))
356 if (may_alias_p (*x, mem))
357 return 1;
359 return -1;
361 return 0;
364 static int
365 walk_mems_1 (rtx *x, rtx *pat)
367 if (MEM_P (*x))
369 /* Visit all MEMs in *PAT and check indepedence. */
370 if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x))
371 /* Indicate that dependence was determined and stop traversal. */
372 return 1;
374 return -1;
376 return 0;
379 /* Return 1 if two specified instructions have mem expr with conflict alias sets*/
380 static int
381 insns_may_alias_p (rtx insn1, rtx insn2)
383 /* For each pair of MEMs in INSN1 and INSN2 check their independence. */
384 return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1,
385 &PATTERN (insn2));
388 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
389 to ddg G. */
390 static void
391 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
393 if (!insns_may_alias_p (from->insn, to->insn))
394 /* Do not create edge if memory references have disjoint alias sets. */
395 return;
397 if (mem_write_insn_p (from->insn))
399 if (mem_read_insn_p (to->insn))
400 create_ddg_dep_no_link (g, from, to,
401 DEBUG_INSN_P (to->insn)
402 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
403 else if (from->cuid != to->cuid)
404 create_ddg_dep_no_link (g, from, to,
405 DEBUG_INSN_P (to->insn)
406 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
408 else
410 if (mem_read_insn_p (to->insn))
411 return;
412 else if (from->cuid != to->cuid)
414 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
415 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
416 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
417 else
418 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
424 /* Perform intra-block Data Dependency analysis and connect the nodes in
425 the DDG. We assume the loop has a single basic block. */
426 static void
427 build_intra_loop_deps (ddg_ptr g)
429 int i;
430 /* Hold the dependency analysis state during dependency calculations. */
431 struct deps_desc tmp_deps;
432 rtx head, tail;
434 /* Build the dependence information, using the sched_analyze function. */
435 init_deps_global ();
436 init_deps (&tmp_deps, false);
438 /* Do the intra-block data dependence analysis for the given block. */
439 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
440 sched_analyze (&tmp_deps, head, tail);
442 /* Build intra-loop data dependencies using the scheduler dependency
443 analysis. */
444 for (i = 0; i < g->num_nodes; i++)
446 ddg_node_ptr dest_node = &g->nodes[i];
447 sd_iterator_def sd_it;
448 dep_t dep;
450 if (! INSN_P (dest_node->insn))
451 continue;
453 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
455 ddg_node_ptr src_node = get_node_of_insn (g, DEP_PRO (dep));
457 if (!src_node)
458 continue;
460 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
463 /* If this insn modifies memory, add an edge to all insns that access
464 memory. */
465 if (mem_access_insn_p (dest_node->insn))
467 int j;
469 for (j = 0; j <= i; j++)
471 ddg_node_ptr j_node = &g->nodes[j];
472 if (DEBUG_INSN_P (j_node->insn))
473 continue;
474 if (mem_access_insn_p (j_node->insn))
475 /* Don't bother calculating inter-loop dep if an intra-loop dep
476 already exists. */
477 if (! TEST_BIT (dest_node->successors, j))
478 add_inter_loop_mem_dep (g, dest_node, j_node);
483 /* Free the INSN_LISTs. */
484 finish_deps_global ();
485 free_deps (&tmp_deps);
487 /* Free dependencies. */
488 sched_free_deps (head, tail, false);
492 /* Given a basic block, create its DDG and return a pointer to a variable
493 of ddg type that represents it.
494 Initialize the ddg structure fields to the appropriate values. */
495 ddg_ptr
496 create_ddg (basic_block bb, int closing_branch_deps)
498 ddg_ptr g;
499 rtx insn, first_note;
500 int i;
501 int num_nodes = 0;
503 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
505 g->bb = bb;
506 g->closing_branch_deps = closing_branch_deps;
508 /* Count the number of insns in the BB. */
509 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
510 insn = NEXT_INSN (insn))
512 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
513 continue;
515 if (DEBUG_INSN_P (insn))
516 g->num_debug++;
517 else
519 if (mem_read_insn_p (insn))
520 g->num_loads++;
521 if (mem_write_insn_p (insn))
522 g->num_stores++;
524 num_nodes++;
527 /* There is nothing to do for this BB. */
528 if ((num_nodes - g->num_debug) <= 1)
530 free (g);
531 return NULL;
534 /* Allocate the nodes array, and initialize the nodes. */
535 g->num_nodes = num_nodes;
536 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
537 g->closing_branch = NULL;
538 i = 0;
539 first_note = NULL_RTX;
540 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
541 insn = NEXT_INSN (insn))
543 if (! INSN_P (insn))
545 if (! first_note && NOTE_P (insn)
546 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
547 first_note = insn;
548 continue;
550 if (JUMP_P (insn))
552 gcc_assert (!g->closing_branch);
553 g->closing_branch = &g->nodes[i];
555 else if (GET_CODE (PATTERN (insn)) == USE)
557 if (! first_note)
558 first_note = insn;
559 continue;
562 g->nodes[i].cuid = i;
563 g->nodes[i].successors = sbitmap_alloc (num_nodes);
564 sbitmap_zero (g->nodes[i].successors);
565 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
566 sbitmap_zero (g->nodes[i].predecessors);
567 g->nodes[i].first_note = (first_note ? first_note : insn);
568 g->nodes[i++].insn = insn;
569 first_note = NULL_RTX;
572 /* We must have found a branch in DDG. */
573 gcc_assert (g->closing_branch);
576 /* Build the data dependency graph. */
577 build_intra_loop_deps (g);
578 build_inter_loop_deps (g);
579 return g;
582 /* Free all the memory allocated for the DDG. */
583 void
584 free_ddg (ddg_ptr g)
586 int i;
588 if (!g)
589 return;
591 for (i = 0; i < g->num_nodes; i++)
593 ddg_edge_ptr e = g->nodes[i].out;
595 while (e)
597 ddg_edge_ptr next = e->next_out;
599 free (e);
600 e = next;
602 sbitmap_free (g->nodes[i].successors);
603 sbitmap_free (g->nodes[i].predecessors);
605 if (g->num_backarcs > 0)
606 free (g->backarcs);
607 free (g->nodes);
608 free (g);
611 void
612 print_ddg_edge (FILE *file, ddg_edge_ptr e)
614 char dep_c;
616 switch (e->type)
618 case OUTPUT_DEP :
619 dep_c = 'O';
620 break;
621 case ANTI_DEP :
622 dep_c = 'A';
623 break;
624 default:
625 dep_c = 'T';
628 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
629 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
632 /* Print the DDG nodes with there in/out edges to the dump file. */
633 void
634 print_ddg (FILE *file, ddg_ptr g)
636 int i;
638 for (i = 0; i < g->num_nodes; i++)
640 ddg_edge_ptr e;
642 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
643 print_rtl_single (file, g->nodes[i].insn);
644 fprintf (file, "OUT ARCS: ");
645 for (e = g->nodes[i].out; e; e = e->next_out)
646 print_ddg_edge (file, e);
648 fprintf (file, "\nIN ARCS: ");
649 for (e = g->nodes[i].in; e; e = e->next_in)
650 print_ddg_edge (file, e);
652 fprintf (file, "\n");
656 /* Print the given DDG in VCG format. */
657 void
658 vcg_print_ddg (FILE *file, ddg_ptr g)
660 int src_cuid;
662 fprintf (file, "graph: {\n");
663 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
665 ddg_edge_ptr e;
666 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
668 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
669 print_rtl_single (file, g->nodes[src_cuid].insn);
670 fprintf (file, "\"}\n");
671 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
673 int dst_uid = INSN_UID (e->dest->insn);
674 int dst_cuid = e->dest->cuid;
676 /* Give the backarcs a different color. */
677 if (e->distance > 0)
678 fprintf (file, "backedge: {color: red ");
679 else
680 fprintf (file, "edge: { ");
682 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
683 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
684 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
687 fprintf (file, "}\n");
690 /* Dump the sccs in SCCS. */
691 void
692 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
694 unsigned int u = 0;
695 sbitmap_iterator sbi;
696 int i;
698 if (!file)
699 return;
701 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
702 for (i = 0; i < sccs->num_sccs; i++)
704 fprintf (file, "SCC number: %d\n", i);
705 EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
707 fprintf (file, "insn num %d\n", u);
708 print_rtl_single (file, g->nodes[u].insn);
711 fprintf (file, "\n");
714 /* Create an edge and initialize it with given values. */
715 static ddg_edge_ptr
716 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
717 dep_type t, dep_data_type dt, int l, int d)
719 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
721 e->src = src;
722 e->dest = dest;
723 e->type = t;
724 e->data_type = dt;
725 e->latency = l;
726 e->distance = d;
727 e->next_in = e->next_out = NULL;
728 e->aux.info = 0;
729 return e;
732 /* Add the given edge to the in/out linked lists of the DDG nodes. */
733 static void
734 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
736 ddg_node_ptr src = e->src;
737 ddg_node_ptr dest = e->dest;
739 /* Should have allocated the sbitmaps. */
740 gcc_assert (src->successors && dest->predecessors);
742 SET_BIT (src->successors, dest->cuid);
743 SET_BIT (dest->predecessors, src->cuid);
744 e->next_in = dest->in;
745 dest->in = e;
746 e->next_out = src->out;
747 src->out = e;
752 /* Algorithm for computing the recurrence_length of an scc. We assume at
753 for now that cycles in the data dependence graph contain a single backarc.
754 This simplifies the algorithm, and can be generalized later. */
755 static void
756 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
758 int j;
759 int result = -1;
761 for (j = 0; j < scc->num_backarcs; j++)
763 ddg_edge_ptr backarc = scc->backarcs[j];
764 int length;
765 int distance = backarc->distance;
766 ddg_node_ptr src = backarc->dest;
767 ddg_node_ptr dest = backarc->src;
769 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
770 if (length < 0 )
772 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
773 continue;
775 length += backarc->latency;
776 result = MAX (result, (length / distance));
778 scc->recurrence_length = result;
781 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
782 and mark edges that belong to this scc as IN_SCC. */
783 static ddg_scc_ptr
784 create_scc (ddg_ptr g, sbitmap nodes)
786 ddg_scc_ptr scc;
787 unsigned int u = 0;
788 sbitmap_iterator sbi;
790 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
791 scc->backarcs = NULL;
792 scc->num_backarcs = 0;
793 scc->nodes = sbitmap_alloc (g->num_nodes);
794 sbitmap_copy (scc->nodes, nodes);
796 /* Mark the backarcs that belong to this SCC. */
797 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
799 ddg_edge_ptr e;
800 ddg_node_ptr n = &g->nodes[u];
802 for (e = n->out; e; e = e->next_out)
803 if (TEST_BIT (nodes, e->dest->cuid))
805 e->aux.count = IN_SCC;
806 if (e->distance > 0)
807 add_backarc_to_scc (scc, e);
811 set_recurrence_length (scc, g);
812 return scc;
815 /* Cleans the memory allocation of a given SCC. */
816 static void
817 free_scc (ddg_scc_ptr scc)
819 if (!scc)
820 return;
822 sbitmap_free (scc->nodes);
823 if (scc->num_backarcs > 0)
824 free (scc->backarcs);
825 free (scc);
829 /* Add a given edge known to be a backarc to the given DDG. */
830 static void
831 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
833 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
835 add_edge_to_ddg (g, e);
836 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
837 g->backarcs[g->num_backarcs++] = e;
840 /* Add backarc to an SCC. */
841 static void
842 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
844 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
846 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
847 scc->backarcs[scc->num_backarcs++] = e;
850 /* Add the given SCC to the DDG. */
851 static void
852 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
854 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
856 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
857 g->sccs[g->num_sccs++] = scc;
860 /* Given the instruction INSN return the node that represents it. */
861 ddg_node_ptr
862 get_node_of_insn (ddg_ptr g, rtx insn)
864 int i;
866 for (i = 0; i < g->num_nodes; i++)
867 if (insn == g->nodes[i].insn)
868 return &g->nodes[i];
869 return NULL;
872 /* Given a set OPS of nodes in the DDG, find the set of their successors
873 which are not in OPS, and set their bits in SUCC. Bits corresponding to
874 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
875 void
876 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
878 unsigned int i = 0;
879 sbitmap_iterator sbi;
881 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
883 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
884 sbitmap_a_or_b (succ, succ, node_succ);
887 /* We want those that are not in ops. */
888 sbitmap_difference (succ, succ, ops);
891 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
892 which are not in OPS, and set their bits in PREDS. Bits corresponding to
893 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
894 void
895 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
897 unsigned int i = 0;
898 sbitmap_iterator sbi;
900 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
902 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
903 sbitmap_a_or_b (preds, preds, node_preds);
906 /* We want those that are not in ops. */
907 sbitmap_difference (preds, preds, ops);
911 /* Compare function to be passed to qsort to order the backarcs in descending
912 recMII order. */
913 static int
914 compare_sccs (const void *s1, const void *s2)
916 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
917 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
918 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
922 /* Order the backarcs in descending recMII order using compare_sccs. */
923 static void
924 order_sccs (ddg_all_sccs_ptr g)
926 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
927 (int (*) (const void *, const void *)) compare_sccs);
930 #ifdef ENABLE_CHECKING
931 /* Check that every node in SCCS belongs to exactly one strongly connected
932 component and that no element of SCCS is empty. */
933 static void
934 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
936 int i = 0;
937 sbitmap tmp = sbitmap_alloc (num_nodes);
939 sbitmap_zero (tmp);
940 for (i = 0; i < sccs->num_sccs; i++)
942 gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes));
943 /* Verify that every node in sccs is in exactly one strongly
944 connected component. */
945 gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes));
946 sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes);
948 sbitmap_free (tmp);
950 #endif
952 /* Perform the Strongly Connected Components decomposing algorithm on the
953 DDG and return DDG_ALL_SCCS structure that contains them. */
954 ddg_all_sccs_ptr
955 create_ddg_all_sccs (ddg_ptr g)
957 int i;
958 int num_nodes = g->num_nodes;
959 sbitmap from = sbitmap_alloc (num_nodes);
960 sbitmap to = sbitmap_alloc (num_nodes);
961 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
962 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
963 xmalloc (sizeof (struct ddg_all_sccs));
965 sccs->ddg = g;
966 sccs->sccs = NULL;
967 sccs->num_sccs = 0;
969 for (i = 0; i < g->num_backarcs; i++)
971 ddg_scc_ptr scc;
972 ddg_edge_ptr backarc = g->backarcs[i];
973 ddg_node_ptr src = backarc->src;
974 ddg_node_ptr dest = backarc->dest;
976 /* If the backarc already belongs to an SCC, continue. */
977 if (backarc->aux.count == IN_SCC)
978 continue;
980 sbitmap_zero (scc_nodes);
981 sbitmap_zero (from);
982 sbitmap_zero (to);
983 SET_BIT (from, dest->cuid);
984 SET_BIT (to, src->cuid);
986 if (find_nodes_on_paths (scc_nodes, g, from, to))
988 scc = create_scc (g, scc_nodes);
989 add_scc_to_ddg (sccs, scc);
992 order_sccs (sccs);
993 sbitmap_free (from);
994 sbitmap_free (to);
995 sbitmap_free (scc_nodes);
996 #ifdef ENABLE_CHECKING
997 check_sccs (sccs, num_nodes);
998 #endif
999 return sccs;
1002 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1003 void
1004 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1006 int i;
1008 if (!all_sccs)
1009 return;
1011 for (i = 0; i < all_sccs->num_sccs; i++)
1012 free_scc (all_sccs->sccs[i]);
1014 free (all_sccs);
1018 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1019 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1020 nodes from FROM and TO). Return nonzero if nodes exist. */
1022 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1024 int answer;
1025 int change;
1026 unsigned int u = 0;
1027 int num_nodes = g->num_nodes;
1028 sbitmap_iterator sbi;
1030 sbitmap workset = sbitmap_alloc (num_nodes);
1031 sbitmap reachable_from = sbitmap_alloc (num_nodes);
1032 sbitmap reach_to = sbitmap_alloc (num_nodes);
1033 sbitmap tmp = sbitmap_alloc (num_nodes);
1035 sbitmap_copy (reachable_from, from);
1036 sbitmap_copy (tmp, from);
1038 change = 1;
1039 while (change)
1041 change = 0;
1042 sbitmap_copy (workset, tmp);
1043 sbitmap_zero (tmp);
1044 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1046 ddg_edge_ptr e;
1047 ddg_node_ptr u_node = &g->nodes[u];
1049 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1051 ddg_node_ptr v_node = e->dest;
1052 int v = v_node->cuid;
1054 if (!TEST_BIT (reachable_from, v))
1056 SET_BIT (reachable_from, v);
1057 SET_BIT (tmp, v);
1058 change = 1;
1064 sbitmap_copy (reach_to, to);
1065 sbitmap_copy (tmp, to);
1067 change = 1;
1068 while (change)
1070 change = 0;
1071 sbitmap_copy (workset, tmp);
1072 sbitmap_zero (tmp);
1073 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1075 ddg_edge_ptr e;
1076 ddg_node_ptr u_node = &g->nodes[u];
1078 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1080 ddg_node_ptr v_node = e->src;
1081 int v = v_node->cuid;
1083 if (!TEST_BIT (reach_to, v))
1085 SET_BIT (reach_to, v);
1086 SET_BIT (tmp, v);
1087 change = 1;
1093 answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
1094 sbitmap_free (workset);
1095 sbitmap_free (reachable_from);
1096 sbitmap_free (reach_to);
1097 sbitmap_free (tmp);
1098 return answer;
1102 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1103 at-least as large as the count of U_NODE plus the latency between them.
1104 Sets a bit in TMP for each successor whose count was changed (increased).
1105 Returns nonzero if any count was changed. */
1106 static int
1107 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1109 ddg_edge_ptr e;
1110 int result = 0;
1112 for (e = u_node->out; e; e = e->next_out)
1114 ddg_node_ptr v_node = e->dest;
1115 int v = v_node->cuid;
1117 if (TEST_BIT (nodes, v)
1118 && (e->distance == 0)
1119 && (v_node->aux.count < u_node->aux.count + e->latency))
1121 v_node->aux.count = u_node->aux.count + e->latency;
1122 SET_BIT (tmp, v);
1123 result = 1;
1126 return result;
1130 /* Find the length of a longest path from SRC to DEST in G,
1131 going only through NODES, and disregarding backarcs. */
1133 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1135 int i;
1136 unsigned int u = 0;
1137 int change = 1;
1138 int result;
1139 int num_nodes = g->num_nodes;
1140 sbitmap workset = sbitmap_alloc (num_nodes);
1141 sbitmap tmp = sbitmap_alloc (num_nodes);
1144 /* Data will hold the distance of the longest path found so far from
1145 src to each node. Initialize to -1 = less than minimum. */
1146 for (i = 0; i < g->num_nodes; i++)
1147 g->nodes[i].aux.count = -1;
1148 g->nodes[src].aux.count = 0;
1150 sbitmap_zero (tmp);
1151 SET_BIT (tmp, src);
1153 while (change)
1155 sbitmap_iterator sbi;
1157 change = 0;
1158 sbitmap_copy (workset, tmp);
1159 sbitmap_zero (tmp);
1160 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1162 ddg_node_ptr u_node = &g->nodes[u];
1164 change |= update_dist_to_successors (u_node, nodes, tmp);
1167 result = g->nodes[dest].aux.count;
1168 sbitmap_free (workset);
1169 sbitmap_free (tmp);
1170 return result;
1173 #endif /* INSN_SCHEDULING */