1 /* DDG - Data Dependence Graph implementation.
2 Copyright (C) 2004-2015 Free Software Foundation, Inc.
3 Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
29 #include "diagnostic-core.h"
33 #include "insn-config.h"
34 #include "insn-attr.h"
37 #include "sched-int.h"
52 #ifdef INSN_SCHEDULING
54 /* A flag indicating that a ddg edge belongs to an SCC or not. */
55 enum edge_flag
{NOT_IN_SCC
= 0, IN_SCC
};
57 /* Forward declarations. */
58 static void add_backarc_to_ddg (ddg_ptr
, ddg_edge_ptr
);
59 static void add_backarc_to_scc (ddg_scc_ptr
, ddg_edge_ptr
);
60 static void add_scc_to_ddg (ddg_all_sccs_ptr
, ddg_scc_ptr
);
61 static void create_ddg_dep_from_intra_loop_link (ddg_ptr
, ddg_node_ptr
,
63 static void create_ddg_dep_no_link (ddg_ptr
, ddg_node_ptr
, ddg_node_ptr
,
64 dep_type
, dep_data_type
, int);
65 static ddg_edge_ptr
create_ddg_edge (ddg_node_ptr
, ddg_node_ptr
, dep_type
,
66 dep_data_type
, int, int);
67 static void add_edge_to_ddg (ddg_ptr g
, ddg_edge_ptr
);
69 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
70 static bool mem_ref_p
;
72 /* Auxiliary function for mem_read_insn_p. */
74 mark_mem_use (rtx
*x
, void *)
76 subrtx_iterator::array_type array
;
77 FOR_EACH_SUBRTX (iter
, array
, *x
, NONCONST
)
85 /* Returns nonzero if INSN reads from memory. */
87 mem_read_insn_p (rtx_insn
*insn
)
90 note_uses (&PATTERN (insn
), mark_mem_use
, NULL
);
95 mark_mem_store (rtx loc
, const_rtx setter ATTRIBUTE_UNUSED
, void *data ATTRIBUTE_UNUSED
)
101 /* Returns nonzero if INSN writes to memory. */
103 mem_write_insn_p (rtx_insn
*insn
)
106 note_stores (PATTERN (insn
), mark_mem_store
, NULL
);
110 /* Returns nonzero if X has access to memory. */
112 rtx_mem_access_p (rtx x
)
125 fmt
= GET_RTX_FORMAT (code
);
126 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
130 if (rtx_mem_access_p (XEXP (x
, i
)))
133 else if (fmt
[i
] == 'E')
134 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
136 if (rtx_mem_access_p (XVECEXP (x
, i
, j
)))
143 /* Returns nonzero if INSN reads to or writes from memory. */
145 mem_access_insn_p (rtx_insn
*insn
)
147 return rtx_mem_access_p (PATTERN (insn
));
150 /* Return true if DEF_INSN contains address being auto-inc or auto-dec
151 which is used in USE_INSN. Otherwise return false. The result is
152 being used to decide whether to remove the edge between def_insn and
153 use_insn when -fmodulo-sched-allow-regmoves is set. This function
154 doesn't need to consider the specific address register; no reg_moves
155 will be allowed for any life range defined by def_insn and used
156 by use_insn, if use_insn uses an address register auto-inc'ed by
159 autoinc_var_is_used_p (rtx_insn
*def_insn
, rtx_insn
*use_insn
)
163 for (note
= REG_NOTES (def_insn
); note
; note
= XEXP (note
, 1))
164 if (REG_NOTE_KIND (note
) == REG_INC
165 && reg_referenced_p (XEXP (note
, 0), PATTERN (use_insn
)))
171 /* Return true if one of the definitions in INSN has MODE_CC. Otherwise
174 def_has_ccmode_p (rtx_insn
*insn
)
178 FOR_EACH_INSN_DEF (def
, insn
)
180 machine_mode mode
= GET_MODE (DF_REF_REG (def
));
182 if (GET_MODE_CLASS (mode
) == MODE_CC
)
189 /* Computes the dependence parameters (latency, distance etc.), creates
190 a ddg_edge and adds it to the given DDG. */
192 create_ddg_dep_from_intra_loop_link (ddg_ptr g
, ddg_node_ptr src_node
,
193 ddg_node_ptr dest_node
, dep_t link
)
196 int latency
, distance
= 0;
197 dep_type t
= TRUE_DEP
;
198 dep_data_type dt
= (mem_access_insn_p (src_node
->insn
)
199 && mem_access_insn_p (dest_node
->insn
) ? MEM_DEP
201 gcc_assert (src_node
->cuid
< dest_node
->cuid
);
204 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
205 if (DEP_TYPE (link
) == REG_DEP_ANTI
)
207 else if (DEP_TYPE (link
) == REG_DEP_OUTPUT
)
210 gcc_assert (!DEBUG_INSN_P (dest_node
->insn
) || t
== ANTI_DEP
);
211 gcc_assert (!DEBUG_INSN_P (src_node
->insn
) || t
== ANTI_DEP
);
213 /* We currently choose not to create certain anti-deps edges and
214 compensate for that by generating reg-moves based on the life-range
215 analysis. The anti-deps that will be deleted are the ones which
216 have true-deps edges in the opposite direction (in other words
217 the kernel has only one def of the relevant register).
218 If the address that is being auto-inc or auto-dec in DEST_NODE
219 is used in SRC_NODE then do not remove the edge to make sure
220 reg-moves will not be created for this address.
221 TODO: support the removal of all anti-deps edges, i.e. including those
222 whose register has multiple defs in the loop. */
223 if (flag_modulo_sched_allow_regmoves
224 && (t
== ANTI_DEP
&& dt
== REG_DEP
)
225 && !def_has_ccmode_p (dest_node
->insn
)
226 && !autoinc_var_is_used_p (dest_node
->insn
, src_node
->insn
))
230 set
= single_set (dest_node
->insn
);
231 /* TODO: Handle registers that REG_P is not true for them, i.e.
232 subregs and special registers. */
233 if (set
&& REG_P (SET_DEST (set
)))
235 int regno
= REGNO (SET_DEST (set
));
237 struct df_rd_bb_info
*bb_info
= DF_RD_BB_INFO (g
->bb
);
239 first_def
= df_bb_regno_first_def_find (g
->bb
, regno
);
240 gcc_assert (first_def
);
242 if (bitmap_bit_p (&bb_info
->gen
, DF_REF_ID (first_def
)))
247 latency
= dep_cost (link
);
248 e
= create_ddg_edge (src_node
, dest_node
, t
, dt
, latency
, distance
);
249 add_edge_to_ddg (g
, e
);
252 /* The same as the above function, but it doesn't require a link parameter. */
254 create_ddg_dep_no_link (ddg_ptr g
, ddg_node_ptr from
, ddg_node_ptr to
,
255 dep_type d_t
, dep_data_type d_dt
, int distance
)
259 enum reg_note dep_kind
;
260 struct _dep _dep
, *dep
= &_dep
;
262 gcc_assert (!DEBUG_INSN_P (to
->insn
) || d_t
== ANTI_DEP
);
263 gcc_assert (!DEBUG_INSN_P (from
->insn
) || d_t
== ANTI_DEP
);
266 dep_kind
= REG_DEP_ANTI
;
267 else if (d_t
== OUTPUT_DEP
)
268 dep_kind
= REG_DEP_OUTPUT
;
271 gcc_assert (d_t
== TRUE_DEP
);
273 dep_kind
= REG_DEP_TRUE
;
276 init_dep (dep
, from
->insn
, to
->insn
, dep_kind
);
280 e
= create_ddg_edge (from
, to
, d_t
, d_dt
, l
, distance
);
282 add_backarc_to_ddg (g
, e
);
284 add_edge_to_ddg (g
, e
);
288 /* Given a downwards exposed register def LAST_DEF (which is the last
289 definition of that register in the bb), add inter-loop true dependences
290 to all its uses in the next iteration, an output dependence to the
291 first def of the same register (possibly itself) in the next iteration
292 and anti-dependences from its uses in the current iteration to the
293 first definition in the next iteration. */
295 add_cross_iteration_register_deps (ddg_ptr g
, df_ref last_def
)
297 int regno
= DF_REF_REGNO (last_def
);
298 struct df_link
*r_use
;
299 int has_use_in_bb_p
= false;
300 rtx_insn
*def_insn
= DF_REF_INSN (last_def
);
301 ddg_node_ptr last_def_node
= get_node_of_insn (g
, def_insn
);
302 ddg_node_ptr use_node
;
303 #ifdef ENABLE_CHECKING
304 struct df_rd_bb_info
*bb_info
= DF_RD_BB_INFO (g
->bb
);
306 df_ref first_def
= df_bb_regno_first_def_find (g
->bb
, regno
);
308 gcc_assert (last_def_node
);
309 gcc_assert (first_def
);
311 #ifdef ENABLE_CHECKING
312 if (DF_REF_ID (last_def
) != DF_REF_ID (first_def
))
313 gcc_assert (!bitmap_bit_p (&bb_info
->gen
,
314 DF_REF_ID (first_def
)));
317 /* Create inter-loop true dependences and anti dependences. */
318 for (r_use
= DF_REF_CHAIN (last_def
); r_use
!= NULL
; r_use
= r_use
->next
)
320 rtx_insn
*use_insn
= DF_REF_INSN (r_use
->ref
);
322 if (BLOCK_FOR_INSN (use_insn
) != g
->bb
)
325 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
326 use_node
= get_node_of_insn (g
, use_insn
);
327 gcc_assert (use_node
);
328 has_use_in_bb_p
= true;
329 if (use_node
->cuid
<= last_def_node
->cuid
)
331 /* Add true deps from last_def to it's uses in the next
332 iteration. Any such upwards exposed use appears before
334 create_ddg_dep_no_link (g
, last_def_node
, use_node
,
335 DEBUG_INSN_P (use_insn
) ? ANTI_DEP
: TRUE_DEP
,
338 else if (!DEBUG_INSN_P (use_insn
))
340 /* Add anti deps from last_def's uses in the current iteration
341 to the first def in the next iteration. We do not add ANTI
342 dep when there is an intra-loop TRUE dep in the opposite
343 direction, but use regmoves to fix such disregarded ANTI
344 deps when broken. If the first_def reaches the USE then
345 there is such a dep. */
346 ddg_node_ptr first_def_node
= get_node_of_insn (g
,
347 DF_REF_INSN (first_def
));
349 gcc_assert (first_def_node
);
351 /* Always create the edge if the use node is a branch in
352 order to prevent the creation of reg-moves.
353 If the address that is being auto-inc or auto-dec in LAST_DEF
354 is used in USE_INSN then do not remove the edge to make sure
355 reg-moves will not be created for that address. */
356 if (DF_REF_ID (last_def
) != DF_REF_ID (first_def
)
357 || !flag_modulo_sched_allow_regmoves
358 || JUMP_P (use_node
->insn
)
359 || autoinc_var_is_used_p (DF_REF_INSN (last_def
), use_insn
)
360 || def_has_ccmode_p (DF_REF_INSN (last_def
)))
361 create_ddg_dep_no_link (g
, use_node
, first_def_node
, ANTI_DEP
,
366 /* Create an inter-loop output dependence between LAST_DEF (which is the
367 last def in its block, being downwards exposed) and the first def in
368 its block. Avoid creating a self output dependence. Avoid creating
369 an output dependence if there is a dependence path between the two
370 defs starting with a true dependence to a use which can be in the
371 next iteration; followed by an anti dependence of that use to the
372 first def (i.e. if there is a use between the two defs.) */
373 if (!has_use_in_bb_p
)
375 ddg_node_ptr dest_node
;
377 if (DF_REF_ID (last_def
) == DF_REF_ID (first_def
))
380 dest_node
= get_node_of_insn (g
, DF_REF_INSN (first_def
));
381 gcc_assert (dest_node
);
382 create_ddg_dep_no_link (g
, last_def_node
, dest_node
,
383 OUTPUT_DEP
, REG_DEP
, 1);
386 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
388 build_inter_loop_deps (ddg_ptr g
)
391 struct df_rd_bb_info
*rd_bb_info
;
394 rd_bb_info
= DF_RD_BB_INFO (g
->bb
);
396 /* Find inter-loop register output, true and anti deps. */
397 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info
->gen
, 0, rd_num
, bi
)
399 df_ref rd
= DF_DEFS_GET (rd_num
);
401 add_cross_iteration_register_deps (g
, rd
);
406 /* Return true if two specified instructions have mem expr with conflict
409 insns_may_alias_p (rtx_insn
*insn1
, rtx_insn
*insn2
)
411 subrtx_iterator::array_type array1
;
412 subrtx_iterator::array_type array2
;
413 FOR_EACH_SUBRTX (iter1
, array1
, PATTERN (insn1
), NONCONST
)
415 const_rtx x1
= *iter1
;
417 FOR_EACH_SUBRTX (iter2
, array2
, PATTERN (insn2
), NONCONST
)
419 const_rtx x2
= *iter2
;
420 if (MEM_P (x2
) && may_alias_p (x2
, x1
))
427 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
430 add_intra_loop_mem_dep (ddg_ptr g
, ddg_node_ptr from
, ddg_node_ptr to
)
433 if ((from
->cuid
== to
->cuid
)
434 || !insns_may_alias_p (from
->insn
, to
->insn
))
435 /* Do not create edge if memory references have disjoint alias sets
436 or 'to' and 'from' are the same instruction. */
439 if (mem_write_insn_p (from
->insn
))
441 if (mem_read_insn_p (to
->insn
))
442 create_ddg_dep_no_link (g
, from
, to
,
443 DEBUG_INSN_P (to
->insn
)
444 ? ANTI_DEP
: TRUE_DEP
, MEM_DEP
, 0);
446 create_ddg_dep_no_link (g
, from
, to
,
447 DEBUG_INSN_P (to
->insn
)
448 ? ANTI_DEP
: OUTPUT_DEP
, MEM_DEP
, 0);
450 else if (!mem_read_insn_p (to
->insn
))
451 create_ddg_dep_no_link (g
, from
, to
, ANTI_DEP
, MEM_DEP
, 0);
454 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
457 add_inter_loop_mem_dep (ddg_ptr g
, ddg_node_ptr from
, ddg_node_ptr to
)
459 if (!insns_may_alias_p (from
->insn
, to
->insn
))
460 /* Do not create edge if memory references have disjoint alias sets. */
463 if (mem_write_insn_p (from
->insn
))
465 if (mem_read_insn_p (to
->insn
))
466 create_ddg_dep_no_link (g
, from
, to
,
467 DEBUG_INSN_P (to
->insn
)
468 ? ANTI_DEP
: TRUE_DEP
, MEM_DEP
, 1);
469 else if (from
->cuid
!= to
->cuid
)
470 create_ddg_dep_no_link (g
, from
, to
,
471 DEBUG_INSN_P (to
->insn
)
472 ? ANTI_DEP
: OUTPUT_DEP
, MEM_DEP
, 1);
476 if (mem_read_insn_p (to
->insn
))
478 else if (from
->cuid
!= to
->cuid
)
480 create_ddg_dep_no_link (g
, from
, to
, ANTI_DEP
, MEM_DEP
, 1);
481 if (DEBUG_INSN_P (from
->insn
) || DEBUG_INSN_P (to
->insn
))
482 create_ddg_dep_no_link (g
, to
, from
, ANTI_DEP
, MEM_DEP
, 1);
484 create_ddg_dep_no_link (g
, to
, from
, TRUE_DEP
, MEM_DEP
, 1);
490 /* Perform intra-block Data Dependency analysis and connect the nodes in
491 the DDG. We assume the loop has a single basic block. */
493 build_intra_loop_deps (ddg_ptr g
)
496 /* Hold the dependency analysis state during dependency calculations. */
497 struct deps_desc tmp_deps
;
498 rtx_insn
*head
, *tail
;
500 /* Build the dependence information, using the sched_analyze function. */
502 init_deps (&tmp_deps
, false);
504 /* Do the intra-block data dependence analysis for the given block. */
505 get_ebb_head_tail (g
->bb
, g
->bb
, &head
, &tail
);
506 sched_analyze (&tmp_deps
, head
, tail
);
508 /* Build intra-loop data dependencies using the scheduler dependency
510 for (i
= 0; i
< g
->num_nodes
; i
++)
512 ddg_node_ptr dest_node
= &g
->nodes
[i
];
513 sd_iterator_def sd_it
;
516 if (! INSN_P (dest_node
->insn
))
519 FOR_EACH_DEP (dest_node
->insn
, SD_LIST_BACK
, sd_it
, dep
)
521 rtx_insn
*src_insn
= DEP_PRO (dep
);
522 ddg_node_ptr src_node
;
524 /* Don't add dependencies on debug insns to non-debug insns
525 to avoid codegen differences between -g and -g0. */
526 if (DEBUG_INSN_P (src_insn
) && !DEBUG_INSN_P (dest_node
->insn
))
529 src_node
= get_node_of_insn (g
, src_insn
);
534 create_ddg_dep_from_intra_loop_link (g
, src_node
, dest_node
, dep
);
537 /* If this insn modifies memory, add an edge to all insns that access
539 if (mem_access_insn_p (dest_node
->insn
))
543 for (j
= 0; j
<= i
; j
++)
545 ddg_node_ptr j_node
= &g
->nodes
[j
];
546 if (DEBUG_INSN_P (j_node
->insn
))
548 if (mem_access_insn_p (j_node
->insn
))
550 /* Don't bother calculating inter-loop dep if an intra-loop dep
552 if (! bitmap_bit_p (dest_node
->successors
, j
))
553 add_inter_loop_mem_dep (g
, dest_node
, j_node
);
554 /* If -fmodulo-sched-allow-regmoves
555 is set certain anti-dep edges are not created.
556 It might be that these anti-dep edges are on the
557 path from one memory instruction to another such that
558 removing these edges could cause a violation of the
559 memory dependencies. Thus we add intra edges between
560 every two memory instructions in this case. */
561 if (flag_modulo_sched_allow_regmoves
562 && !bitmap_bit_p (dest_node
->predecessors
, j
))
563 add_intra_loop_mem_dep (g
, j_node
, dest_node
);
569 /* Free the INSN_LISTs. */
570 finish_deps_global ();
571 free_deps (&tmp_deps
);
573 /* Free dependencies. */
574 sched_free_deps (head
, tail
, false);
578 /* Given a basic block, create its DDG and return a pointer to a variable
579 of ddg type that represents it.
580 Initialize the ddg structure fields to the appropriate values. */
582 create_ddg (basic_block bb
, int closing_branch_deps
)
585 rtx_insn
*insn
, *first_note
;
589 g
= (ddg_ptr
) xcalloc (1, sizeof (struct ddg
));
592 g
->closing_branch_deps
= closing_branch_deps
;
594 /* Count the number of insns in the BB. */
595 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
596 insn
= NEXT_INSN (insn
))
598 if (! INSN_P (insn
) || GET_CODE (PATTERN (insn
)) == USE
)
601 if (DEBUG_INSN_P (insn
))
605 if (mem_read_insn_p (insn
))
607 if (mem_write_insn_p (insn
))
613 /* There is nothing to do for this BB. */
614 if ((num_nodes
- g
->num_debug
) <= 1)
620 /* Allocate the nodes array, and initialize the nodes. */
621 g
->num_nodes
= num_nodes
;
622 g
->nodes
= (ddg_node_ptr
) xcalloc (num_nodes
, sizeof (struct ddg_node
));
623 g
->closing_branch
= NULL
;
626 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
627 insn
= NEXT_INSN (insn
))
631 if (! first_note
&& NOTE_P (insn
)
632 && NOTE_KIND (insn
) != NOTE_INSN_BASIC_BLOCK
)
638 gcc_assert (!g
->closing_branch
);
639 g
->closing_branch
= &g
->nodes
[i
];
641 else if (GET_CODE (PATTERN (insn
)) == USE
)
648 g
->nodes
[i
].cuid
= i
;
649 g
->nodes
[i
].successors
= sbitmap_alloc (num_nodes
);
650 bitmap_clear (g
->nodes
[i
].successors
);
651 g
->nodes
[i
].predecessors
= sbitmap_alloc (num_nodes
);
652 bitmap_clear (g
->nodes
[i
].predecessors
);
653 g
->nodes
[i
].first_note
= (first_note
? first_note
: insn
);
654 g
->nodes
[i
++].insn
= insn
;
658 /* We must have found a branch in DDG. */
659 gcc_assert (g
->closing_branch
);
662 /* Build the data dependency graph. */
663 build_intra_loop_deps (g
);
664 build_inter_loop_deps (g
);
668 /* Free all the memory allocated for the DDG. */
677 for (i
= 0; i
< g
->num_nodes
; i
++)
679 ddg_edge_ptr e
= g
->nodes
[i
].out
;
683 ddg_edge_ptr next
= e
->next_out
;
688 sbitmap_free (g
->nodes
[i
].successors
);
689 sbitmap_free (g
->nodes
[i
].predecessors
);
691 if (g
->num_backarcs
> 0)
698 print_ddg_edge (FILE *file
, ddg_edge_ptr e
)
714 fprintf (file
, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e
->src
->insn
),
715 dep_c
, e
->latency
, e
->distance
, INSN_UID (e
->dest
->insn
));
718 /* Print the DDG nodes with there in/out edges to the dump file. */
720 print_ddg (FILE *file
, ddg_ptr g
)
724 for (i
= 0; i
< g
->num_nodes
; i
++)
728 fprintf (file
, "Node num: %d\n", g
->nodes
[i
].cuid
);
729 print_rtl_single (file
, g
->nodes
[i
].insn
);
730 fprintf (file
, "OUT ARCS: ");
731 for (e
= g
->nodes
[i
].out
; e
; e
= e
->next_out
)
732 print_ddg_edge (file
, e
);
734 fprintf (file
, "\nIN ARCS: ");
735 for (e
= g
->nodes
[i
].in
; e
; e
= e
->next_in
)
736 print_ddg_edge (file
, e
);
738 fprintf (file
, "\n");
742 /* Print the given DDG in VCG format. */
744 vcg_print_ddg (FILE *file
, ddg_ptr g
)
748 fprintf (file
, "graph: {\n");
749 for (src_cuid
= 0; src_cuid
< g
->num_nodes
; src_cuid
++)
752 int src_uid
= INSN_UID (g
->nodes
[src_cuid
].insn
);
754 fprintf (file
, "node: {title: \"%d_%d\" info1: \"", src_cuid
, src_uid
);
755 print_rtl_single (file
, g
->nodes
[src_cuid
].insn
);
756 fprintf (file
, "\"}\n");
757 for (e
= g
->nodes
[src_cuid
].out
; e
; e
= e
->next_out
)
759 int dst_uid
= INSN_UID (e
->dest
->insn
);
760 int dst_cuid
= e
->dest
->cuid
;
762 /* Give the backarcs a different color. */
764 fprintf (file
, "backedge: {color: red ");
766 fprintf (file
, "edge: { ");
768 fprintf (file
, "sourcename: \"%d_%d\" ", src_cuid
, src_uid
);
769 fprintf (file
, "targetname: \"%d_%d\" ", dst_cuid
, dst_uid
);
770 fprintf (file
, "label: \"%d_%d\"}\n", e
->latency
, e
->distance
);
773 fprintf (file
, "}\n");
776 /* Dump the sccs in SCCS. */
778 print_sccs (FILE *file
, ddg_all_sccs_ptr sccs
, ddg_ptr g
)
781 sbitmap_iterator sbi
;
787 fprintf (file
, "\n;; Number of SCC nodes - %d\n", sccs
->num_sccs
);
788 for (i
= 0; i
< sccs
->num_sccs
; i
++)
790 fprintf (file
, "SCC number: %d\n", i
);
791 EXECUTE_IF_SET_IN_BITMAP (sccs
->sccs
[i
]->nodes
, 0, u
, sbi
)
793 fprintf (file
, "insn num %d\n", u
);
794 print_rtl_single (file
, g
->nodes
[u
].insn
);
797 fprintf (file
, "\n");
800 /* Create an edge and initialize it with given values. */
802 create_ddg_edge (ddg_node_ptr src
, ddg_node_ptr dest
,
803 dep_type t
, dep_data_type dt
, int l
, int d
)
805 ddg_edge_ptr e
= (ddg_edge_ptr
) xmalloc (sizeof (struct ddg_edge
));
813 e
->next_in
= e
->next_out
= NULL
;
818 /* Add the given edge to the in/out linked lists of the DDG nodes. */
820 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED
, ddg_edge_ptr e
)
822 ddg_node_ptr src
= e
->src
;
823 ddg_node_ptr dest
= e
->dest
;
825 /* Should have allocated the sbitmaps. */
826 gcc_assert (src
->successors
&& dest
->predecessors
);
828 bitmap_set_bit (src
->successors
, dest
->cuid
);
829 bitmap_set_bit (dest
->predecessors
, src
->cuid
);
830 e
->next_in
= dest
->in
;
832 e
->next_out
= src
->out
;
838 /* Algorithm for computing the recurrence_length of an scc. We assume at
839 for now that cycles in the data dependence graph contain a single backarc.
840 This simplifies the algorithm, and can be generalized later. */
842 set_recurrence_length (ddg_scc_ptr scc
, ddg_ptr g
)
847 for (j
= 0; j
< scc
->num_backarcs
; j
++)
849 ddg_edge_ptr backarc
= scc
->backarcs
[j
];
851 int distance
= backarc
->distance
;
852 ddg_node_ptr src
= backarc
->dest
;
853 ddg_node_ptr dest
= backarc
->src
;
855 length
= longest_simple_path (g
, src
->cuid
, dest
->cuid
, scc
->nodes
);
858 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
861 length
+= backarc
->latency
;
862 result
= MAX (result
, (length
/ distance
));
864 scc
->recurrence_length
= result
;
867 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
868 and mark edges that belong to this scc as IN_SCC. */
870 create_scc (ddg_ptr g
, sbitmap nodes
)
874 sbitmap_iterator sbi
;
876 scc
= (ddg_scc_ptr
) xmalloc (sizeof (struct ddg_scc
));
877 scc
->backarcs
= NULL
;
878 scc
->num_backarcs
= 0;
879 scc
->nodes
= sbitmap_alloc (g
->num_nodes
);
880 bitmap_copy (scc
->nodes
, nodes
);
882 /* Mark the backarcs that belong to this SCC. */
883 EXECUTE_IF_SET_IN_BITMAP (nodes
, 0, u
, sbi
)
886 ddg_node_ptr n
= &g
->nodes
[u
];
888 for (e
= n
->out
; e
; e
= e
->next_out
)
889 if (bitmap_bit_p (nodes
, e
->dest
->cuid
))
891 e
->aux
.count
= IN_SCC
;
893 add_backarc_to_scc (scc
, e
);
897 set_recurrence_length (scc
, g
);
901 /* Cleans the memory allocation of a given SCC. */
903 free_scc (ddg_scc_ptr scc
)
908 sbitmap_free (scc
->nodes
);
909 if (scc
->num_backarcs
> 0)
910 free (scc
->backarcs
);
915 /* Add a given edge known to be a backarc to the given DDG. */
917 add_backarc_to_ddg (ddg_ptr g
, ddg_edge_ptr e
)
919 int size
= (g
->num_backarcs
+ 1) * sizeof (ddg_edge_ptr
);
921 add_edge_to_ddg (g
, e
);
922 g
->backarcs
= (ddg_edge_ptr
*) xrealloc (g
->backarcs
, size
);
923 g
->backarcs
[g
->num_backarcs
++] = e
;
926 /* Add backarc to an SCC. */
928 add_backarc_to_scc (ddg_scc_ptr scc
, ddg_edge_ptr e
)
930 int size
= (scc
->num_backarcs
+ 1) * sizeof (ddg_edge_ptr
);
932 scc
->backarcs
= (ddg_edge_ptr
*) xrealloc (scc
->backarcs
, size
);
933 scc
->backarcs
[scc
->num_backarcs
++] = e
;
936 /* Add the given SCC to the DDG. */
938 add_scc_to_ddg (ddg_all_sccs_ptr g
, ddg_scc_ptr scc
)
940 int size
= (g
->num_sccs
+ 1) * sizeof (ddg_scc_ptr
);
942 g
->sccs
= (ddg_scc_ptr
*) xrealloc (g
->sccs
, size
);
943 g
->sccs
[g
->num_sccs
++] = scc
;
946 /* Given the instruction INSN return the node that represents it. */
948 get_node_of_insn (ddg_ptr g
, rtx_insn
*insn
)
952 for (i
= 0; i
< g
->num_nodes
; i
++)
953 if (insn
== g
->nodes
[i
].insn
)
958 /* Given a set OPS of nodes in the DDG, find the set of their successors
959 which are not in OPS, and set their bits in SUCC. Bits corresponding to
960 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
962 find_successors (sbitmap succ
, ddg_ptr g
, sbitmap ops
)
965 sbitmap_iterator sbi
;
967 EXECUTE_IF_SET_IN_BITMAP (ops
, 0, i
, sbi
)
969 const sbitmap node_succ
= NODE_SUCCESSORS (&g
->nodes
[i
]);
970 bitmap_ior (succ
, succ
, node_succ
);
973 /* We want those that are not in ops. */
974 bitmap_and_compl (succ
, succ
, ops
);
977 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
978 which are not in OPS, and set their bits in PREDS. Bits corresponding to
979 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
981 find_predecessors (sbitmap preds
, ddg_ptr g
, sbitmap ops
)
984 sbitmap_iterator sbi
;
986 EXECUTE_IF_SET_IN_BITMAP (ops
, 0, i
, sbi
)
988 const sbitmap node_preds
= NODE_PREDECESSORS (&g
->nodes
[i
]);
989 bitmap_ior (preds
, preds
, node_preds
);
992 /* We want those that are not in ops. */
993 bitmap_and_compl (preds
, preds
, ops
);
997 /* Compare function to be passed to qsort to order the backarcs in descending
1000 compare_sccs (const void *s1
, const void *s2
)
1002 const int rec_l1
= (*(const ddg_scc_ptr
*)s1
)->recurrence_length
;
1003 const int rec_l2
= (*(const ddg_scc_ptr
*)s2
)->recurrence_length
;
1004 return ((rec_l2
> rec_l1
) - (rec_l2
< rec_l1
));
1008 /* Order the backarcs in descending recMII order using compare_sccs. */
1010 order_sccs (ddg_all_sccs_ptr g
)
1012 qsort (g
->sccs
, g
->num_sccs
, sizeof (ddg_scc_ptr
),
1013 (int (*) (const void *, const void *)) compare_sccs
);
1016 #ifdef ENABLE_CHECKING
1017 /* Check that every node in SCCS belongs to exactly one strongly connected
1018 component and that no element of SCCS is empty. */
1020 check_sccs (ddg_all_sccs_ptr sccs
, int num_nodes
)
1023 sbitmap tmp
= sbitmap_alloc (num_nodes
);
1026 for (i
= 0; i
< sccs
->num_sccs
; i
++)
1028 gcc_assert (!bitmap_empty_p (sccs
->sccs
[i
]->nodes
));
1029 /* Verify that every node in sccs is in exactly one strongly
1030 connected component. */
1031 gcc_assert (!bitmap_intersect_p (tmp
, sccs
->sccs
[i
]->nodes
));
1032 bitmap_ior (tmp
, tmp
, sccs
->sccs
[i
]->nodes
);
1038 /* Perform the Strongly Connected Components decomposing algorithm on the
1039 DDG and return DDG_ALL_SCCS structure that contains them. */
1041 create_ddg_all_sccs (ddg_ptr g
)
1044 int num_nodes
= g
->num_nodes
;
1045 sbitmap from
= sbitmap_alloc (num_nodes
);
1046 sbitmap to
= sbitmap_alloc (num_nodes
);
1047 sbitmap scc_nodes
= sbitmap_alloc (num_nodes
);
1048 ddg_all_sccs_ptr sccs
= (ddg_all_sccs_ptr
)
1049 xmalloc (sizeof (struct ddg_all_sccs
));
1055 for (i
= 0; i
< g
->num_backarcs
; i
++)
1058 ddg_edge_ptr backarc
= g
->backarcs
[i
];
1059 ddg_node_ptr src
= backarc
->src
;
1060 ddg_node_ptr dest
= backarc
->dest
;
1062 /* If the backarc already belongs to an SCC, continue. */
1063 if (backarc
->aux
.count
== IN_SCC
)
1066 bitmap_clear (scc_nodes
);
1067 bitmap_clear (from
);
1069 bitmap_set_bit (from
, dest
->cuid
);
1070 bitmap_set_bit (to
, src
->cuid
);
1072 if (find_nodes_on_paths (scc_nodes
, g
, from
, to
))
1074 scc
= create_scc (g
, scc_nodes
);
1075 add_scc_to_ddg (sccs
, scc
);
1079 sbitmap_free (from
);
1081 sbitmap_free (scc_nodes
);
1082 #ifdef ENABLE_CHECKING
1083 check_sccs (sccs
, num_nodes
);
1088 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1090 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs
)
1097 for (i
= 0; i
< all_sccs
->num_sccs
; i
++)
1098 free_scc (all_sccs
->sccs
[i
]);
1100 free (all_sccs
->sccs
);
1105 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1106 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1107 nodes from FROM and TO). Return nonzero if nodes exist. */
1109 find_nodes_on_paths (sbitmap result
, ddg_ptr g
, sbitmap from
, sbitmap to
)
1114 int num_nodes
= g
->num_nodes
;
1115 sbitmap_iterator sbi
;
1117 sbitmap workset
= sbitmap_alloc (num_nodes
);
1118 sbitmap reachable_from
= sbitmap_alloc (num_nodes
);
1119 sbitmap reach_to
= sbitmap_alloc (num_nodes
);
1120 sbitmap tmp
= sbitmap_alloc (num_nodes
);
1122 bitmap_copy (reachable_from
, from
);
1123 bitmap_copy (tmp
, from
);
1129 bitmap_copy (workset
, tmp
);
1131 EXECUTE_IF_SET_IN_BITMAP (workset
, 0, u
, sbi
)
1134 ddg_node_ptr u_node
= &g
->nodes
[u
];
1136 for (e
= u_node
->out
; e
!= (ddg_edge_ptr
) 0; e
= e
->next_out
)
1138 ddg_node_ptr v_node
= e
->dest
;
1139 int v
= v_node
->cuid
;
1141 if (!bitmap_bit_p (reachable_from
, v
))
1143 bitmap_set_bit (reachable_from
, v
);
1144 bitmap_set_bit (tmp
, v
);
1151 bitmap_copy (reach_to
, to
);
1152 bitmap_copy (tmp
, to
);
1158 bitmap_copy (workset
, tmp
);
1160 EXECUTE_IF_SET_IN_BITMAP (workset
, 0, u
, sbi
)
1163 ddg_node_ptr u_node
= &g
->nodes
[u
];
1165 for (e
= u_node
->in
; e
!= (ddg_edge_ptr
) 0; e
= e
->next_in
)
1167 ddg_node_ptr v_node
= e
->src
;
1168 int v
= v_node
->cuid
;
1170 if (!bitmap_bit_p (reach_to
, v
))
1172 bitmap_set_bit (reach_to
, v
);
1173 bitmap_set_bit (tmp
, v
);
1180 answer
= bitmap_and (result
, reachable_from
, reach_to
);
1181 sbitmap_free (workset
);
1182 sbitmap_free (reachable_from
);
1183 sbitmap_free (reach_to
);
1189 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1190 at-least as large as the count of U_NODE plus the latency between them.
1191 Sets a bit in TMP for each successor whose count was changed (increased).
1192 Returns nonzero if any count was changed. */
1194 update_dist_to_successors (ddg_node_ptr u_node
, sbitmap nodes
, sbitmap tmp
)
1199 for (e
= u_node
->out
; e
; e
= e
->next_out
)
1201 ddg_node_ptr v_node
= e
->dest
;
1202 int v
= v_node
->cuid
;
1204 if (bitmap_bit_p (nodes
, v
)
1205 && (e
->distance
== 0)
1206 && (v_node
->aux
.count
< u_node
->aux
.count
+ e
->latency
))
1208 v_node
->aux
.count
= u_node
->aux
.count
+ e
->latency
;
1209 bitmap_set_bit (tmp
, v
);
1217 /* Find the length of a longest path from SRC to DEST in G,
1218 going only through NODES, and disregarding backarcs. */
1220 longest_simple_path (struct ddg
* g
, int src
, int dest
, sbitmap nodes
)
1226 int num_nodes
= g
->num_nodes
;
1227 sbitmap workset
= sbitmap_alloc (num_nodes
);
1228 sbitmap tmp
= sbitmap_alloc (num_nodes
);
1231 /* Data will hold the distance of the longest path found so far from
1232 src to each node. Initialize to -1 = less than minimum. */
1233 for (i
= 0; i
< g
->num_nodes
; i
++)
1234 g
->nodes
[i
].aux
.count
= -1;
1235 g
->nodes
[src
].aux
.count
= 0;
1238 bitmap_set_bit (tmp
, src
);
1242 sbitmap_iterator sbi
;
1245 bitmap_copy (workset
, tmp
);
1247 EXECUTE_IF_SET_IN_BITMAP (workset
, 0, u
, sbi
)
1249 ddg_node_ptr u_node
= &g
->nodes
[u
];
1251 change
|= update_dist_to_successors (u_node
, nodes
, tmp
);
1254 result
= g
->nodes
[dest
].aux
.count
;
1255 sbitmap_free (workset
);
1260 #endif /* INSN_SCHEDULING */