2013-10-30 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / ddg.c
blob0d9089fd470b726aa05bb853db2eca43eb290bed
1 /* DDG - Data Dependence Graph implementation.
2 Copyright (C) 2004-2013 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 "tm.h"
26 #include "diagnostic-core.h"
27 #include "rtl.h"
28 #include "tm_p.h"
29 #include "hard-reg-set.h"
30 #include "regs.h"
31 #include "function.h"
32 #include "flags.h"
33 #include "insn-config.h"
34 #include "insn-attr.h"
35 #include "except.h"
36 #include "recog.h"
37 #include "sched-int.h"
38 #include "target.h"
39 #include "cfgloop.h"
40 #include "sbitmap.h"
41 #include "expr.h"
42 #include "bitmap.h"
43 #include "ddg.h"
45 #ifdef INSN_SCHEDULING
47 /* A flag indicating that a ddg edge belongs to an SCC or not. */
48 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
50 /* Forward declarations. */
51 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
52 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
53 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
54 static void create_ddg_dep_from_intra_loop_link (ddg_ptr, ddg_node_ptr,
55 ddg_node_ptr, dep_t);
56 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
57 dep_type, dep_data_type, int);
58 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
59 dep_data_type, int, int);
60 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
62 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
63 static bool mem_ref_p;
65 /* Auxiliary function for mem_read_insn_p. */
66 static int
67 mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
69 if (MEM_P (*x))
70 mem_ref_p = true;
71 return 0;
74 /* Auxiliary function for mem_read_insn_p. */
75 static void
76 mark_mem_use_1 (rtx *x, void *data)
78 for_each_rtx (x, mark_mem_use, data);
81 /* Returns nonzero if INSN reads from memory. */
82 static bool
83 mem_read_insn_p (rtx insn)
85 mem_ref_p = false;
86 note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
87 return mem_ref_p;
90 static void
91 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
93 if (MEM_P (loc))
94 mem_ref_p = true;
97 /* Returns nonzero if INSN writes to memory. */
98 static bool
99 mem_write_insn_p (rtx insn)
101 mem_ref_p = false;
102 note_stores (PATTERN (insn), mark_mem_store, NULL);
103 return mem_ref_p;
106 /* Returns nonzero if X has access to memory. */
107 static bool
108 rtx_mem_access_p (rtx x)
110 int i, j;
111 const char *fmt;
112 enum rtx_code code;
114 if (x == 0)
115 return false;
117 if (MEM_P (x))
118 return true;
120 code = GET_CODE (x);
121 fmt = GET_RTX_FORMAT (code);
122 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
124 if (fmt[i] == 'e')
126 if (rtx_mem_access_p (XEXP (x, i)))
127 return true;
129 else if (fmt[i] == 'E')
130 for (j = 0; j < XVECLEN (x, i); j++)
132 if (rtx_mem_access_p (XVECEXP (x, i, j)))
133 return true;
136 return false;
139 /* Returns nonzero if INSN reads to or writes from memory. */
140 static bool
141 mem_access_insn_p (rtx insn)
143 return rtx_mem_access_p (PATTERN (insn));
146 /* Return true if DEF_INSN contains address being auto-inc or auto-dec
147 which is used in USE_INSN. Otherwise return false. The result is
148 being used to decide whether to remove the edge between def_insn and
149 use_insn when -fmodulo-sched-allow-regmoves is set. This function
150 doesn't need to consider the specific address register; no reg_moves
151 will be allowed for any life range defined by def_insn and used
152 by use_insn, if use_insn uses an address register auto-inc'ed by
153 def_insn. */
154 bool
155 autoinc_var_is_used_p (rtx def_insn, rtx use_insn)
157 rtx note;
159 for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
160 if (REG_NOTE_KIND (note) == REG_INC
161 && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
162 return true;
164 return false;
167 /* Return true if one of the definitions in INSN has MODE_CC. Otherwise
168 return false. */
169 static bool
170 def_has_ccmode_p (rtx insn)
172 df_ref *def;
174 for (def = DF_INSN_DEFS (insn); *def; def++)
176 enum machine_mode mode = GET_MODE (DF_REF_REG (*def));
178 if (GET_MODE_CLASS (mode) == MODE_CC)
179 return true;
182 return false;
185 /* Computes the dependence parameters (latency, distance etc.), creates
186 a ddg_edge and adds it to the given DDG. */
187 static void
188 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
189 ddg_node_ptr dest_node, dep_t link)
191 ddg_edge_ptr e;
192 int latency, distance = 0;
193 dep_type t = TRUE_DEP;
194 dep_data_type dt = (mem_access_insn_p (src_node->insn)
195 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
196 : REG_DEP);
197 gcc_assert (src_node->cuid < dest_node->cuid);
198 gcc_assert (link);
200 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
201 if (DEP_TYPE (link) == REG_DEP_ANTI)
202 t = ANTI_DEP;
203 else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
204 t = OUTPUT_DEP;
206 gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
207 gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
209 /* We currently choose not to create certain anti-deps edges and
210 compensate for that by generating reg-moves based on the life-range
211 analysis. The anti-deps that will be deleted are the ones which
212 have true-deps edges in the opposite direction (in other words
213 the kernel has only one def of the relevant register).
214 If the address that is being auto-inc or auto-dec in DEST_NODE
215 is used in SRC_NODE then do not remove the edge to make sure
216 reg-moves will not be created for this address.
217 TODO: support the removal of all anti-deps edges, i.e. including those
218 whose register has multiple defs in the loop. */
219 if (flag_modulo_sched_allow_regmoves
220 && (t == ANTI_DEP && dt == REG_DEP)
221 && !def_has_ccmode_p (dest_node->insn)
222 && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
224 rtx set;
226 set = single_set (dest_node->insn);
227 /* TODO: Handle registers that REG_P is not true for them, i.e.
228 subregs and special registers. */
229 if (set && REG_P (SET_DEST (set)))
231 int regno = REGNO (SET_DEST (set));
232 df_ref first_def;
233 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
235 first_def = df_bb_regno_first_def_find (g->bb, regno);
236 gcc_assert (first_def);
238 if (bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)))
239 return;
243 latency = dep_cost (link);
244 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
245 add_edge_to_ddg (g, e);
248 /* The same as the above function, but it doesn't require a link parameter. */
249 static void
250 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
251 dep_type d_t, dep_data_type d_dt, int distance)
253 ddg_edge_ptr e;
254 int l;
255 enum reg_note dep_kind;
256 struct _dep _dep, *dep = &_dep;
258 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
259 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
261 if (d_t == ANTI_DEP)
262 dep_kind = REG_DEP_ANTI;
263 else if (d_t == OUTPUT_DEP)
264 dep_kind = REG_DEP_OUTPUT;
265 else
267 gcc_assert (d_t == TRUE_DEP);
269 dep_kind = REG_DEP_TRUE;
272 init_dep (dep, from->insn, to->insn, dep_kind);
274 l = dep_cost (dep);
276 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
277 if (distance > 0)
278 add_backarc_to_ddg (g, e);
279 else
280 add_edge_to_ddg (g, e);
284 /* Given a downwards exposed register def LAST_DEF (which is the last
285 definition of that register in the bb), add inter-loop true dependences
286 to all its uses in the next iteration, an output dependence to the
287 first def of the same register (possibly itself) in the next iteration
288 and anti-dependences from its uses in the current iteration to the
289 first definition in the next iteration. */
290 static void
291 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
293 int regno = DF_REF_REGNO (last_def);
294 struct df_link *r_use;
295 int has_use_in_bb_p = false;
296 rtx def_insn = DF_REF_INSN (last_def);
297 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
298 ddg_node_ptr use_node;
299 #ifdef ENABLE_CHECKING
300 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
301 #endif
302 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
304 gcc_assert (last_def_node);
305 gcc_assert (first_def);
307 #ifdef ENABLE_CHECKING
308 if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
309 gcc_assert (!bitmap_bit_p (&bb_info->gen,
310 DF_REF_ID (first_def)));
311 #endif
313 /* Create inter-loop true dependences and anti dependences. */
314 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
316 rtx use_insn = DF_REF_INSN (r_use->ref);
318 if (BLOCK_FOR_INSN (use_insn) != g->bb)
319 continue;
321 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
322 use_node = get_node_of_insn (g, use_insn);
323 gcc_assert (use_node);
324 has_use_in_bb_p = true;
325 if (use_node->cuid <= last_def_node->cuid)
327 /* Add true deps from last_def to it's uses in the next
328 iteration. Any such upwards exposed use appears before
329 the last_def def. */
330 create_ddg_dep_no_link (g, last_def_node, use_node,
331 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
332 REG_DEP, 1);
334 else if (!DEBUG_INSN_P (use_insn))
336 /* Add anti deps from last_def's uses in the current iteration
337 to the first def in the next iteration. We do not add ANTI
338 dep when there is an intra-loop TRUE dep in the opposite
339 direction, but use regmoves to fix such disregarded ANTI
340 deps when broken. If the first_def reaches the USE then
341 there is such a dep. */
342 ddg_node_ptr first_def_node = get_node_of_insn (g,
343 DF_REF_INSN (first_def));
345 gcc_assert (first_def_node);
347 /* Always create the edge if the use node is a branch in
348 order to prevent the creation of reg-moves.
349 If the address that is being auto-inc or auto-dec in LAST_DEF
350 is used in USE_INSN then do not remove the edge to make sure
351 reg-moves will not be created for that address. */
352 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
353 || !flag_modulo_sched_allow_regmoves
354 || JUMP_P (use_node->insn)
355 || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
356 || def_has_ccmode_p (DF_REF_INSN (last_def)))
357 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
358 REG_DEP, 1);
362 /* Create an inter-loop output dependence between LAST_DEF (which is the
363 last def in its block, being downwards exposed) and the first def in
364 its block. Avoid creating a self output dependence. Avoid creating
365 an output dependence if there is a dependence path between the two
366 defs starting with a true dependence to a use which can be in the
367 next iteration; followed by an anti dependence of that use to the
368 first def (i.e. if there is a use between the two defs.) */
369 if (!has_use_in_bb_p)
371 ddg_node_ptr dest_node;
373 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
374 return;
376 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
377 gcc_assert (dest_node);
378 create_ddg_dep_no_link (g, last_def_node, dest_node,
379 OUTPUT_DEP, REG_DEP, 1);
382 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
383 static void
384 build_inter_loop_deps (ddg_ptr g)
386 unsigned rd_num;
387 struct df_rd_bb_info *rd_bb_info;
388 bitmap_iterator bi;
390 rd_bb_info = DF_RD_BB_INFO (g->bb);
392 /* Find inter-loop register output, true and anti deps. */
393 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
395 df_ref rd = DF_DEFS_GET (rd_num);
397 add_cross_iteration_register_deps (g, rd);
402 static int
403 walk_mems_2 (rtx *x, rtx mem)
405 if (MEM_P (*x))
407 if (may_alias_p (*x, mem))
408 return 1;
410 return -1;
412 return 0;
415 static int
416 walk_mems_1 (rtx *x, rtx *pat)
418 if (MEM_P (*x))
420 /* Visit all MEMs in *PAT and check independence. */
421 if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x))
422 /* Indicate that dependence was determined and stop traversal. */
423 return 1;
425 return -1;
427 return 0;
430 /* Return 1 if two specified instructions have mem expr with conflict alias sets*/
431 static int
432 insns_may_alias_p (rtx insn1, rtx insn2)
434 /* For each pair of MEMs in INSN1 and INSN2 check their independence. */
435 return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1,
436 &PATTERN (insn2));
439 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
440 to ddg G. */
441 static void
442 add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
445 if ((from->cuid == to->cuid)
446 || !insns_may_alias_p (from->insn, to->insn))
447 /* Do not create edge if memory references have disjoint alias sets
448 or 'to' and 'from' are the same instruction. */
449 return;
451 if (mem_write_insn_p (from->insn))
453 if (mem_read_insn_p (to->insn))
454 create_ddg_dep_no_link (g, from, to,
455 DEBUG_INSN_P (to->insn)
456 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
457 else
458 create_ddg_dep_no_link (g, from, to,
459 DEBUG_INSN_P (to->insn)
460 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
462 else if (!mem_read_insn_p (to->insn))
463 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
466 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
467 to ddg G. */
468 static void
469 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
471 if (!insns_may_alias_p (from->insn, to->insn))
472 /* Do not create edge if memory references have disjoint alias sets. */
473 return;
475 if (mem_write_insn_p (from->insn))
477 if (mem_read_insn_p (to->insn))
478 create_ddg_dep_no_link (g, from, to,
479 DEBUG_INSN_P (to->insn)
480 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
481 else if (from->cuid != to->cuid)
482 create_ddg_dep_no_link (g, from, to,
483 DEBUG_INSN_P (to->insn)
484 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
486 else
488 if (mem_read_insn_p (to->insn))
489 return;
490 else if (from->cuid != to->cuid)
492 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
493 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
494 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
495 else
496 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
502 /* Perform intra-block Data Dependency analysis and connect the nodes in
503 the DDG. We assume the loop has a single basic block. */
504 static void
505 build_intra_loop_deps (ddg_ptr g)
507 int i;
508 /* Hold the dependency analysis state during dependency calculations. */
509 struct deps_desc tmp_deps;
510 rtx head, tail;
512 /* Build the dependence information, using the sched_analyze function. */
513 init_deps_global ();
514 init_deps (&tmp_deps, false);
516 /* Do the intra-block data dependence analysis for the given block. */
517 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
518 sched_analyze (&tmp_deps, head, tail);
520 /* Build intra-loop data dependencies using the scheduler dependency
521 analysis. */
522 for (i = 0; i < g->num_nodes; i++)
524 ddg_node_ptr dest_node = &g->nodes[i];
525 sd_iterator_def sd_it;
526 dep_t dep;
528 if (! INSN_P (dest_node->insn))
529 continue;
531 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
533 rtx src_insn = DEP_PRO (dep);
534 ddg_node_ptr src_node;
536 /* Don't add dependencies on debug insns to non-debug insns
537 to avoid codegen differences between -g and -g0. */
538 if (DEBUG_INSN_P (src_insn) && !DEBUG_INSN_P (dest_node->insn))
539 continue;
541 src_node = get_node_of_insn (g, src_insn);
543 if (!src_node)
544 continue;
546 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
549 /* If this insn modifies memory, add an edge to all insns that access
550 memory. */
551 if (mem_access_insn_p (dest_node->insn))
553 int j;
555 for (j = 0; j <= i; j++)
557 ddg_node_ptr j_node = &g->nodes[j];
558 if (DEBUG_INSN_P (j_node->insn))
559 continue;
560 if (mem_access_insn_p (j_node->insn))
562 /* Don't bother calculating inter-loop dep if an intra-loop dep
563 already exists. */
564 if (! bitmap_bit_p (dest_node->successors, j))
565 add_inter_loop_mem_dep (g, dest_node, j_node);
566 /* If -fmodulo-sched-allow-regmoves
567 is set certain anti-dep edges are not created.
568 It might be that these anti-dep edges are on the
569 path from one memory instruction to another such that
570 removing these edges could cause a violation of the
571 memory dependencies. Thus we add intra edges between
572 every two memory instructions in this case. */
573 if (flag_modulo_sched_allow_regmoves
574 && !bitmap_bit_p (dest_node->predecessors, j))
575 add_intra_loop_mem_dep (g, j_node, dest_node);
581 /* Free the INSN_LISTs. */
582 finish_deps_global ();
583 free_deps (&tmp_deps);
585 /* Free dependencies. */
586 sched_free_deps (head, tail, false);
590 /* Given a basic block, create its DDG and return a pointer to a variable
591 of ddg type that represents it.
592 Initialize the ddg structure fields to the appropriate values. */
593 ddg_ptr
594 create_ddg (basic_block bb, int closing_branch_deps)
596 ddg_ptr g;
597 rtx insn, first_note;
598 int i;
599 int num_nodes = 0;
601 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
603 g->bb = bb;
604 g->closing_branch_deps = closing_branch_deps;
606 /* Count the number of insns in the BB. */
607 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
608 insn = NEXT_INSN (insn))
610 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
611 continue;
613 if (DEBUG_INSN_P (insn))
614 g->num_debug++;
615 else
617 if (mem_read_insn_p (insn))
618 g->num_loads++;
619 if (mem_write_insn_p (insn))
620 g->num_stores++;
622 num_nodes++;
625 /* There is nothing to do for this BB. */
626 if ((num_nodes - g->num_debug) <= 1)
628 free (g);
629 return NULL;
632 /* Allocate the nodes array, and initialize the nodes. */
633 g->num_nodes = num_nodes;
634 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
635 g->closing_branch = NULL;
636 i = 0;
637 first_note = NULL_RTX;
638 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
639 insn = NEXT_INSN (insn))
641 if (! INSN_P (insn))
643 if (! first_note && NOTE_P (insn)
644 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
645 first_note = insn;
646 continue;
648 if (JUMP_P (insn))
650 gcc_assert (!g->closing_branch);
651 g->closing_branch = &g->nodes[i];
653 else if (GET_CODE (PATTERN (insn)) == USE)
655 if (! first_note)
656 first_note = insn;
657 continue;
660 g->nodes[i].cuid = i;
661 g->nodes[i].successors = sbitmap_alloc (num_nodes);
662 bitmap_clear (g->nodes[i].successors);
663 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
664 bitmap_clear (g->nodes[i].predecessors);
665 g->nodes[i].first_note = (first_note ? first_note : insn);
666 g->nodes[i++].insn = insn;
667 first_note = NULL_RTX;
670 /* We must have found a branch in DDG. */
671 gcc_assert (g->closing_branch);
674 /* Build the data dependency graph. */
675 build_intra_loop_deps (g);
676 build_inter_loop_deps (g);
677 return g;
680 /* Free all the memory allocated for the DDG. */
681 void
682 free_ddg (ddg_ptr g)
684 int i;
686 if (!g)
687 return;
689 for (i = 0; i < g->num_nodes; i++)
691 ddg_edge_ptr e = g->nodes[i].out;
693 while (e)
695 ddg_edge_ptr next = e->next_out;
697 free (e);
698 e = next;
700 sbitmap_free (g->nodes[i].successors);
701 sbitmap_free (g->nodes[i].predecessors);
703 if (g->num_backarcs > 0)
704 free (g->backarcs);
705 free (g->nodes);
706 free (g);
709 void
710 print_ddg_edge (FILE *file, ddg_edge_ptr e)
712 char dep_c;
714 switch (e->type)
716 case OUTPUT_DEP :
717 dep_c = 'O';
718 break;
719 case ANTI_DEP :
720 dep_c = 'A';
721 break;
722 default:
723 dep_c = 'T';
726 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
727 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
730 /* Print the DDG nodes with there in/out edges to the dump file. */
731 void
732 print_ddg (FILE *file, ddg_ptr g)
734 int i;
736 for (i = 0; i < g->num_nodes; i++)
738 ddg_edge_ptr e;
740 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
741 print_rtl_single (file, g->nodes[i].insn);
742 fprintf (file, "OUT ARCS: ");
743 for (e = g->nodes[i].out; e; e = e->next_out)
744 print_ddg_edge (file, e);
746 fprintf (file, "\nIN ARCS: ");
747 for (e = g->nodes[i].in; e; e = e->next_in)
748 print_ddg_edge (file, e);
750 fprintf (file, "\n");
754 /* Print the given DDG in VCG format. */
755 DEBUG_FUNCTION void
756 vcg_print_ddg (FILE *file, ddg_ptr g)
758 int src_cuid;
760 fprintf (file, "graph: {\n");
761 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
763 ddg_edge_ptr e;
764 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
766 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
767 print_rtl_single (file, g->nodes[src_cuid].insn);
768 fprintf (file, "\"}\n");
769 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
771 int dst_uid = INSN_UID (e->dest->insn);
772 int dst_cuid = e->dest->cuid;
774 /* Give the backarcs a different color. */
775 if (e->distance > 0)
776 fprintf (file, "backedge: {color: red ");
777 else
778 fprintf (file, "edge: { ");
780 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
781 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
782 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
785 fprintf (file, "}\n");
788 /* Dump the sccs in SCCS. */
789 void
790 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
792 unsigned int u = 0;
793 sbitmap_iterator sbi;
794 int i;
796 if (!file)
797 return;
799 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
800 for (i = 0; i < sccs->num_sccs; i++)
802 fprintf (file, "SCC number: %d\n", i);
803 EXECUTE_IF_SET_IN_BITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
805 fprintf (file, "insn num %d\n", u);
806 print_rtl_single (file, g->nodes[u].insn);
809 fprintf (file, "\n");
812 /* Create an edge and initialize it with given values. */
813 static ddg_edge_ptr
814 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
815 dep_type t, dep_data_type dt, int l, int d)
817 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
819 e->src = src;
820 e->dest = dest;
821 e->type = t;
822 e->data_type = dt;
823 e->latency = l;
824 e->distance = d;
825 e->next_in = e->next_out = NULL;
826 e->aux.info = 0;
827 return e;
830 /* Add the given edge to the in/out linked lists of the DDG nodes. */
831 static void
832 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
834 ddg_node_ptr src = e->src;
835 ddg_node_ptr dest = e->dest;
837 /* Should have allocated the sbitmaps. */
838 gcc_assert (src->successors && dest->predecessors);
840 bitmap_set_bit (src->successors, dest->cuid);
841 bitmap_set_bit (dest->predecessors, src->cuid);
842 e->next_in = dest->in;
843 dest->in = e;
844 e->next_out = src->out;
845 src->out = e;
850 /* Algorithm for computing the recurrence_length of an scc. We assume at
851 for now that cycles in the data dependence graph contain a single backarc.
852 This simplifies the algorithm, and can be generalized later. */
853 static void
854 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
856 int j;
857 int result = -1;
859 for (j = 0; j < scc->num_backarcs; j++)
861 ddg_edge_ptr backarc = scc->backarcs[j];
862 int length;
863 int distance = backarc->distance;
864 ddg_node_ptr src = backarc->dest;
865 ddg_node_ptr dest = backarc->src;
867 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
868 if (length < 0 )
870 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
871 continue;
873 length += backarc->latency;
874 result = MAX (result, (length / distance));
876 scc->recurrence_length = result;
879 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
880 and mark edges that belong to this scc as IN_SCC. */
881 static ddg_scc_ptr
882 create_scc (ddg_ptr g, sbitmap nodes)
884 ddg_scc_ptr scc;
885 unsigned int u = 0;
886 sbitmap_iterator sbi;
888 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
889 scc->backarcs = NULL;
890 scc->num_backarcs = 0;
891 scc->nodes = sbitmap_alloc (g->num_nodes);
892 bitmap_copy (scc->nodes, nodes);
894 /* Mark the backarcs that belong to this SCC. */
895 EXECUTE_IF_SET_IN_BITMAP (nodes, 0, u, sbi)
897 ddg_edge_ptr e;
898 ddg_node_ptr n = &g->nodes[u];
900 for (e = n->out; e; e = e->next_out)
901 if (bitmap_bit_p (nodes, e->dest->cuid))
903 e->aux.count = IN_SCC;
904 if (e->distance > 0)
905 add_backarc_to_scc (scc, e);
909 set_recurrence_length (scc, g);
910 return scc;
913 /* Cleans the memory allocation of a given SCC. */
914 static void
915 free_scc (ddg_scc_ptr scc)
917 if (!scc)
918 return;
920 sbitmap_free (scc->nodes);
921 if (scc->num_backarcs > 0)
922 free (scc->backarcs);
923 free (scc);
927 /* Add a given edge known to be a backarc to the given DDG. */
928 static void
929 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
931 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
933 add_edge_to_ddg (g, e);
934 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
935 g->backarcs[g->num_backarcs++] = e;
938 /* Add backarc to an SCC. */
939 static void
940 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
942 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
944 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
945 scc->backarcs[scc->num_backarcs++] = e;
948 /* Add the given SCC to the DDG. */
949 static void
950 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
952 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
954 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
955 g->sccs[g->num_sccs++] = scc;
958 /* Given the instruction INSN return the node that represents it. */
959 ddg_node_ptr
960 get_node_of_insn (ddg_ptr g, rtx insn)
962 int i;
964 for (i = 0; i < g->num_nodes; i++)
965 if (insn == g->nodes[i].insn)
966 return &g->nodes[i];
967 return NULL;
970 /* Given a set OPS of nodes in the DDG, find the set of their successors
971 which are not in OPS, and set their bits in SUCC. Bits corresponding to
972 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
973 void
974 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
976 unsigned int i = 0;
977 sbitmap_iterator sbi;
979 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
981 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
982 bitmap_ior (succ, succ, node_succ);
985 /* We want those that are not in ops. */
986 bitmap_and_compl (succ, succ, ops);
989 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
990 which are not in OPS, and set their bits in PREDS. Bits corresponding to
991 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
992 void
993 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
995 unsigned int i = 0;
996 sbitmap_iterator sbi;
998 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
1000 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
1001 bitmap_ior (preds, preds, node_preds);
1004 /* We want those that are not in ops. */
1005 bitmap_and_compl (preds, preds, ops);
1009 /* Compare function to be passed to qsort to order the backarcs in descending
1010 recMII order. */
1011 static int
1012 compare_sccs (const void *s1, const void *s2)
1014 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
1015 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
1016 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
1020 /* Order the backarcs in descending recMII order using compare_sccs. */
1021 static void
1022 order_sccs (ddg_all_sccs_ptr g)
1024 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
1025 (int (*) (const void *, const void *)) compare_sccs);
1028 #ifdef ENABLE_CHECKING
1029 /* Check that every node in SCCS belongs to exactly one strongly connected
1030 component and that no element of SCCS is empty. */
1031 static void
1032 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
1034 int i = 0;
1035 sbitmap tmp = sbitmap_alloc (num_nodes);
1037 bitmap_clear (tmp);
1038 for (i = 0; i < sccs->num_sccs; i++)
1040 gcc_assert (!bitmap_empty_p (sccs->sccs[i]->nodes));
1041 /* Verify that every node in sccs is in exactly one strongly
1042 connected component. */
1043 gcc_assert (!bitmap_intersect_p (tmp, sccs->sccs[i]->nodes));
1044 bitmap_ior (tmp, tmp, sccs->sccs[i]->nodes);
1046 sbitmap_free (tmp);
1048 #endif
1050 /* Perform the Strongly Connected Components decomposing algorithm on the
1051 DDG and return DDG_ALL_SCCS structure that contains them. */
1052 ddg_all_sccs_ptr
1053 create_ddg_all_sccs (ddg_ptr g)
1055 int i;
1056 int num_nodes = g->num_nodes;
1057 sbitmap from = sbitmap_alloc (num_nodes);
1058 sbitmap to = sbitmap_alloc (num_nodes);
1059 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
1060 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
1061 xmalloc (sizeof (struct ddg_all_sccs));
1063 sccs->ddg = g;
1064 sccs->sccs = NULL;
1065 sccs->num_sccs = 0;
1067 for (i = 0; i < g->num_backarcs; i++)
1069 ddg_scc_ptr scc;
1070 ddg_edge_ptr backarc = g->backarcs[i];
1071 ddg_node_ptr src = backarc->src;
1072 ddg_node_ptr dest = backarc->dest;
1074 /* If the backarc already belongs to an SCC, continue. */
1075 if (backarc->aux.count == IN_SCC)
1076 continue;
1078 bitmap_clear (scc_nodes);
1079 bitmap_clear (from);
1080 bitmap_clear (to);
1081 bitmap_set_bit (from, dest->cuid);
1082 bitmap_set_bit (to, src->cuid);
1084 if (find_nodes_on_paths (scc_nodes, g, from, to))
1086 scc = create_scc (g, scc_nodes);
1087 add_scc_to_ddg (sccs, scc);
1090 order_sccs (sccs);
1091 sbitmap_free (from);
1092 sbitmap_free (to);
1093 sbitmap_free (scc_nodes);
1094 #ifdef ENABLE_CHECKING
1095 check_sccs (sccs, num_nodes);
1096 #endif
1097 return sccs;
1100 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1101 void
1102 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1104 int i;
1106 if (!all_sccs)
1107 return;
1109 for (i = 0; i < all_sccs->num_sccs; i++)
1110 free_scc (all_sccs->sccs[i]);
1112 free (all_sccs->sccs);
1113 free (all_sccs);
1117 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1118 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1119 nodes from FROM and TO). Return nonzero if nodes exist. */
1121 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1123 int answer;
1124 int change;
1125 unsigned int u = 0;
1126 int num_nodes = g->num_nodes;
1127 sbitmap_iterator sbi;
1129 sbitmap workset = sbitmap_alloc (num_nodes);
1130 sbitmap reachable_from = sbitmap_alloc (num_nodes);
1131 sbitmap reach_to = sbitmap_alloc (num_nodes);
1132 sbitmap tmp = sbitmap_alloc (num_nodes);
1134 bitmap_copy (reachable_from, from);
1135 bitmap_copy (tmp, from);
1137 change = 1;
1138 while (change)
1140 change = 0;
1141 bitmap_copy (workset, tmp);
1142 bitmap_clear (tmp);
1143 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1145 ddg_edge_ptr e;
1146 ddg_node_ptr u_node = &g->nodes[u];
1148 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1150 ddg_node_ptr v_node = e->dest;
1151 int v = v_node->cuid;
1153 if (!bitmap_bit_p (reachable_from, v))
1155 bitmap_set_bit (reachable_from, v);
1156 bitmap_set_bit (tmp, v);
1157 change = 1;
1163 bitmap_copy (reach_to, to);
1164 bitmap_copy (tmp, to);
1166 change = 1;
1167 while (change)
1169 change = 0;
1170 bitmap_copy (workset, tmp);
1171 bitmap_clear (tmp);
1172 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1174 ddg_edge_ptr e;
1175 ddg_node_ptr u_node = &g->nodes[u];
1177 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1179 ddg_node_ptr v_node = e->src;
1180 int v = v_node->cuid;
1182 if (!bitmap_bit_p (reach_to, v))
1184 bitmap_set_bit (reach_to, v);
1185 bitmap_set_bit (tmp, v);
1186 change = 1;
1192 answer = bitmap_and (result, reachable_from, reach_to);
1193 sbitmap_free (workset);
1194 sbitmap_free (reachable_from);
1195 sbitmap_free (reach_to);
1196 sbitmap_free (tmp);
1197 return answer;
1201 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1202 at-least as large as the count of U_NODE plus the latency between them.
1203 Sets a bit in TMP for each successor whose count was changed (increased).
1204 Returns nonzero if any count was changed. */
1205 static int
1206 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1208 ddg_edge_ptr e;
1209 int result = 0;
1211 for (e = u_node->out; e; e = e->next_out)
1213 ddg_node_ptr v_node = e->dest;
1214 int v = v_node->cuid;
1216 if (bitmap_bit_p (nodes, v)
1217 && (e->distance == 0)
1218 && (v_node->aux.count < u_node->aux.count + e->latency))
1220 v_node->aux.count = u_node->aux.count + e->latency;
1221 bitmap_set_bit (tmp, v);
1222 result = 1;
1225 return result;
1229 /* Find the length of a longest path from SRC to DEST in G,
1230 going only through NODES, and disregarding backarcs. */
1232 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1234 int i;
1235 unsigned int u = 0;
1236 int change = 1;
1237 int result;
1238 int num_nodes = g->num_nodes;
1239 sbitmap workset = sbitmap_alloc (num_nodes);
1240 sbitmap tmp = sbitmap_alloc (num_nodes);
1243 /* Data will hold the distance of the longest path found so far from
1244 src to each node. Initialize to -1 = less than minimum. */
1245 for (i = 0; i < g->num_nodes; i++)
1246 g->nodes[i].aux.count = -1;
1247 g->nodes[src].aux.count = 0;
1249 bitmap_clear (tmp);
1250 bitmap_set_bit (tmp, src);
1252 while (change)
1254 sbitmap_iterator sbi;
1256 change = 0;
1257 bitmap_copy (workset, tmp);
1258 bitmap_clear (tmp);
1259 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1261 ddg_node_ptr u_node = &g->nodes[u];
1263 change |= update_dist_to_successors (u_node, nodes, tmp);
1266 result = g->nodes[dest].aux.count;
1267 sbitmap_free (workset);
1268 sbitmap_free (tmp);
1269 return result;
1272 #endif /* INSN_SCHEDULING */