Add missing ChangeLog entry
[official-gcc.git] / gcc / ddg.c
blobd06bdbb5448a36d4ecad229e8313723e01dc5f9e
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 /* If a true dep edge enters the branch create an anti edge in the
201 opposite direction to prevent the creation of reg-moves. */
202 if ((DEP_TYPE (link) == REG_DEP_TRUE) && JUMP_P (dest_node->insn))
203 create_ddg_dep_no_link (g, dest_node, src_node, ANTI_DEP, REG_DEP, 1);
205 latency = dep_cost (link);
206 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
207 add_edge_to_ddg (g, e);
210 /* The same as the above function, but it doesn't require a link parameter. */
211 static void
212 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
213 dep_type d_t, dep_data_type d_dt, int distance)
215 ddg_edge_ptr e;
216 int l;
217 enum reg_note dep_kind;
218 struct _dep _dep, *dep = &_dep;
220 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
221 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
223 if (d_t == ANTI_DEP)
224 dep_kind = REG_DEP_ANTI;
225 else if (d_t == OUTPUT_DEP)
226 dep_kind = REG_DEP_OUTPUT;
227 else
229 gcc_assert (d_t == TRUE_DEP);
231 dep_kind = REG_DEP_TRUE;
234 init_dep (dep, from->insn, to->insn, dep_kind);
236 l = dep_cost (dep);
238 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
239 if (distance > 0)
240 add_backarc_to_ddg (g, e);
241 else
242 add_edge_to_ddg (g, e);
246 /* Given a downwards exposed register def LAST_DEF (which is the last
247 definition of that register in the bb), add inter-loop true dependences
248 to all its uses in the next iteration, an output dependence to the
249 first def of the same register (possibly itself) in the next iteration
250 and anti-dependences from its uses in the current iteration to the
251 first definition in the next iteration. */
252 static void
253 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
255 int regno = DF_REF_REGNO (last_def);
256 struct df_link *r_use;
257 int has_use_in_bb_p = false;
258 rtx def_insn = DF_REF_INSN (last_def);
259 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
260 ddg_node_ptr use_node;
261 #ifdef ENABLE_CHECKING
262 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
263 #endif
264 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
266 gcc_assert (last_def_node);
267 gcc_assert (first_def);
269 #ifdef ENABLE_CHECKING
270 if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
271 gcc_assert (!bitmap_bit_p (&bb_info->gen,
272 DF_REF_ID (first_def)));
273 #endif
275 /* Create inter-loop true dependences and anti dependences. */
276 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
278 rtx use_insn = DF_REF_INSN (r_use->ref);
280 if (BLOCK_FOR_INSN (use_insn) != g->bb)
281 continue;
283 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
284 use_node = get_node_of_insn (g, use_insn);
285 gcc_assert (use_node);
286 has_use_in_bb_p = true;
287 if (use_node->cuid <= last_def_node->cuid)
289 /* Add true deps from last_def to it's uses in the next
290 iteration. Any such upwards exposed use appears before
291 the last_def def. */
292 create_ddg_dep_no_link (g, last_def_node, use_node,
293 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
294 REG_DEP, 1);
296 else if (!DEBUG_INSN_P (use_insn))
298 /* Add anti deps from last_def's uses in the current iteration
299 to the first def in the next iteration. We do not add ANTI
300 dep when there is an intra-loop TRUE dep in the opposite
301 direction, but use regmoves to fix such disregarded ANTI
302 deps when broken. If the first_def reaches the USE then
303 there is such a dep. */
304 ddg_node_ptr first_def_node = get_node_of_insn (g,
305 DF_REF_INSN (first_def));
307 gcc_assert (first_def_node);
309 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
310 || !flag_modulo_sched_allow_regmoves)
311 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
312 REG_DEP, 1);
316 /* Create an inter-loop output dependence between LAST_DEF (which is the
317 last def in its block, being downwards exposed) and the first def in
318 its block. Avoid creating a self output dependence. Avoid creating
319 an output dependence if there is a dependence path between the two
320 defs starting with a true dependence to a use which can be in the
321 next iteration; followed by an anti dependence of that use to the
322 first def (i.e. if there is a use between the two defs.) */
323 if (!has_use_in_bb_p)
325 ddg_node_ptr dest_node;
327 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
328 return;
330 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
331 gcc_assert (dest_node);
332 create_ddg_dep_no_link (g, last_def_node, dest_node,
333 OUTPUT_DEP, REG_DEP, 1);
336 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
337 static void
338 build_inter_loop_deps (ddg_ptr g)
340 unsigned rd_num;
341 struct df_rd_bb_info *rd_bb_info;
342 bitmap_iterator bi;
344 rd_bb_info = DF_RD_BB_INFO (g->bb);
346 /* Find inter-loop register output, true and anti deps. */
347 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
349 df_ref rd = DF_DEFS_GET (rd_num);
351 add_cross_iteration_register_deps (g, rd);
356 static int
357 walk_mems_2 (rtx *x, rtx mem)
359 if (MEM_P (*x))
361 if (may_alias_p (*x, mem))
362 return 1;
364 return -1;
366 return 0;
369 static int
370 walk_mems_1 (rtx *x, rtx *pat)
372 if (MEM_P (*x))
374 /* Visit all MEMs in *PAT and check indepedence. */
375 if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x))
376 /* Indicate that dependence was determined and stop traversal. */
377 return 1;
379 return -1;
381 return 0;
384 /* Return 1 if two specified instructions have mem expr with conflict alias sets*/
385 static int
386 insns_may_alias_p (rtx insn1, rtx insn2)
388 /* For each pair of MEMs in INSN1 and INSN2 check their independence. */
389 return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1,
390 &PATTERN (insn2));
393 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
394 to ddg G. */
395 static void
396 add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
399 if ((from->cuid == to->cuid)
400 || !insns_may_alias_p (from->insn, to->insn))
401 /* Do not create edge if memory references have disjoint alias sets
402 or 'to' and 'from' are the same instruction. */
403 return;
405 if (mem_write_insn_p (from->insn))
407 if (mem_read_insn_p (to->insn))
408 create_ddg_dep_no_link (g, from, to,
409 DEBUG_INSN_P (to->insn)
410 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
411 else
412 create_ddg_dep_no_link (g, from, to,
413 DEBUG_INSN_P (to->insn)
414 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
416 else if (!mem_read_insn_p (to->insn))
417 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
420 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
421 to ddg G. */
422 static void
423 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
425 if (!insns_may_alias_p (from->insn, to->insn))
426 /* Do not create edge if memory references have disjoint alias sets. */
427 return;
429 if (mem_write_insn_p (from->insn))
431 if (mem_read_insn_p (to->insn))
432 create_ddg_dep_no_link (g, from, to,
433 DEBUG_INSN_P (to->insn)
434 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
435 else if (from->cuid != to->cuid)
436 create_ddg_dep_no_link (g, from, to,
437 DEBUG_INSN_P (to->insn)
438 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
440 else
442 if (mem_read_insn_p (to->insn))
443 return;
444 else if (from->cuid != to->cuid)
446 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
447 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
448 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
449 else
450 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
456 /* Perform intra-block Data Dependency analysis and connect the nodes in
457 the DDG. We assume the loop has a single basic block. */
458 static void
459 build_intra_loop_deps (ddg_ptr g)
461 int i;
462 /* Hold the dependency analysis state during dependency calculations. */
463 struct deps_desc tmp_deps;
464 rtx head, tail;
466 /* Build the dependence information, using the sched_analyze function. */
467 init_deps_global ();
468 init_deps (&tmp_deps, false);
470 /* Do the intra-block data dependence analysis for the given block. */
471 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
472 sched_analyze (&tmp_deps, head, tail);
474 /* Build intra-loop data dependencies using the scheduler dependency
475 analysis. */
476 for (i = 0; i < g->num_nodes; i++)
478 ddg_node_ptr dest_node = &g->nodes[i];
479 sd_iterator_def sd_it;
480 dep_t dep;
482 if (! INSN_P (dest_node->insn))
483 continue;
485 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
487 ddg_node_ptr src_node = get_node_of_insn (g, DEP_PRO (dep));
489 if (!src_node)
490 continue;
492 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
495 /* If this insn modifies memory, add an edge to all insns that access
496 memory. */
497 if (mem_access_insn_p (dest_node->insn))
499 int j;
501 for (j = 0; j <= i; j++)
503 ddg_node_ptr j_node = &g->nodes[j];
504 if (DEBUG_INSN_P (j_node->insn))
505 continue;
506 if (mem_access_insn_p (j_node->insn))
508 /* Don't bother calculating inter-loop dep if an intra-loop dep
509 already exists. */
510 if (! TEST_BIT (dest_node->successors, j))
511 add_inter_loop_mem_dep (g, dest_node, j_node);
512 /* If -fmodulo-sched-allow-regmoves
513 is set certain anti-dep edges are not created.
514 It might be that these anti-dep edges are on the
515 path from one memory instruction to another such that
516 removing these edges could cause a violation of the
517 memory dependencies. Thus we add intra edges between
518 every two memory instructions in this case. */
519 if (flag_modulo_sched_allow_regmoves
520 && !TEST_BIT (dest_node->predecessors, j))
521 add_intra_loop_mem_dep (g, j_node, dest_node);
527 /* Free the INSN_LISTs. */
528 finish_deps_global ();
529 free_deps (&tmp_deps);
531 /* Free dependencies. */
532 sched_free_deps (head, tail, false);
536 /* Given a basic block, create its DDG and return a pointer to a variable
537 of ddg type that represents it.
538 Initialize the ddg structure fields to the appropriate values. */
539 ddg_ptr
540 create_ddg (basic_block bb, int closing_branch_deps)
542 ddg_ptr g;
543 rtx insn, first_note;
544 int i;
545 int num_nodes = 0;
547 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
549 g->bb = bb;
550 g->closing_branch_deps = closing_branch_deps;
552 /* Count the number of insns in the BB. */
553 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
554 insn = NEXT_INSN (insn))
556 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
557 continue;
559 if (DEBUG_INSN_P (insn))
560 g->num_debug++;
561 else
563 if (mem_read_insn_p (insn))
564 g->num_loads++;
565 if (mem_write_insn_p (insn))
566 g->num_stores++;
568 num_nodes++;
571 /* There is nothing to do for this BB. */
572 if ((num_nodes - g->num_debug) <= 1)
574 free (g);
575 return NULL;
578 /* Allocate the nodes array, and initialize the nodes. */
579 g->num_nodes = num_nodes;
580 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
581 g->closing_branch = NULL;
582 i = 0;
583 first_note = NULL_RTX;
584 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
585 insn = NEXT_INSN (insn))
587 if (! INSN_P (insn))
589 if (! first_note && NOTE_P (insn)
590 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
591 first_note = insn;
592 continue;
594 if (JUMP_P (insn))
596 gcc_assert (!g->closing_branch);
597 g->closing_branch = &g->nodes[i];
599 else if (GET_CODE (PATTERN (insn)) == USE)
601 if (! first_note)
602 first_note = insn;
603 continue;
606 g->nodes[i].cuid = i;
607 g->nodes[i].successors = sbitmap_alloc (num_nodes);
608 sbitmap_zero (g->nodes[i].successors);
609 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
610 sbitmap_zero (g->nodes[i].predecessors);
611 g->nodes[i].first_note = (first_note ? first_note : insn);
612 g->nodes[i++].insn = insn;
613 first_note = NULL_RTX;
616 /* We must have found a branch in DDG. */
617 gcc_assert (g->closing_branch);
620 /* Build the data dependency graph. */
621 build_intra_loop_deps (g);
622 build_inter_loop_deps (g);
623 return g;
626 /* Free all the memory allocated for the DDG. */
627 void
628 free_ddg (ddg_ptr g)
630 int i;
632 if (!g)
633 return;
635 for (i = 0; i < g->num_nodes; i++)
637 ddg_edge_ptr e = g->nodes[i].out;
639 while (e)
641 ddg_edge_ptr next = e->next_out;
643 free (e);
644 e = next;
646 sbitmap_free (g->nodes[i].successors);
647 sbitmap_free (g->nodes[i].predecessors);
649 if (g->num_backarcs > 0)
650 free (g->backarcs);
651 free (g->nodes);
652 free (g);
655 void
656 print_ddg_edge (FILE *file, ddg_edge_ptr e)
658 char dep_c;
660 switch (e->type)
662 case OUTPUT_DEP :
663 dep_c = 'O';
664 break;
665 case ANTI_DEP :
666 dep_c = 'A';
667 break;
668 default:
669 dep_c = 'T';
672 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
673 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
676 /* Print the DDG nodes with there in/out edges to the dump file. */
677 void
678 print_ddg (FILE *file, ddg_ptr g)
680 int i;
682 for (i = 0; i < g->num_nodes; i++)
684 ddg_edge_ptr e;
686 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
687 print_rtl_single (file, g->nodes[i].insn);
688 fprintf (file, "OUT ARCS: ");
689 for (e = g->nodes[i].out; e; e = e->next_out)
690 print_ddg_edge (file, e);
692 fprintf (file, "\nIN ARCS: ");
693 for (e = g->nodes[i].in; e; e = e->next_in)
694 print_ddg_edge (file, e);
696 fprintf (file, "\n");
700 /* Print the given DDG in VCG format. */
701 void
702 vcg_print_ddg (FILE *file, ddg_ptr g)
704 int src_cuid;
706 fprintf (file, "graph: {\n");
707 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
709 ddg_edge_ptr e;
710 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
712 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
713 print_rtl_single (file, g->nodes[src_cuid].insn);
714 fprintf (file, "\"}\n");
715 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
717 int dst_uid = INSN_UID (e->dest->insn);
718 int dst_cuid = e->dest->cuid;
720 /* Give the backarcs a different color. */
721 if (e->distance > 0)
722 fprintf (file, "backedge: {color: red ");
723 else
724 fprintf (file, "edge: { ");
726 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
727 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
728 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
731 fprintf (file, "}\n");
734 /* Dump the sccs in SCCS. */
735 void
736 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
738 unsigned int u = 0;
739 sbitmap_iterator sbi;
740 int i;
742 if (!file)
743 return;
745 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
746 for (i = 0; i < sccs->num_sccs; i++)
748 fprintf (file, "SCC number: %d\n", i);
749 EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
751 fprintf (file, "insn num %d\n", u);
752 print_rtl_single (file, g->nodes[u].insn);
755 fprintf (file, "\n");
758 /* Create an edge and initialize it with given values. */
759 static ddg_edge_ptr
760 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
761 dep_type t, dep_data_type dt, int l, int d)
763 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
765 e->src = src;
766 e->dest = dest;
767 e->type = t;
768 e->data_type = dt;
769 e->latency = l;
770 e->distance = d;
771 e->next_in = e->next_out = NULL;
772 e->aux.info = 0;
773 return e;
776 /* Add the given edge to the in/out linked lists of the DDG nodes. */
777 static void
778 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
780 ddg_node_ptr src = e->src;
781 ddg_node_ptr dest = e->dest;
783 /* Should have allocated the sbitmaps. */
784 gcc_assert (src->successors && dest->predecessors);
786 SET_BIT (src->successors, dest->cuid);
787 SET_BIT (dest->predecessors, src->cuid);
788 e->next_in = dest->in;
789 dest->in = e;
790 e->next_out = src->out;
791 src->out = e;
796 /* Algorithm for computing the recurrence_length of an scc. We assume at
797 for now that cycles in the data dependence graph contain a single backarc.
798 This simplifies the algorithm, and can be generalized later. */
799 static void
800 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
802 int j;
803 int result = -1;
805 for (j = 0; j < scc->num_backarcs; j++)
807 ddg_edge_ptr backarc = scc->backarcs[j];
808 int length;
809 int distance = backarc->distance;
810 ddg_node_ptr src = backarc->dest;
811 ddg_node_ptr dest = backarc->src;
813 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
814 if (length < 0 )
816 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
817 continue;
819 length += backarc->latency;
820 result = MAX (result, (length / distance));
822 scc->recurrence_length = result;
825 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
826 and mark edges that belong to this scc as IN_SCC. */
827 static ddg_scc_ptr
828 create_scc (ddg_ptr g, sbitmap nodes)
830 ddg_scc_ptr scc;
831 unsigned int u = 0;
832 sbitmap_iterator sbi;
834 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
835 scc->backarcs = NULL;
836 scc->num_backarcs = 0;
837 scc->nodes = sbitmap_alloc (g->num_nodes);
838 sbitmap_copy (scc->nodes, nodes);
840 /* Mark the backarcs that belong to this SCC. */
841 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
843 ddg_edge_ptr e;
844 ddg_node_ptr n = &g->nodes[u];
846 for (e = n->out; e; e = e->next_out)
847 if (TEST_BIT (nodes, e->dest->cuid))
849 e->aux.count = IN_SCC;
850 if (e->distance > 0)
851 add_backarc_to_scc (scc, e);
855 set_recurrence_length (scc, g);
856 return scc;
859 /* Cleans the memory allocation of a given SCC. */
860 static void
861 free_scc (ddg_scc_ptr scc)
863 if (!scc)
864 return;
866 sbitmap_free (scc->nodes);
867 if (scc->num_backarcs > 0)
868 free (scc->backarcs);
869 free (scc);
873 /* Add a given edge known to be a backarc to the given DDG. */
874 static void
875 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
877 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
879 add_edge_to_ddg (g, e);
880 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
881 g->backarcs[g->num_backarcs++] = e;
884 /* Add backarc to an SCC. */
885 static void
886 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
888 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
890 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
891 scc->backarcs[scc->num_backarcs++] = e;
894 /* Add the given SCC to the DDG. */
895 static void
896 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
898 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
900 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
901 g->sccs[g->num_sccs++] = scc;
904 /* Given the instruction INSN return the node that represents it. */
905 ddg_node_ptr
906 get_node_of_insn (ddg_ptr g, rtx insn)
908 int i;
910 for (i = 0; i < g->num_nodes; i++)
911 if (insn == g->nodes[i].insn)
912 return &g->nodes[i];
913 return NULL;
916 /* Given a set OPS of nodes in the DDG, find the set of their successors
917 which are not in OPS, and set their bits in SUCC. Bits corresponding to
918 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
919 void
920 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
922 unsigned int i = 0;
923 sbitmap_iterator sbi;
925 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
927 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
928 sbitmap_a_or_b (succ, succ, node_succ);
931 /* We want those that are not in ops. */
932 sbitmap_difference (succ, succ, ops);
935 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
936 which are not in OPS, and set their bits in PREDS. Bits corresponding to
937 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
938 void
939 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
941 unsigned int i = 0;
942 sbitmap_iterator sbi;
944 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
946 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
947 sbitmap_a_or_b (preds, preds, node_preds);
950 /* We want those that are not in ops. */
951 sbitmap_difference (preds, preds, ops);
955 /* Compare function to be passed to qsort to order the backarcs in descending
956 recMII order. */
957 static int
958 compare_sccs (const void *s1, const void *s2)
960 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
961 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
962 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
966 /* Order the backarcs in descending recMII order using compare_sccs. */
967 static void
968 order_sccs (ddg_all_sccs_ptr g)
970 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
971 (int (*) (const void *, const void *)) compare_sccs);
974 #ifdef ENABLE_CHECKING
975 /* Check that every node in SCCS belongs to exactly one strongly connected
976 component and that no element of SCCS is empty. */
977 static void
978 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
980 int i = 0;
981 sbitmap tmp = sbitmap_alloc (num_nodes);
983 sbitmap_zero (tmp);
984 for (i = 0; i < sccs->num_sccs; i++)
986 gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes));
987 /* Verify that every node in sccs is in exactly one strongly
988 connected component. */
989 gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes));
990 sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes);
992 sbitmap_free (tmp);
994 #endif
996 /* Perform the Strongly Connected Components decomposing algorithm on the
997 DDG and return DDG_ALL_SCCS structure that contains them. */
998 ddg_all_sccs_ptr
999 create_ddg_all_sccs (ddg_ptr g)
1001 int i;
1002 int num_nodes = g->num_nodes;
1003 sbitmap from = sbitmap_alloc (num_nodes);
1004 sbitmap to = sbitmap_alloc (num_nodes);
1005 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
1006 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
1007 xmalloc (sizeof (struct ddg_all_sccs));
1009 sccs->ddg = g;
1010 sccs->sccs = NULL;
1011 sccs->num_sccs = 0;
1013 for (i = 0; i < g->num_backarcs; i++)
1015 ddg_scc_ptr scc;
1016 ddg_edge_ptr backarc = g->backarcs[i];
1017 ddg_node_ptr src = backarc->src;
1018 ddg_node_ptr dest = backarc->dest;
1020 /* If the backarc already belongs to an SCC, continue. */
1021 if (backarc->aux.count == IN_SCC)
1022 continue;
1024 sbitmap_zero (scc_nodes);
1025 sbitmap_zero (from);
1026 sbitmap_zero (to);
1027 SET_BIT (from, dest->cuid);
1028 SET_BIT (to, src->cuid);
1030 if (find_nodes_on_paths (scc_nodes, g, from, to))
1032 scc = create_scc (g, scc_nodes);
1033 add_scc_to_ddg (sccs, scc);
1036 order_sccs (sccs);
1037 sbitmap_free (from);
1038 sbitmap_free (to);
1039 sbitmap_free (scc_nodes);
1040 #ifdef ENABLE_CHECKING
1041 check_sccs (sccs, num_nodes);
1042 #endif
1043 return sccs;
1046 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1047 void
1048 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1050 int i;
1052 if (!all_sccs)
1053 return;
1055 for (i = 0; i < all_sccs->num_sccs; i++)
1056 free_scc (all_sccs->sccs[i]);
1058 free (all_sccs->sccs);
1059 free (all_sccs);
1063 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1064 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1065 nodes from FROM and TO). Return nonzero if nodes exist. */
1067 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1069 int answer;
1070 int change;
1071 unsigned int u = 0;
1072 int num_nodes = g->num_nodes;
1073 sbitmap_iterator sbi;
1075 sbitmap workset = sbitmap_alloc (num_nodes);
1076 sbitmap reachable_from = sbitmap_alloc (num_nodes);
1077 sbitmap reach_to = sbitmap_alloc (num_nodes);
1078 sbitmap tmp = sbitmap_alloc (num_nodes);
1080 sbitmap_copy (reachable_from, from);
1081 sbitmap_copy (tmp, from);
1083 change = 1;
1084 while (change)
1086 change = 0;
1087 sbitmap_copy (workset, tmp);
1088 sbitmap_zero (tmp);
1089 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1091 ddg_edge_ptr e;
1092 ddg_node_ptr u_node = &g->nodes[u];
1094 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1096 ddg_node_ptr v_node = e->dest;
1097 int v = v_node->cuid;
1099 if (!TEST_BIT (reachable_from, v))
1101 SET_BIT (reachable_from, v);
1102 SET_BIT (tmp, v);
1103 change = 1;
1109 sbitmap_copy (reach_to, to);
1110 sbitmap_copy (tmp, to);
1112 change = 1;
1113 while (change)
1115 change = 0;
1116 sbitmap_copy (workset, tmp);
1117 sbitmap_zero (tmp);
1118 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1120 ddg_edge_ptr e;
1121 ddg_node_ptr u_node = &g->nodes[u];
1123 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1125 ddg_node_ptr v_node = e->src;
1126 int v = v_node->cuid;
1128 if (!TEST_BIT (reach_to, v))
1130 SET_BIT (reach_to, v);
1131 SET_BIT (tmp, v);
1132 change = 1;
1138 answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
1139 sbitmap_free (workset);
1140 sbitmap_free (reachable_from);
1141 sbitmap_free (reach_to);
1142 sbitmap_free (tmp);
1143 return answer;
1147 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1148 at-least as large as the count of U_NODE plus the latency between them.
1149 Sets a bit in TMP for each successor whose count was changed (increased).
1150 Returns nonzero if any count was changed. */
1151 static int
1152 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1154 ddg_edge_ptr e;
1155 int result = 0;
1157 for (e = u_node->out; e; e = e->next_out)
1159 ddg_node_ptr v_node = e->dest;
1160 int v = v_node->cuid;
1162 if (TEST_BIT (nodes, v)
1163 && (e->distance == 0)
1164 && (v_node->aux.count < u_node->aux.count + e->latency))
1166 v_node->aux.count = u_node->aux.count + e->latency;
1167 SET_BIT (tmp, v);
1168 result = 1;
1171 return result;
1175 /* Find the length of a longest path from SRC to DEST in G,
1176 going only through NODES, and disregarding backarcs. */
1178 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1180 int i;
1181 unsigned int u = 0;
1182 int change = 1;
1183 int result;
1184 int num_nodes = g->num_nodes;
1185 sbitmap workset = sbitmap_alloc (num_nodes);
1186 sbitmap tmp = sbitmap_alloc (num_nodes);
1189 /* Data will hold the distance of the longest path found so far from
1190 src to each node. Initialize to -1 = less than minimum. */
1191 for (i = 0; i < g->num_nodes; i++)
1192 g->nodes[i].aux.count = -1;
1193 g->nodes[src].aux.count = 0;
1195 sbitmap_zero (tmp);
1196 SET_BIT (tmp, src);
1198 while (change)
1200 sbitmap_iterator sbi;
1202 change = 0;
1203 sbitmap_copy (workset, tmp);
1204 sbitmap_zero (tmp);
1205 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1207 ddg_node_ptr u_node = &g->nodes[u];
1209 change |= update_dist_to_successors (u_node, nodes, tmp);
1212 result = g->nodes[dest].aux.count;
1213 sbitmap_free (workset);
1214 sbitmap_free (tmp);
1215 return result;
1218 #endif /* INSN_SCHEDULING */