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
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
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/>. */
25 #include "coretypes.h"
27 #include "diagnostic-core.h"
30 #include "hard-reg-set.h"
34 #include "insn-config.h"
35 #include "insn-attr.h"
38 #include "sched-int.h"
46 #ifdef INSN_SCHEDULING
48 /* A flag indicating that a ddg edge belongs to an SCC or not. */
49 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
51 /* Forward declarations. */
52 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
53 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
54 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
55 static void create_ddg_dep_from_intra_loop_link (ddg_ptr, ddg_node_ptr,
57 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
58 dep_type, dep_data_type, int);
59 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
60 dep_data_type, int, int);
61 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
63 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
64 static bool mem_ref_p;
66 /* Auxiliary function for mem_read_insn_p. */
68 mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
75 /* Auxiliary function for mem_read_insn_p. */
77 mark_mem_use_1 (rtx *x, void *data)
79 for_each_rtx (x, mark_mem_use, data);
82 /* Returns nonzero if INSN reads from memory. */
84 mem_read_insn_p (rtx insn)
87 note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
92 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
98 /* Returns nonzero if INSN writes to memory. */
100 mem_write_insn_p (rtx insn)
103 note_stores (PATTERN (insn), mark_mem_store, NULL);
107 /* Returns nonzero if X has access to memory. */
109 rtx_mem_access_p (rtx x)
122 fmt = GET_RTX_FORMAT (code);
123 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
127 if (rtx_mem_access_p (XEXP (x, i)))
130 else if (fmt[i] == 'E')
131 for (j = 0; j < XVECLEN (x, i); j++)
133 if (rtx_mem_access_p (XVECEXP (x, i, j)))
140 /* Returns nonzero if INSN reads to or writes from memory. */
142 mem_access_insn_p (rtx insn)
144 return rtx_mem_access_p (PATTERN (insn));
147 /* Return true if DEF_INSN contains address being auto-inc or auto-dec
148 which is used in USE_INSN. Otherwise return false. The result is
149 being used to decide whether to remove the edge between def_insn and
150 use_insn when -fmodulo-sched-allow-regmoves is set. This function
151 doesn't need to consider the specific address register; no reg_moves
152 will be allowed for any life range defined by def_insn and used
153 by use_insn, if use_insn uses an address register auto-inc'ed by
156 autoinc_var_is_used_p (rtx def_insn, rtx use_insn)
160 for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
161 if (REG_NOTE_KIND (note) == REG_INC
162 && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
168 /* Return true if one of the definitions in INSN has MODE_CC. Otherwise
171 def_has_ccmode_p (rtx insn)
175 for (def = DF_INSN_DEFS (insn); *def; def++)
177 enum machine_mode mode = GET_MODE (DF_REF_REG (*def));
179 if (GET_MODE_CLASS (mode) == MODE_CC)
186 /* Computes the dependence parameters (latency, distance etc.), creates
187 a ddg_edge and adds it to the given DDG. */
189 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
190 ddg_node_ptr dest_node, dep_t link)
193 int latency, distance = 0;
194 dep_type t = TRUE_DEP;
195 dep_data_type dt = (mem_access_insn_p (src_node->insn)
196 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
198 gcc_assert (src_node->cuid < dest_node->cuid);
201 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
202 if (DEP_TYPE (link) == REG_DEP_ANTI)
204 else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
207 gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
208 gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
210 /* We currently choose not to create certain anti-deps edges and
211 compensate for that by generating reg-moves based on the life-range
212 analysis. The anti-deps that will be deleted are the ones which
213 have true-deps edges in the opposite direction (in other words
214 the kernel has only one def of the relevant register).
215 If the address that is being auto-inc or auto-dec in DEST_NODE
216 is used in SRC_NODE then do not remove the edge to make sure
217 reg-moves will not be created for this address.
218 TODO: support the removal of all anti-deps edges, i.e. including those
219 whose register has multiple defs in the loop. */
220 if (flag_modulo_sched_allow_regmoves
221 && (t == ANTI_DEP && dt == REG_DEP)
222 && !def_has_ccmode_p (dest_node->insn)
223 && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
227 set = single_set (dest_node->insn);
228 /* TODO: Handle registers that REG_P is not true for them, i.e.
229 subregs and special registers. */
230 if (set && REG_P (SET_DEST (set)))
232 int regno = REGNO (SET_DEST (set));
234 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
236 first_def = df_bb_regno_first_def_find (g->bb, regno);
237 gcc_assert (first_def);
239 if (bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)))
244 latency = dep_cost (link);
245 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
246 add_edge_to_ddg (g, e);
249 /* The same as the above function, but it doesn't require a link parameter. */
251 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
252 dep_type d_t, dep_data_type d_dt, int distance)
256 enum reg_note dep_kind;
257 struct _dep _dep, *dep = &_dep;
259 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
260 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
263 dep_kind = REG_DEP_ANTI;
264 else if (d_t == OUTPUT_DEP)
265 dep_kind = REG_DEP_OUTPUT;
268 gcc_assert (d_t == TRUE_DEP);
270 dep_kind = REG_DEP_TRUE;
273 init_dep (dep, from->insn, to->insn, dep_kind);
277 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
279 add_backarc_to_ddg (g, e);
281 add_edge_to_ddg (g, e);
285 /* Given a downwards exposed register def LAST_DEF (which is the last
286 definition of that register in the bb), add inter-loop true dependences
287 to all its uses in the next iteration, an output dependence to the
288 first def of the same register (possibly itself) in the next iteration
289 and anti-dependences from its uses in the current iteration to the
290 first definition in the next iteration. */
292 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
294 int regno = DF_REF_REGNO (last_def);
295 struct df_link *r_use;
296 int has_use_in_bb_p = false;
297 rtx def_insn = DF_REF_INSN (last_def);
298 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
299 ddg_node_ptr use_node;
300 #ifdef ENABLE_CHECKING
301 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
303 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
305 gcc_assert (last_def_node);
306 gcc_assert (first_def);
308 #ifdef ENABLE_CHECKING
309 if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
310 gcc_assert (!bitmap_bit_p (&bb_info->gen,
311 DF_REF_ID (first_def)));
314 /* Create inter-loop true dependences and anti dependences. */
315 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
317 rtx use_insn = DF_REF_INSN (r_use->ref);
319 if (BLOCK_FOR_INSN (use_insn) != g->bb)
322 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
323 use_node = get_node_of_insn (g, use_insn);
324 gcc_assert (use_node);
325 has_use_in_bb_p = true;
326 if (use_node->cuid <= last_def_node->cuid)
328 /* Add true deps from last_def to it's uses in the next
329 iteration. Any such upwards exposed use appears before
331 create_ddg_dep_no_link (g, last_def_node, use_node,
332 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
335 else if (!DEBUG_INSN_P (use_insn))
337 /* Add anti deps from last_def's uses in the current iteration
338 to the first def in the next iteration. We do not add ANTI
339 dep when there is an intra-loop TRUE dep in the opposite
340 direction, but use regmoves to fix such disregarded ANTI
341 deps when broken. If the first_def reaches the USE then
342 there is such a dep. */
343 ddg_node_ptr first_def_node = get_node_of_insn (g,
344 DF_REF_INSN (first_def));
346 gcc_assert (first_def_node);
348 /* Always create the edge if the use node is a branch in
349 order to prevent the creation of reg-moves.
350 If the address that is being auto-inc or auto-dec in LAST_DEF
351 is used in USE_INSN then do not remove the edge to make sure
352 reg-moves will not be created for that address. */
353 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
354 || !flag_modulo_sched_allow_regmoves
355 || JUMP_P (use_node->insn)
356 || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
357 || def_has_ccmode_p (DF_REF_INSN (last_def)))
358 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
363 /* Create an inter-loop output dependence between LAST_DEF (which is the
364 last def in its block, being downwards exposed) and the first def in
365 its block. Avoid creating a self output dependence. Avoid creating
366 an output dependence if there is a dependence path between the two
367 defs starting with a true dependence to a use which can be in the
368 next iteration; followed by an anti dependence of that use to the
369 first def (i.e. if there is a use between the two defs.) */
370 if (!has_use_in_bb_p)
372 ddg_node_ptr dest_node;
374 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
377 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
378 gcc_assert (dest_node);
379 create_ddg_dep_no_link (g, last_def_node, dest_node,
380 OUTPUT_DEP, REG_DEP, 1);
383 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
385 build_inter_loop_deps (ddg_ptr g)
388 struct df_rd_bb_info *rd_bb_info;
391 rd_bb_info = DF_RD_BB_INFO (g->bb);
393 /* Find inter-loop register output, true and anti deps. */
394 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
396 df_ref rd = DF_DEFS_GET (rd_num);
398 add_cross_iteration_register_deps (g, rd);
404 walk_mems_2 (rtx *x, rtx mem)
408 if (may_alias_p (*x, mem))
417 walk_mems_1 (rtx *x, rtx *pat)
421 /* Visit all MEMs in *PAT and check indepedence. */
422 if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x))
423 /* Indicate that dependence was determined and stop traversal. */
431 /* Return 1 if two specified instructions have mem expr with conflict alias sets*/
433 insns_may_alias_p (rtx insn1, rtx insn2)
435 /* For each pair of MEMs in INSN1 and INSN2 check their independence. */
436 return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1,
440 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
443 add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
446 if ((from->cuid == to->cuid)
447 || !insns_may_alias_p (from->insn, to->insn))
448 /* Do not create edge if memory references have disjoint alias sets
449 or 'to' and 'from' are the same instruction. */
452 if (mem_write_insn_p (from->insn))
454 if (mem_read_insn_p (to->insn))
455 create_ddg_dep_no_link (g, from, to,
456 DEBUG_INSN_P (to->insn)
457 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
459 create_ddg_dep_no_link (g, from, to,
460 DEBUG_INSN_P (to->insn)
461 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
463 else if (!mem_read_insn_p (to->insn))
464 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
467 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
470 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
472 if (!insns_may_alias_p (from->insn, to->insn))
473 /* Do not create edge if memory references have disjoint alias sets. */
476 if (mem_write_insn_p (from->insn))
478 if (mem_read_insn_p (to->insn))
479 create_ddg_dep_no_link (g, from, to,
480 DEBUG_INSN_P (to->insn)
481 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
482 else if (from->cuid != to->cuid)
483 create_ddg_dep_no_link (g, from, to,
484 DEBUG_INSN_P (to->insn)
485 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
489 if (mem_read_insn_p (to->insn))
491 else if (from->cuid != to->cuid)
493 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
494 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
495 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
497 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
503 /* Perform intra-block Data Dependency analysis and connect the nodes in
504 the DDG. We assume the loop has a single basic block. */
506 build_intra_loop_deps (ddg_ptr g)
509 /* Hold the dependency analysis state during dependency calculations. */
510 struct deps_desc tmp_deps;
513 /* Build the dependence information, using the sched_analyze function. */
515 init_deps (&tmp_deps, false);
517 /* Do the intra-block data dependence analysis for the given block. */
518 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
519 sched_analyze (&tmp_deps, head, tail);
521 /* Build intra-loop data dependencies using the scheduler dependency
523 for (i = 0; i < g->num_nodes; i++)
525 ddg_node_ptr dest_node = &g->nodes[i];
526 sd_iterator_def sd_it;
529 if (! INSN_P (dest_node->insn))
532 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
534 rtx src_insn = DEP_PRO (dep);
535 ddg_node_ptr src_node;
537 /* Don't add dependencies on debug insns to non-debug insns
538 to avoid codegen differences between -g and -g0. */
539 if (DEBUG_INSN_P (src_insn) && !DEBUG_INSN_P (dest_node->insn))
542 src_node = get_node_of_insn (g, src_insn);
547 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
550 /* If this insn modifies memory, add an edge to all insns that access
552 if (mem_access_insn_p (dest_node->insn))
556 for (j = 0; j <= i; j++)
558 ddg_node_ptr j_node = &g->nodes[j];
559 if (DEBUG_INSN_P (j_node->insn))
561 if (mem_access_insn_p (j_node->insn))
563 /* Don't bother calculating inter-loop dep if an intra-loop dep
565 if (! TEST_BIT (dest_node->successors, j))
566 add_inter_loop_mem_dep (g, dest_node, j_node);
567 /* If -fmodulo-sched-allow-regmoves
568 is set certain anti-dep edges are not created.
569 It might be that these anti-dep edges are on the
570 path from one memory instruction to another such that
571 removing these edges could cause a violation of the
572 memory dependencies. Thus we add intra edges between
573 every two memory instructions in this case. */
574 if (flag_modulo_sched_allow_regmoves
575 && !TEST_BIT (dest_node->predecessors, j))
576 add_intra_loop_mem_dep (g, j_node, dest_node);
582 /* Free the INSN_LISTs. */
583 finish_deps_global ();
584 free_deps (&tmp_deps);
586 /* Free dependencies. */
587 sched_free_deps (head, tail, false);
591 /* Given a basic block, create its DDG and return a pointer to a variable
592 of ddg type that represents it.
593 Initialize the ddg structure fields to the appropriate values. */
595 create_ddg (basic_block bb, int closing_branch_deps)
598 rtx insn, first_note;
602 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
605 g->closing_branch_deps = closing_branch_deps;
607 /* Count the number of insns in the BB. */
608 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
609 insn = NEXT_INSN (insn))
611 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
614 if (DEBUG_INSN_P (insn))
618 if (mem_read_insn_p (insn))
620 if (mem_write_insn_p (insn))
626 /* There is nothing to do for this BB. */
627 if ((num_nodes - g->num_debug) <= 1)
633 /* Allocate the nodes array, and initialize the nodes. */
634 g->num_nodes = num_nodes;
635 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
636 g->closing_branch = NULL;
638 first_note = NULL_RTX;
639 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
640 insn = NEXT_INSN (insn))
644 if (! first_note && NOTE_P (insn)
645 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
651 gcc_assert (!g->closing_branch);
652 g->closing_branch = &g->nodes[i];
654 else if (GET_CODE (PATTERN (insn)) == USE)
661 g->nodes[i].cuid = i;
662 g->nodes[i].successors = sbitmap_alloc (num_nodes);
663 sbitmap_zero (g->nodes[i].successors);
664 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
665 sbitmap_zero (g->nodes[i].predecessors);
666 g->nodes[i].first_note = (first_note ? first_note : insn);
667 g->nodes[i++].insn = insn;
668 first_note = NULL_RTX;
671 /* We must have found a branch in DDG. */
672 gcc_assert (g->closing_branch);
675 /* Build the data dependency graph. */
676 build_intra_loop_deps (g);
677 build_inter_loop_deps (g);
681 /* Free all the memory allocated for the DDG. */
690 for (i = 0; i < g->num_nodes; i++)
692 ddg_edge_ptr e = g->nodes[i].out;
696 ddg_edge_ptr next = e->next_out;
701 sbitmap_free (g->nodes[i].successors);
702 sbitmap_free (g->nodes[i].predecessors);
704 if (g->num_backarcs > 0)
711 print_ddg_edge (FILE *file, ddg_edge_ptr e)
727 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
728 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
731 /* Print the DDG nodes with there in/out edges to the dump file. */
733 print_ddg (FILE *file, ddg_ptr g)
737 for (i = 0; i < g->num_nodes; i++)
741 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
742 print_rtl_single (file, g->nodes[i].insn);
743 fprintf (file, "OUT ARCS: ");
744 for (e = g->nodes[i].out; e; e = e->next_out)
745 print_ddg_edge (file, e);
747 fprintf (file, "\nIN ARCS: ");
748 for (e = g->nodes[i].in; e; e = e->next_in)
749 print_ddg_edge (file, e);
751 fprintf (file, "\n");
755 /* Print the given DDG in VCG format. */
757 vcg_print_ddg (FILE *file, ddg_ptr g)
761 fprintf (file, "graph: {\n");
762 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
765 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
767 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
768 print_rtl_single (file, g->nodes[src_cuid].insn);
769 fprintf (file, "\"}\n");
770 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
772 int dst_uid = INSN_UID (e->dest->insn);
773 int dst_cuid = e->dest->cuid;
775 /* Give the backarcs a different color. */
777 fprintf (file, "backedge: {color: red ");
779 fprintf (file, "edge: { ");
781 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
782 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
783 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
786 fprintf (file, "}\n");
789 /* Dump the sccs in SCCS. */
791 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
794 sbitmap_iterator sbi;
800 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
801 for (i = 0; i < sccs->num_sccs; i++)
803 fprintf (file, "SCC number: %d\n", i);
804 EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
806 fprintf (file, "insn num %d\n", u);
807 print_rtl_single (file, g->nodes[u].insn);
810 fprintf (file, "\n");
813 /* Create an edge and initialize it with given values. */
815 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
816 dep_type t, dep_data_type dt, int l, int d)
818 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
826 e->next_in = e->next_out = NULL;
831 /* Add the given edge to the in/out linked lists of the DDG nodes. */
833 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
835 ddg_node_ptr src = e->src;
836 ddg_node_ptr dest = e->dest;
838 /* Should have allocated the sbitmaps. */
839 gcc_assert (src->successors && dest->predecessors);
841 SET_BIT (src->successors, dest->cuid);
842 SET_BIT (dest->predecessors, src->cuid);
843 e->next_in = dest->in;
845 e->next_out = src->out;
851 /* Algorithm for computing the recurrence_length of an scc. We assume at
852 for now that cycles in the data dependence graph contain a single backarc.
853 This simplifies the algorithm, and can be generalized later. */
855 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
860 for (j = 0; j < scc->num_backarcs; j++)
862 ddg_edge_ptr backarc = scc->backarcs[j];
864 int distance = backarc->distance;
865 ddg_node_ptr src = backarc->dest;
866 ddg_node_ptr dest = backarc->src;
868 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
871 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
874 length += backarc->latency;
875 result = MAX (result, (length / distance));
877 scc->recurrence_length = result;
880 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
881 and mark edges that belong to this scc as IN_SCC. */
883 create_scc (ddg_ptr g, sbitmap nodes)
887 sbitmap_iterator sbi;
889 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
890 scc->backarcs = NULL;
891 scc->num_backarcs = 0;
892 scc->nodes = sbitmap_alloc (g->num_nodes);
893 sbitmap_copy (scc->nodes, nodes);
895 /* Mark the backarcs that belong to this SCC. */
896 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
899 ddg_node_ptr n = &g->nodes[u];
901 for (e = n->out; e; e = e->next_out)
902 if (TEST_BIT (nodes, e->dest->cuid))
904 e->aux.count = IN_SCC;
906 add_backarc_to_scc (scc, e);
910 set_recurrence_length (scc, g);
914 /* Cleans the memory allocation of a given SCC. */
916 free_scc (ddg_scc_ptr scc)
921 sbitmap_free (scc->nodes);
922 if (scc->num_backarcs > 0)
923 free (scc->backarcs);
928 /* Add a given edge known to be a backarc to the given DDG. */
930 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
932 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
934 add_edge_to_ddg (g, e);
935 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
936 g->backarcs[g->num_backarcs++] = e;
939 /* Add backarc to an SCC. */
941 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
943 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
945 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
946 scc->backarcs[scc->num_backarcs++] = e;
949 /* Add the given SCC to the DDG. */
951 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
953 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
955 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
956 g->sccs[g->num_sccs++] = scc;
959 /* Given the instruction INSN return the node that represents it. */
961 get_node_of_insn (ddg_ptr g, rtx insn)
965 for (i = 0; i < g->num_nodes; i++)
966 if (insn == g->nodes[i].insn)
971 /* Given a set OPS of nodes in the DDG, find the set of their successors
972 which are not in OPS, and set their bits in SUCC. Bits corresponding to
973 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
975 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
978 sbitmap_iterator sbi;
980 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
982 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
983 sbitmap_a_or_b (succ, succ, node_succ);
986 /* We want those that are not in ops. */
987 sbitmap_difference (succ, succ, ops);
990 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
991 which are not in OPS, and set their bits in PREDS. Bits corresponding to
992 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
994 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
997 sbitmap_iterator sbi;
999 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
1001 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
1002 sbitmap_a_or_b (preds, preds, node_preds);
1005 /* We want those that are not in ops. */
1006 sbitmap_difference (preds, preds, ops);
1010 /* Compare function to be passed to qsort to order the backarcs in descending
1013 compare_sccs (const void *s1, const void *s2)
1015 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
1016 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
1017 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
1021 /* Order the backarcs in descending recMII order using compare_sccs. */
1023 order_sccs (ddg_all_sccs_ptr g)
1025 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
1026 (int (*) (const void *, const void *)) compare_sccs);
1029 #ifdef ENABLE_CHECKING
1030 /* Check that every node in SCCS belongs to exactly one strongly connected
1031 component and that no element of SCCS is empty. */
1033 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
1036 sbitmap tmp = sbitmap_alloc (num_nodes);
1039 for (i = 0; i < sccs->num_sccs; i++)
1041 gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes));
1042 /* Verify that every node in sccs is in exactly one strongly
1043 connected component. */
1044 gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes));
1045 sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes);
1051 /* Perform the Strongly Connected Components decomposing algorithm on the
1052 DDG and return DDG_ALL_SCCS structure that contains them. */
1054 create_ddg_all_sccs (ddg_ptr g)
1057 int num_nodes = g->num_nodes;
1058 sbitmap from = sbitmap_alloc (num_nodes);
1059 sbitmap to = sbitmap_alloc (num_nodes);
1060 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
1061 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
1062 xmalloc (sizeof (struct ddg_all_sccs));
1068 for (i = 0; i < g->num_backarcs; i++)
1071 ddg_edge_ptr backarc = g->backarcs[i];
1072 ddg_node_ptr src = backarc->src;
1073 ddg_node_ptr dest = backarc->dest;
1075 /* If the backarc already belongs to an SCC, continue. */
1076 if (backarc->aux.count == IN_SCC)
1079 sbitmap_zero (scc_nodes);
1080 sbitmap_zero (from);
1082 SET_BIT (from, dest->cuid);
1083 SET_BIT (to, src->cuid);
1085 if (find_nodes_on_paths (scc_nodes, g, from, to))
1087 scc = create_scc (g, scc_nodes);
1088 add_scc_to_ddg (sccs, scc);
1092 sbitmap_free (from);
1094 sbitmap_free (scc_nodes);
1095 #ifdef ENABLE_CHECKING
1096 check_sccs (sccs, num_nodes);
1101 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1103 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1110 for (i = 0; i < all_sccs->num_sccs; i++)
1111 free_scc (all_sccs->sccs[i]);
1113 free (all_sccs->sccs);
1118 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1119 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1120 nodes from FROM and TO). Return nonzero if nodes exist. */
1122 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1127 int num_nodes = g->num_nodes;
1128 sbitmap_iterator sbi;
1130 sbitmap workset = sbitmap_alloc (num_nodes);
1131 sbitmap reachable_from = sbitmap_alloc (num_nodes);
1132 sbitmap reach_to = sbitmap_alloc (num_nodes);
1133 sbitmap tmp = sbitmap_alloc (num_nodes);
1135 sbitmap_copy (reachable_from, from);
1136 sbitmap_copy (tmp, from);
1142 sbitmap_copy (workset, tmp);
1144 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1147 ddg_node_ptr u_node = &g->nodes[u];
1149 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1151 ddg_node_ptr v_node = e->dest;
1152 int v = v_node->cuid;
1154 if (!TEST_BIT (reachable_from, v))
1156 SET_BIT (reachable_from, v);
1164 sbitmap_copy (reach_to, to);
1165 sbitmap_copy (tmp, to);
1171 sbitmap_copy (workset, tmp);
1173 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1176 ddg_node_ptr u_node = &g->nodes[u];
1178 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1180 ddg_node_ptr v_node = e->src;
1181 int v = v_node->cuid;
1183 if (!TEST_BIT (reach_to, v))
1185 SET_BIT (reach_to, v);
1193 answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
1194 sbitmap_free (workset);
1195 sbitmap_free (reachable_from);
1196 sbitmap_free (reach_to);
1202 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1203 at-least as large as the count of U_NODE plus the latency between them.
1204 Sets a bit in TMP for each successor whose count was changed (increased).
1205 Returns nonzero if any count was changed. */
1207 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1212 for (e = u_node->out; e; e = e->next_out)
1214 ddg_node_ptr v_node = e->dest;
1215 int v = v_node->cuid;
1217 if (TEST_BIT (nodes, v)
1218 && (e->distance == 0)
1219 && (v_node->aux.count < u_node->aux.count + e->latency))
1221 v_node->aux.count = u_node->aux.count + e->latency;
1230 /* Find the length of a longest path from SRC to DEST in G,
1231 going only through NODES, and disregarding backarcs. */
1233 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1239 int num_nodes = g->num_nodes;
1240 sbitmap workset = sbitmap_alloc (num_nodes);
1241 sbitmap tmp = sbitmap_alloc (num_nodes);
1244 /* Data will hold the distance of the longest path found so far from
1245 src to each node. Initialize to -1 = less than minimum. */
1246 for (i = 0; i < g->num_nodes; i++)
1247 g->nodes[i].aux.count = -1;
1248 g->nodes[src].aux.count = 0;
1255 sbitmap_iterator sbi;
1258 sbitmap_copy (workset, tmp);
1260 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1262 ddg_node_ptr u_node = &g->nodes[u];
1264 change |= update_dist_to_successors (u_node, nodes, tmp);
1267 result = g->nodes[dest].aux.count;
1268 sbitmap_free (workset);
1273 #endif /* INSN_SCHEDULING */