[35/77] Add uses of as_a <scalar_int_mode>
[official-gcc.git] / gcc / ddg.c
blob8aaed80dec4ac19b848d4a9546dac9638fe3645a
1 /* DDG - Data Dependence Graph implementation.
2 Copyright (C) 2004-2017 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
10 version.
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
15 for more details.
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/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "backend.h"
26 #include "rtl.h"
27 #include "df.h"
28 #include "insn-attr.h"
29 #include "sched-int.h"
30 #include "ddg.h"
31 #include "rtl-iter.h"
33 #ifdef INSN_SCHEDULING
35 /* A flag indicating that a ddg edge belongs to an SCC or not. */
36 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
38 /* Forward declarations. */
39 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
40 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
41 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
42 static void create_ddg_dep_from_intra_loop_link (ddg_ptr, ddg_node_ptr,
43 ddg_node_ptr, dep_t);
44 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
45 dep_type, dep_data_type, int);
46 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
47 dep_data_type, int, int);
48 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
50 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
51 static bool mem_ref_p;
53 /* Auxiliary function for mem_read_insn_p. */
54 static void
55 mark_mem_use (rtx *x, void *)
57 subrtx_iterator::array_type array;
58 FOR_EACH_SUBRTX (iter, array, *x, NONCONST)
59 if (MEM_P (*iter))
61 mem_ref_p = true;
62 break;
66 /* Returns nonzero if INSN reads from memory. */
67 static bool
68 mem_read_insn_p (rtx_insn *insn)
70 mem_ref_p = false;
71 note_uses (&PATTERN (insn), mark_mem_use, NULL);
72 return mem_ref_p;
75 static void
76 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
78 if (MEM_P (loc))
79 mem_ref_p = true;
82 /* Returns nonzero if INSN writes to memory. */
83 static bool
84 mem_write_insn_p (rtx_insn *insn)
86 mem_ref_p = false;
87 note_stores (PATTERN (insn), mark_mem_store, NULL);
88 return mem_ref_p;
91 /* Returns nonzero if X has access to memory. */
92 static bool
93 rtx_mem_access_p (rtx x)
95 int i, j;
96 const char *fmt;
97 enum rtx_code code;
99 if (x == 0)
100 return false;
102 if (MEM_P (x))
103 return true;
105 code = GET_CODE (x);
106 fmt = GET_RTX_FORMAT (code);
107 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
109 if (fmt[i] == 'e')
111 if (rtx_mem_access_p (XEXP (x, i)))
112 return true;
114 else if (fmt[i] == 'E')
115 for (j = 0; j < XVECLEN (x, i); j++)
117 if (rtx_mem_access_p (XVECEXP (x, i, j)))
118 return true;
121 return false;
124 /* Returns nonzero if INSN reads to or writes from memory. */
125 static bool
126 mem_access_insn_p (rtx_insn *insn)
128 return rtx_mem_access_p (PATTERN (insn));
131 /* Return true if DEF_INSN contains address being auto-inc or auto-dec
132 which is used in USE_INSN. Otherwise return false. The result is
133 being used to decide whether to remove the edge between def_insn and
134 use_insn when -fmodulo-sched-allow-regmoves is set. This function
135 doesn't need to consider the specific address register; no reg_moves
136 will be allowed for any life range defined by def_insn and used
137 by use_insn, if use_insn uses an address register auto-inc'ed by
138 def_insn. */
139 bool
140 autoinc_var_is_used_p (rtx_insn *def_insn, rtx_insn *use_insn)
142 rtx note;
144 for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
145 if (REG_NOTE_KIND (note) == REG_INC
146 && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
147 return true;
149 return false;
152 /* Return true if one of the definitions in INSN has MODE_CC. Otherwise
153 return false. */
154 static bool
155 def_has_ccmode_p (rtx_insn *insn)
157 df_ref def;
159 FOR_EACH_INSN_DEF (def, insn)
161 machine_mode mode = GET_MODE (DF_REF_REG (def));
163 if (GET_MODE_CLASS (mode) == MODE_CC)
164 return true;
167 return false;
170 /* Computes the dependence parameters (latency, distance etc.), creates
171 a ddg_edge and adds it to the given DDG. */
172 static void
173 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
174 ddg_node_ptr dest_node, dep_t link)
176 ddg_edge_ptr e;
177 int latency, distance = 0;
178 dep_type t = TRUE_DEP;
179 dep_data_type dt = (mem_access_insn_p (src_node->insn)
180 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
181 : REG_DEP);
182 gcc_assert (src_node->cuid < dest_node->cuid);
183 gcc_assert (link);
185 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
186 if (DEP_TYPE (link) == REG_DEP_ANTI)
187 t = ANTI_DEP;
188 else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
189 t = OUTPUT_DEP;
191 gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
192 gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
194 /* We currently choose not to create certain anti-deps edges and
195 compensate for that by generating reg-moves based on the life-range
196 analysis. The anti-deps that will be deleted are the ones which
197 have true-deps edges in the opposite direction (in other words
198 the kernel has only one def of the relevant register).
199 If the address that is being auto-inc or auto-dec in DEST_NODE
200 is used in SRC_NODE then do not remove the edge to make sure
201 reg-moves will not be created for this address.
202 TODO: support the removal of all anti-deps edges, i.e. including those
203 whose register has multiple defs in the loop. */
204 if (flag_modulo_sched_allow_regmoves
205 && (t == ANTI_DEP && dt == REG_DEP)
206 && !def_has_ccmode_p (dest_node->insn)
207 && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
209 rtx set;
211 set = single_set (dest_node->insn);
212 /* TODO: Handle registers that REG_P is not true for them, i.e.
213 subregs and special registers. */
214 if (set && REG_P (SET_DEST (set)))
216 int regno = REGNO (SET_DEST (set));
217 df_ref first_def;
218 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
220 first_def = df_bb_regno_first_def_find (g->bb, regno);
221 gcc_assert (first_def);
223 if (bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)))
224 return;
228 latency = dep_cost (link);
229 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
230 add_edge_to_ddg (g, e);
233 /* The same as the above function, but it doesn't require a link parameter. */
234 static void
235 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
236 dep_type d_t, dep_data_type d_dt, int distance)
238 ddg_edge_ptr e;
239 int l;
240 enum reg_note dep_kind;
241 struct _dep _dep, *dep = &_dep;
243 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
244 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
246 if (d_t == ANTI_DEP)
247 dep_kind = REG_DEP_ANTI;
248 else if (d_t == OUTPUT_DEP)
249 dep_kind = REG_DEP_OUTPUT;
250 else
252 gcc_assert (d_t == TRUE_DEP);
254 dep_kind = REG_DEP_TRUE;
257 init_dep (dep, from->insn, to->insn, dep_kind);
259 l = dep_cost (dep);
261 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
262 if (distance > 0)
263 add_backarc_to_ddg (g, e);
264 else
265 add_edge_to_ddg (g, e);
269 /* Given a downwards exposed register def LAST_DEF (which is the last
270 definition of that register in the bb), add inter-loop true dependences
271 to all its uses in the next iteration, an output dependence to the
272 first def of the same register (possibly itself) in the next iteration
273 and anti-dependences from its uses in the current iteration to the
274 first definition in the next iteration. */
275 static void
276 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
278 int regno = DF_REF_REGNO (last_def);
279 struct df_link *r_use;
280 int has_use_in_bb_p = false;
281 rtx_insn *def_insn = DF_REF_INSN (last_def);
282 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
283 ddg_node_ptr use_node;
284 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
286 gcc_assert (last_def_node);
287 gcc_assert (first_def);
289 if (flag_checking && DF_REF_ID (last_def) != DF_REF_ID (first_def))
291 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
292 gcc_assert (!bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)));
295 /* Create inter-loop true dependences and anti dependences. */
296 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
298 rtx_insn *use_insn = DF_REF_INSN (r_use->ref);
300 if (BLOCK_FOR_INSN (use_insn) != g->bb)
301 continue;
303 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
304 use_node = get_node_of_insn (g, use_insn);
305 gcc_assert (use_node);
306 has_use_in_bb_p = true;
307 if (use_node->cuid <= last_def_node->cuid)
309 /* Add true deps from last_def to it's uses in the next
310 iteration. Any such upwards exposed use appears before
311 the last_def def. */
312 create_ddg_dep_no_link (g, last_def_node, use_node,
313 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
314 REG_DEP, 1);
316 else if (!DEBUG_INSN_P (use_insn))
318 /* Add anti deps from last_def's uses in the current iteration
319 to the first def in the next iteration. We do not add ANTI
320 dep when there is an intra-loop TRUE dep in the opposite
321 direction, but use regmoves to fix such disregarded ANTI
322 deps when broken. If the first_def reaches the USE then
323 there is such a dep. */
324 ddg_node_ptr first_def_node = get_node_of_insn (g,
325 DF_REF_INSN (first_def));
327 gcc_assert (first_def_node);
329 /* Always create the edge if the use node is a branch in
330 order to prevent the creation of reg-moves.
331 If the address that is being auto-inc or auto-dec in LAST_DEF
332 is used in USE_INSN then do not remove the edge to make sure
333 reg-moves will not be created for that address. */
334 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
335 || !flag_modulo_sched_allow_regmoves
336 || JUMP_P (use_node->insn)
337 || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
338 || def_has_ccmode_p (DF_REF_INSN (last_def)))
339 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
340 REG_DEP, 1);
344 /* Create an inter-loop output dependence between LAST_DEF (which is the
345 last def in its block, being downwards exposed) and the first def in
346 its block. Avoid creating a self output dependence. Avoid creating
347 an output dependence if there is a dependence path between the two
348 defs starting with a true dependence to a use which can be in the
349 next iteration; followed by an anti dependence of that use to the
350 first def (i.e. if there is a use between the two defs.) */
351 if (!has_use_in_bb_p)
353 ddg_node_ptr dest_node;
355 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
356 return;
358 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
359 gcc_assert (dest_node);
360 create_ddg_dep_no_link (g, last_def_node, dest_node,
361 OUTPUT_DEP, REG_DEP, 1);
364 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
365 static void
366 build_inter_loop_deps (ddg_ptr g)
368 unsigned rd_num;
369 struct df_rd_bb_info *rd_bb_info;
370 bitmap_iterator bi;
372 rd_bb_info = DF_RD_BB_INFO (g->bb);
374 /* Find inter-loop register output, true and anti deps. */
375 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
377 df_ref rd = DF_DEFS_GET (rd_num);
379 add_cross_iteration_register_deps (g, rd);
384 /* Return true if two specified instructions have mem expr with conflict
385 alias sets. */
386 static bool
387 insns_may_alias_p (rtx_insn *insn1, rtx_insn *insn2)
389 subrtx_iterator::array_type array1;
390 subrtx_iterator::array_type array2;
391 FOR_EACH_SUBRTX (iter1, array1, PATTERN (insn1), NONCONST)
393 const_rtx x1 = *iter1;
394 if (MEM_P (x1))
395 FOR_EACH_SUBRTX (iter2, array2, PATTERN (insn2), NONCONST)
397 const_rtx x2 = *iter2;
398 if (MEM_P (x2) && may_alias_p (x2, x1))
399 return true;
402 return false;
405 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
406 to ddg G. */
407 static void
408 add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
411 if ((from->cuid == to->cuid)
412 || !insns_may_alias_p (from->insn, to->insn))
413 /* Do not create edge if memory references have disjoint alias sets
414 or 'to' and 'from' are the same instruction. */
415 return;
417 if (mem_write_insn_p (from->insn))
419 if (mem_read_insn_p (to->insn))
420 create_ddg_dep_no_link (g, from, to,
421 DEBUG_INSN_P (to->insn)
422 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
423 else
424 create_ddg_dep_no_link (g, from, to,
425 DEBUG_INSN_P (to->insn)
426 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
428 else if (!mem_read_insn_p (to->insn))
429 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
432 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
433 to ddg G. */
434 static void
435 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
437 if (!insns_may_alias_p (from->insn, to->insn))
438 /* Do not create edge if memory references have disjoint alias sets. */
439 return;
441 if (mem_write_insn_p (from->insn))
443 if (mem_read_insn_p (to->insn))
444 create_ddg_dep_no_link (g, from, to,
445 DEBUG_INSN_P (to->insn)
446 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
447 else if (from->cuid != to->cuid)
448 create_ddg_dep_no_link (g, from, to,
449 DEBUG_INSN_P (to->insn)
450 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
452 else
454 if (mem_read_insn_p (to->insn))
455 return;
456 else if (from->cuid != to->cuid)
458 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
459 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
460 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
461 else
462 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
468 /* Perform intra-block Data Dependency analysis and connect the nodes in
469 the DDG. We assume the loop has a single basic block. */
470 static void
471 build_intra_loop_deps (ddg_ptr g)
473 int i;
474 /* Hold the dependency analysis state during dependency calculations. */
475 struct deps_desc tmp_deps;
476 rtx_insn *head, *tail;
478 /* Build the dependence information, using the sched_analyze function. */
479 init_deps_global ();
480 init_deps (&tmp_deps, false);
482 /* Do the intra-block data dependence analysis for the given block. */
483 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
484 sched_analyze (&tmp_deps, head, tail);
486 /* Build intra-loop data dependencies using the scheduler dependency
487 analysis. */
488 for (i = 0; i < g->num_nodes; i++)
490 ddg_node_ptr dest_node = &g->nodes[i];
491 sd_iterator_def sd_it;
492 dep_t dep;
494 if (! INSN_P (dest_node->insn))
495 continue;
497 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
499 rtx_insn *src_insn = DEP_PRO (dep);
500 ddg_node_ptr src_node;
502 /* Don't add dependencies on debug insns to non-debug insns
503 to avoid codegen differences between -g and -g0. */
504 if (DEBUG_INSN_P (src_insn) && !DEBUG_INSN_P (dest_node->insn))
505 continue;
507 src_node = get_node_of_insn (g, src_insn);
509 if (!src_node)
510 continue;
512 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
515 /* If this insn modifies memory, add an edge to all insns that access
516 memory. */
517 if (mem_access_insn_p (dest_node->insn))
519 int j;
521 for (j = 0; j <= i; j++)
523 ddg_node_ptr j_node = &g->nodes[j];
524 if (DEBUG_INSN_P (j_node->insn))
525 continue;
526 if (mem_access_insn_p (j_node->insn))
528 /* Don't bother calculating inter-loop dep if an intra-loop dep
529 already exists. */
530 if (! bitmap_bit_p (dest_node->successors, j))
531 add_inter_loop_mem_dep (g, dest_node, j_node);
532 /* If -fmodulo-sched-allow-regmoves
533 is set certain anti-dep edges are not created.
534 It might be that these anti-dep edges are on the
535 path from one memory instruction to another such that
536 removing these edges could cause a violation of the
537 memory dependencies. Thus we add intra edges between
538 every two memory instructions in this case. */
539 if (flag_modulo_sched_allow_regmoves
540 && !bitmap_bit_p (dest_node->predecessors, j))
541 add_intra_loop_mem_dep (g, j_node, dest_node);
547 /* Free the INSN_LISTs. */
548 finish_deps_global ();
549 free_deps (&tmp_deps);
551 /* Free dependencies. */
552 sched_free_deps (head, tail, false);
556 /* Given a basic block, create its DDG and return a pointer to a variable
557 of ddg type that represents it.
558 Initialize the ddg structure fields to the appropriate values. */
559 ddg_ptr
560 create_ddg (basic_block bb, int closing_branch_deps)
562 ddg_ptr g;
563 rtx_insn *insn, *first_note;
564 int i;
565 int num_nodes = 0;
567 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
569 g->bb = bb;
570 g->closing_branch_deps = closing_branch_deps;
572 /* Count the number of insns in the BB. */
573 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
574 insn = NEXT_INSN (insn))
576 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
577 continue;
579 if (DEBUG_INSN_P (insn))
580 g->num_debug++;
581 else
583 if (mem_read_insn_p (insn))
584 g->num_loads++;
585 if (mem_write_insn_p (insn))
586 g->num_stores++;
588 num_nodes++;
591 /* There is nothing to do for this BB. */
592 if ((num_nodes - g->num_debug) <= 1)
594 free (g);
595 return NULL;
598 /* Allocate the nodes array, and initialize the nodes. */
599 g->num_nodes = num_nodes;
600 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
601 g->closing_branch = NULL;
602 i = 0;
603 first_note = NULL;
604 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
605 insn = NEXT_INSN (insn))
607 if (! INSN_P (insn))
609 if (! first_note && NOTE_P (insn)
610 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
611 first_note = insn;
612 continue;
614 if (JUMP_P (insn))
616 gcc_assert (!g->closing_branch);
617 g->closing_branch = &g->nodes[i];
619 else if (GET_CODE (PATTERN (insn)) == USE)
621 if (! first_note)
622 first_note = insn;
623 continue;
626 g->nodes[i].cuid = i;
627 g->nodes[i].successors = sbitmap_alloc (num_nodes);
628 bitmap_clear (g->nodes[i].successors);
629 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
630 bitmap_clear (g->nodes[i].predecessors);
631 g->nodes[i].first_note = (first_note ? first_note : insn);
632 g->nodes[i++].insn = insn;
633 first_note = NULL;
636 /* We must have found a branch in DDG. */
637 gcc_assert (g->closing_branch);
640 /* Build the data dependency graph. */
641 build_intra_loop_deps (g);
642 build_inter_loop_deps (g);
643 return g;
646 /* Free all the memory allocated for the DDG. */
647 void
648 free_ddg (ddg_ptr g)
650 int i;
652 if (!g)
653 return;
655 for (i = 0; i < g->num_nodes; i++)
657 ddg_edge_ptr e = g->nodes[i].out;
659 while (e)
661 ddg_edge_ptr next = e->next_out;
663 free (e);
664 e = next;
666 sbitmap_free (g->nodes[i].successors);
667 sbitmap_free (g->nodes[i].predecessors);
669 if (g->num_backarcs > 0)
670 free (g->backarcs);
671 free (g->nodes);
672 free (g);
675 void
676 print_ddg_edge (FILE *file, ddg_edge_ptr e)
678 char dep_c;
680 switch (e->type)
682 case OUTPUT_DEP :
683 dep_c = 'O';
684 break;
685 case ANTI_DEP :
686 dep_c = 'A';
687 break;
688 default:
689 dep_c = 'T';
692 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
693 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
696 /* Print the DDG nodes with there in/out edges to the dump file. */
697 void
698 print_ddg (FILE *file, ddg_ptr g)
700 int i;
702 for (i = 0; i < g->num_nodes; i++)
704 ddg_edge_ptr e;
706 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
707 print_rtl_single (file, g->nodes[i].insn);
708 fprintf (file, "OUT ARCS: ");
709 for (e = g->nodes[i].out; e; e = e->next_out)
710 print_ddg_edge (file, e);
712 fprintf (file, "\nIN ARCS: ");
713 for (e = g->nodes[i].in; e; e = e->next_in)
714 print_ddg_edge (file, e);
716 fprintf (file, "\n");
720 /* Print the given DDG in VCG format. */
721 DEBUG_FUNCTION void
722 vcg_print_ddg (FILE *file, ddg_ptr g)
724 int src_cuid;
726 fprintf (file, "graph: {\n");
727 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
729 ddg_edge_ptr e;
730 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
732 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
733 print_rtl_single (file, g->nodes[src_cuid].insn);
734 fprintf (file, "\"}\n");
735 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
737 int dst_uid = INSN_UID (e->dest->insn);
738 int dst_cuid = e->dest->cuid;
740 /* Give the backarcs a different color. */
741 if (e->distance > 0)
742 fprintf (file, "backedge: {color: red ");
743 else
744 fprintf (file, "edge: { ");
746 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
747 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
748 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
751 fprintf (file, "}\n");
754 /* Dump the sccs in SCCS. */
755 void
756 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
758 unsigned int u = 0;
759 sbitmap_iterator sbi;
760 int i;
762 if (!file)
763 return;
765 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
766 for (i = 0; i < sccs->num_sccs; i++)
768 fprintf (file, "SCC number: %d\n", i);
769 EXECUTE_IF_SET_IN_BITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
771 fprintf (file, "insn num %d\n", u);
772 print_rtl_single (file, g->nodes[u].insn);
775 fprintf (file, "\n");
778 /* Create an edge and initialize it with given values. */
779 static ddg_edge_ptr
780 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
781 dep_type t, dep_data_type dt, int l, int d)
783 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
785 e->src = src;
786 e->dest = dest;
787 e->type = t;
788 e->data_type = dt;
789 e->latency = l;
790 e->distance = d;
791 e->next_in = e->next_out = NULL;
792 e->aux.info = 0;
793 return e;
796 /* Add the given edge to the in/out linked lists of the DDG nodes. */
797 static void
798 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
800 ddg_node_ptr src = e->src;
801 ddg_node_ptr dest = e->dest;
803 /* Should have allocated the sbitmaps. */
804 gcc_assert (src->successors && dest->predecessors);
806 bitmap_set_bit (src->successors, dest->cuid);
807 bitmap_set_bit (dest->predecessors, src->cuid);
808 e->next_in = dest->in;
809 dest->in = e;
810 e->next_out = src->out;
811 src->out = e;
816 /* Algorithm for computing the recurrence_length of an scc. We assume at
817 for now that cycles in the data dependence graph contain a single backarc.
818 This simplifies the algorithm, and can be generalized later. */
819 static void
820 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
822 int j;
823 int result = -1;
825 for (j = 0; j < scc->num_backarcs; j++)
827 ddg_edge_ptr backarc = scc->backarcs[j];
828 int length;
829 int distance = backarc->distance;
830 ddg_node_ptr src = backarc->dest;
831 ddg_node_ptr dest = backarc->src;
833 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
834 if (length < 0 )
836 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
837 continue;
839 length += backarc->latency;
840 result = MAX (result, (length / distance));
842 scc->recurrence_length = result;
845 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
846 and mark edges that belong to this scc as IN_SCC. */
847 static ddg_scc_ptr
848 create_scc (ddg_ptr g, sbitmap nodes)
850 ddg_scc_ptr scc;
851 unsigned int u = 0;
852 sbitmap_iterator sbi;
854 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
855 scc->backarcs = NULL;
856 scc->num_backarcs = 0;
857 scc->nodes = sbitmap_alloc (g->num_nodes);
858 bitmap_copy (scc->nodes, nodes);
860 /* Mark the backarcs that belong to this SCC. */
861 EXECUTE_IF_SET_IN_BITMAP (nodes, 0, u, sbi)
863 ddg_edge_ptr e;
864 ddg_node_ptr n = &g->nodes[u];
866 for (e = n->out; e; e = e->next_out)
867 if (bitmap_bit_p (nodes, e->dest->cuid))
869 e->aux.count = IN_SCC;
870 if (e->distance > 0)
871 add_backarc_to_scc (scc, e);
875 set_recurrence_length (scc, g);
876 return scc;
879 /* Cleans the memory allocation of a given SCC. */
880 static void
881 free_scc (ddg_scc_ptr scc)
883 if (!scc)
884 return;
886 sbitmap_free (scc->nodes);
887 if (scc->num_backarcs > 0)
888 free (scc->backarcs);
889 free (scc);
893 /* Add a given edge known to be a backarc to the given DDG. */
894 static void
895 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
897 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
899 add_edge_to_ddg (g, e);
900 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
901 g->backarcs[g->num_backarcs++] = e;
904 /* Add backarc to an SCC. */
905 static void
906 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
908 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
910 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
911 scc->backarcs[scc->num_backarcs++] = e;
914 /* Add the given SCC to the DDG. */
915 static void
916 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
918 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
920 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
921 g->sccs[g->num_sccs++] = scc;
924 /* Given the instruction INSN return the node that represents it. */
925 ddg_node_ptr
926 get_node_of_insn (ddg_ptr g, rtx_insn *insn)
928 int i;
930 for (i = 0; i < g->num_nodes; i++)
931 if (insn == g->nodes[i].insn)
932 return &g->nodes[i];
933 return NULL;
936 /* Given a set OPS of nodes in the DDG, find the set of their successors
937 which are not in OPS, and set their bits in SUCC. Bits corresponding to
938 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
939 void
940 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
942 unsigned int i = 0;
943 sbitmap_iterator sbi;
945 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
947 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
948 bitmap_ior (succ, succ, node_succ);
951 /* We want those that are not in ops. */
952 bitmap_and_compl (succ, succ, ops);
955 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
956 which are not in OPS, and set their bits in PREDS. Bits corresponding to
957 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
958 void
959 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
961 unsigned int i = 0;
962 sbitmap_iterator sbi;
964 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
966 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
967 bitmap_ior (preds, preds, node_preds);
970 /* We want those that are not in ops. */
971 bitmap_and_compl (preds, preds, ops);
975 /* Compare function to be passed to qsort to order the backarcs in descending
976 recMII order. */
977 static int
978 compare_sccs (const void *s1, const void *s2)
980 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
981 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
982 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
986 /* Order the backarcs in descending recMII order using compare_sccs. */
987 static void
988 order_sccs (ddg_all_sccs_ptr g)
990 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
991 (int (*) (const void *, const void *)) compare_sccs);
994 /* Check that every node in SCCS belongs to exactly one strongly connected
995 component and that no element of SCCS is empty. */
996 static void
997 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
999 int i = 0;
1000 auto_sbitmap tmp (num_nodes);
1002 bitmap_clear (tmp);
1003 for (i = 0; i < sccs->num_sccs; i++)
1005 gcc_assert (!bitmap_empty_p (sccs->sccs[i]->nodes));
1006 /* Verify that every node in sccs is in exactly one strongly
1007 connected component. */
1008 gcc_assert (!bitmap_intersect_p (tmp, sccs->sccs[i]->nodes));
1009 bitmap_ior (tmp, tmp, sccs->sccs[i]->nodes);
1013 /* Perform the Strongly Connected Components decomposing algorithm on the
1014 DDG and return DDG_ALL_SCCS structure that contains them. */
1015 ddg_all_sccs_ptr
1016 create_ddg_all_sccs (ddg_ptr g)
1018 int i;
1019 int num_nodes = g->num_nodes;
1020 auto_sbitmap from (num_nodes);
1021 auto_sbitmap to (num_nodes);
1022 auto_sbitmap scc_nodes (num_nodes);
1023 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
1024 xmalloc (sizeof (struct ddg_all_sccs));
1026 sccs->ddg = g;
1027 sccs->sccs = NULL;
1028 sccs->num_sccs = 0;
1030 for (i = 0; i < g->num_backarcs; i++)
1032 ddg_scc_ptr scc;
1033 ddg_edge_ptr backarc = g->backarcs[i];
1034 ddg_node_ptr src = backarc->src;
1035 ddg_node_ptr dest = backarc->dest;
1037 /* If the backarc already belongs to an SCC, continue. */
1038 if (backarc->aux.count == IN_SCC)
1039 continue;
1041 bitmap_clear (scc_nodes);
1042 bitmap_clear (from);
1043 bitmap_clear (to);
1044 bitmap_set_bit (from, dest->cuid);
1045 bitmap_set_bit (to, src->cuid);
1047 if (find_nodes_on_paths (scc_nodes, g, from, to))
1049 scc = create_scc (g, scc_nodes);
1050 add_scc_to_ddg (sccs, scc);
1053 order_sccs (sccs);
1055 if (flag_checking)
1056 check_sccs (sccs, num_nodes);
1058 return sccs;
1061 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1062 void
1063 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1065 int i;
1067 if (!all_sccs)
1068 return;
1070 for (i = 0; i < all_sccs->num_sccs; i++)
1071 free_scc (all_sccs->sccs[i]);
1073 free (all_sccs->sccs);
1074 free (all_sccs);
1078 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1079 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1080 nodes from FROM and TO). Return nonzero if nodes exist. */
1082 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1084 int change;
1085 unsigned int u = 0;
1086 int num_nodes = g->num_nodes;
1087 sbitmap_iterator sbi;
1089 auto_sbitmap workset (num_nodes);
1090 auto_sbitmap reachable_from (num_nodes);
1091 auto_sbitmap reach_to (num_nodes);
1092 auto_sbitmap tmp (num_nodes);
1094 bitmap_copy (reachable_from, from);
1095 bitmap_copy (tmp, from);
1097 change = 1;
1098 while (change)
1100 change = 0;
1101 bitmap_copy (workset, tmp);
1102 bitmap_clear (tmp);
1103 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1105 ddg_edge_ptr e;
1106 ddg_node_ptr u_node = &g->nodes[u];
1108 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1110 ddg_node_ptr v_node = e->dest;
1111 int v = v_node->cuid;
1113 if (!bitmap_bit_p (reachable_from, v))
1115 bitmap_set_bit (reachable_from, v);
1116 bitmap_set_bit (tmp, v);
1117 change = 1;
1123 bitmap_copy (reach_to, to);
1124 bitmap_copy (tmp, to);
1126 change = 1;
1127 while (change)
1129 change = 0;
1130 bitmap_copy (workset, tmp);
1131 bitmap_clear (tmp);
1132 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1134 ddg_edge_ptr e;
1135 ddg_node_ptr u_node = &g->nodes[u];
1137 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1139 ddg_node_ptr v_node = e->src;
1140 int v = v_node->cuid;
1142 if (!bitmap_bit_p (reach_to, v))
1144 bitmap_set_bit (reach_to, v);
1145 bitmap_set_bit (tmp, v);
1146 change = 1;
1152 return bitmap_and (result, reachable_from, reach_to);
1156 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1157 at-least as large as the count of U_NODE plus the latency between them.
1158 Sets a bit in TMP for each successor whose count was changed (increased).
1159 Returns nonzero if any count was changed. */
1160 static int
1161 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1163 ddg_edge_ptr e;
1164 int result = 0;
1166 for (e = u_node->out; e; e = e->next_out)
1168 ddg_node_ptr v_node = e->dest;
1169 int v = v_node->cuid;
1171 if (bitmap_bit_p (nodes, v)
1172 && (e->distance == 0)
1173 && (v_node->aux.count < u_node->aux.count + e->latency))
1175 v_node->aux.count = u_node->aux.count + e->latency;
1176 bitmap_set_bit (tmp, v);
1177 result = 1;
1180 return result;
1184 /* Find the length of a longest path from SRC to DEST in G,
1185 going only through NODES, and disregarding backarcs. */
1187 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1189 int i;
1190 unsigned int u = 0;
1191 int change = 1;
1192 int num_nodes = g->num_nodes;
1193 auto_sbitmap workset (num_nodes);
1194 auto_sbitmap tmp (num_nodes);
1197 /* Data will hold the distance of the longest path found so far from
1198 src to each node. Initialize to -1 = less than minimum. */
1199 for (i = 0; i < g->num_nodes; i++)
1200 g->nodes[i].aux.count = -1;
1201 g->nodes[src].aux.count = 0;
1203 bitmap_clear (tmp);
1204 bitmap_set_bit (tmp, src);
1206 while (change)
1208 sbitmap_iterator sbi;
1210 change = 0;
1211 bitmap_copy (workset, tmp);
1212 bitmap_clear (tmp);
1213 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1215 ddg_node_ptr u_node = &g->nodes[u];
1217 change |= update_dist_to_successors (u_node, nodes, tmp);
1220 return g->nodes[dest].aux.count;
1223 #endif /* INSN_SCHEDULING */