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"
40 #include "cfglayout.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
,
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. */
69 mark_mem_use (rtx
*x
, void *data ATTRIBUTE_UNUSED
)
76 /* Auxiliary function for mem_read_insn_p. */
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. */
85 mem_read_insn_p (rtx insn
)
88 note_uses (&PATTERN (insn
), mark_mem_use_1
, NULL
);
93 mark_mem_store (rtx loc
, const_rtx setter ATTRIBUTE_UNUSED
, void *data ATTRIBUTE_UNUSED
)
99 /* Returns nonzero if INSN writes to memory. */
101 mem_write_insn_p (rtx insn
)
104 note_stores (PATTERN (insn
), mark_mem_store
, NULL
);
108 /* Returns nonzero if X has access to memory. */
110 rtx_mem_access_p (rtx x
)
123 fmt
= GET_RTX_FORMAT (code
);
124 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
128 if (rtx_mem_access_p (XEXP (x
, i
)))
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
)))
141 /* Returns nonzero if INSN reads to or writes from memory. */
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. */
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
)
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
160 gcc_assert (src_node
->cuid
< dest_node
->cuid
);
163 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
164 if (DEP_TYPE (link
) == REG_DEP_ANTI
)
166 else if (DEP_TYPE (link
) == REG_DEP_OUTPUT
)
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
))
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
));
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
)))
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. */
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
)
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
);
224 dep_kind
= REG_DEP_ANTI
;
225 else if (d_t
== OUTPUT_DEP
)
226 dep_kind
= REG_DEP_OUTPUT
;
229 gcc_assert (d_t
== TRUE_DEP
);
231 dep_kind
= REG_DEP_TRUE
;
234 init_dep (dep
, from
->insn
, to
->insn
, dep_kind
);
238 e
= create_ddg_edge (from
, to
, d_t
, d_dt
, l
, distance
);
240 add_backarc_to_ddg (g
, e
);
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. */
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
);
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
)));
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
)
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
292 create_ddg_dep_no_link (g
, last_def_node
, use_node
,
293 DEBUG_INSN_P (use_insn
) ? ANTI_DEP
: TRUE_DEP
,
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
,
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
))
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. */
338 build_inter_loop_deps (ddg_ptr g
)
341 struct df_rd_bb_info
*rd_bb_info
;
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
);
357 walk_mems_2 (rtx
*x
, rtx mem
)
361 if (may_alias_p (*x
, mem
))
370 walk_mems_1 (rtx
*x
, rtx
*pat
)
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. */
384 /* Return 1 if two specified instructions have mem expr with conflict alias sets*/
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
,
393 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
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. */
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);
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
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. */
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);
442 if (mem_read_insn_p (to
->insn
))
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);
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. */
459 build_intra_loop_deps (ddg_ptr g
)
462 /* Hold the dependency analysis state during dependency calculations. */
463 struct deps_desc tmp_deps
;
466 /* Build the dependence information, using the sched_analyze function. */
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
476 for (i
= 0; i
< g
->num_nodes
; i
++)
478 ddg_node_ptr dest_node
= &g
->nodes
[i
];
479 sd_iterator_def sd_it
;
482 if (! INSN_P (dest_node
->insn
))
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
));
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
497 if (mem_access_insn_p (dest_node
->insn
))
501 for (j
= 0; j
<= i
; j
++)
503 ddg_node_ptr j_node
= &g
->nodes
[j
];
504 if (DEBUG_INSN_P (j_node
->insn
))
506 if (mem_access_insn_p (j_node
->insn
))
508 /* Don't bother calculating inter-loop dep if an intra-loop dep
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. */
540 create_ddg (basic_block bb
, int closing_branch_deps
)
543 rtx insn
, first_note
;
547 g
= (ddg_ptr
) xcalloc (1, sizeof (struct ddg
));
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
)
559 if (DEBUG_INSN_P (insn
))
563 if (mem_read_insn_p (insn
))
565 if (mem_write_insn_p (insn
))
571 /* There is nothing to do for this BB. */
572 if ((num_nodes
- g
->num_debug
) <= 1)
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
;
583 first_note
= NULL_RTX
;
584 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
585 insn
= NEXT_INSN (insn
))
589 if (! first_note
&& NOTE_P (insn
)
590 && NOTE_KIND (insn
) != NOTE_INSN_BASIC_BLOCK
)
596 gcc_assert (!g
->closing_branch
);
597 g
->closing_branch
= &g
->nodes
[i
];
599 else if (GET_CODE (PATTERN (insn
)) == USE
)
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
);
626 /* Free all the memory allocated for the DDG. */
635 for (i
= 0; i
< g
->num_nodes
; i
++)
637 ddg_edge_ptr e
= g
->nodes
[i
].out
;
641 ddg_edge_ptr next
= e
->next_out
;
646 sbitmap_free (g
->nodes
[i
].successors
);
647 sbitmap_free (g
->nodes
[i
].predecessors
);
649 if (g
->num_backarcs
> 0)
656 print_ddg_edge (FILE *file
, ddg_edge_ptr e
)
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. */
678 print_ddg (FILE *file
, ddg_ptr g
)
682 for (i
= 0; i
< g
->num_nodes
; i
++)
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. */
702 vcg_print_ddg (FILE *file
, ddg_ptr g
)
706 fprintf (file
, "graph: {\n");
707 for (src_cuid
= 0; src_cuid
< g
->num_nodes
; src_cuid
++)
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. */
722 fprintf (file
, "backedge: {color: red ");
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. */
736 print_sccs (FILE *file
, ddg_all_sccs_ptr sccs
, ddg_ptr g
)
739 sbitmap_iterator sbi
;
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. */
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
));
771 e
->next_in
= e
->next_out
= NULL
;
776 /* Add the given edge to the in/out linked lists of the DDG nodes. */
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
;
790 e
->next_out
= src
->out
;
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. */
800 set_recurrence_length (ddg_scc_ptr scc
, ddg_ptr g
)
805 for (j
= 0; j
< scc
->num_backarcs
; j
++)
807 ddg_edge_ptr backarc
= scc
->backarcs
[j
];
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
);
816 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
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. */
828 create_scc (ddg_ptr g
, sbitmap nodes
)
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
)
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
;
851 add_backarc_to_scc (scc
, e
);
855 set_recurrence_length (scc
, g
);
859 /* Cleans the memory allocation of a given SCC. */
861 free_scc (ddg_scc_ptr scc
)
866 sbitmap_free (scc
->nodes
);
867 if (scc
->num_backarcs
> 0)
868 free (scc
->backarcs
);
873 /* Add a given edge known to be a backarc to the given DDG. */
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. */
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. */
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. */
906 get_node_of_insn (ddg_ptr g
, rtx insn
)
910 for (i
= 0; i
< g
->num_nodes
; i
++)
911 if (insn
== g
->nodes
[i
].insn
)
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. */
920 find_successors (sbitmap succ
, ddg_ptr g
, sbitmap ops
)
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. */
939 find_predecessors (sbitmap preds
, ddg_ptr g
, sbitmap ops
)
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
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. */
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. */
978 check_sccs (ddg_all_sccs_ptr sccs
, int num_nodes
)
981 sbitmap tmp
= sbitmap_alloc (num_nodes
);
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
);
996 /* Perform the Strongly Connected Components decomposing algorithm on the
997 DDG and return DDG_ALL_SCCS structure that contains them. */
999 create_ddg_all_sccs (ddg_ptr g
)
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
));
1013 for (i
= 0; i
< g
->num_backarcs
; i
++)
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
)
1024 sbitmap_zero (scc_nodes
);
1025 sbitmap_zero (from
);
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
);
1037 sbitmap_free (from
);
1039 sbitmap_free (scc_nodes
);
1040 #ifdef ENABLE_CHECKING
1041 check_sccs (sccs
, num_nodes
);
1046 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1048 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs
)
1055 for (i
= 0; i
< all_sccs
->num_sccs
; i
++)
1056 free_scc (all_sccs
->sccs
[i
]);
1058 free (all_sccs
->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
)
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
);
1087 sbitmap_copy (workset
, tmp
);
1089 EXECUTE_IF_SET_IN_SBITMAP (workset
, 0, u
, sbi
)
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
);
1109 sbitmap_copy (reach_to
, to
);
1110 sbitmap_copy (tmp
, to
);
1116 sbitmap_copy (workset
, tmp
);
1118 EXECUTE_IF_SET_IN_SBITMAP (workset
, 0, u
, sbi
)
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
);
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
);
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. */
1152 update_dist_to_successors (ddg_node_ptr u_node
, sbitmap nodes
, sbitmap tmp
)
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
;
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
)
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;
1200 sbitmap_iterator sbi
;
1203 sbitmap_copy (workset
, 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
);
1218 #endif /* INSN_SCHEDULING */