2012-01-31 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / ddg.c
bloba5158827638942dc32cccf876360e90b4a8d3644
1 /* DDG - Data Dependence Graph implementation.
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "diagnostic-core.h"
28 #include "rtl.h"
29 #include "tm_p.h"
30 #include "hard-reg-set.h"
31 #include "regs.h"
32 #include "function.h"
33 #include "flags.h"
34 #include "insn-config.h"
35 #include "insn-attr.h"
36 #include "except.h"
37 #include "recog.h"
38 #include "sched-int.h"
39 #include "target.h"
40 #include "cfglayout.h"
41 #include "cfgloop.h"
42 #include "sbitmap.h"
43 #include "expr.h"
44 #include "bitmap.h"
45 #include "ddg.h"
47 #ifdef INSN_SCHEDULING
49 /* A flag indicating that a ddg edge belongs to an SCC or not. */
50 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
52 /* Forward declarations. */
53 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
54 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
55 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
56 static void create_ddg_dep_from_intra_loop_link (ddg_ptr, ddg_node_ptr,
57 ddg_node_ptr, dep_t);
58 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
59 dep_type, dep_data_type, int);
60 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
61 dep_data_type, int, int);
62 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
64 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
65 static bool mem_ref_p;
67 /* Auxiliary function for mem_read_insn_p. */
68 static int
69 mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
71 if (MEM_P (*x))
72 mem_ref_p = true;
73 return 0;
76 /* Auxiliary function for mem_read_insn_p. */
77 static void
78 mark_mem_use_1 (rtx *x, void *data)
80 for_each_rtx (x, mark_mem_use, data);
83 /* Returns nonzero if INSN reads from memory. */
84 static bool
85 mem_read_insn_p (rtx insn)
87 mem_ref_p = false;
88 note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
89 return mem_ref_p;
92 static void
93 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
95 if (MEM_P (loc))
96 mem_ref_p = true;
99 /* Returns nonzero if INSN writes to memory. */
100 static bool
101 mem_write_insn_p (rtx insn)
103 mem_ref_p = false;
104 note_stores (PATTERN (insn), mark_mem_store, NULL);
105 return mem_ref_p;
108 /* Returns nonzero if X has access to memory. */
109 static bool
110 rtx_mem_access_p (rtx x)
112 int i, j;
113 const char *fmt;
114 enum rtx_code code;
116 if (x == 0)
117 return false;
119 if (MEM_P (x))
120 return true;
122 code = GET_CODE (x);
123 fmt = GET_RTX_FORMAT (code);
124 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
126 if (fmt[i] == 'e')
128 if (rtx_mem_access_p (XEXP (x, i)))
129 return true;
131 else if (fmt[i] == 'E')
132 for (j = 0; j < XVECLEN (x, i); j++)
134 if (rtx_mem_access_p (XVECEXP (x, i, j)))
135 return true;
138 return false;
141 /* Returns nonzero if INSN reads to or writes from memory. */
142 static bool
143 mem_access_insn_p (rtx insn)
145 return rtx_mem_access_p (PATTERN (insn));
148 /* Return true if DEF_INSN contains address being auto-inc or auto-dec
149 which is used in USE_INSN. Otherwise return false. The result is
150 being used to decide whether to remove the edge between def_insn and
151 use_insn when -fmodulo-sched-allow-regmoves is set. This function
152 doesn't need to consider the specific address register; no reg_moves
153 will be allowed for any life range defined by def_insn and used
154 by use_insn, if use_insn uses an address register auto-inc'ed by
155 def_insn. */
156 bool
157 autoinc_var_is_used_p (rtx def_insn, rtx use_insn)
159 rtx note;
161 for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
162 if (REG_NOTE_KIND (note) == REG_INC
163 && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
164 return true;
166 return false;
169 /* Return true if one of the definitions in INSN has MODE_CC. Otherwise
170 return false. */
171 static bool
172 def_has_ccmode_p (rtx insn)
174 df_ref *def;
176 for (def = DF_INSN_DEFS (insn); *def; def++)
178 enum machine_mode mode = GET_MODE (DF_REF_REG (*def));
180 if (GET_MODE_CLASS (mode) == MODE_CC)
181 return true;
184 return false;
187 /* Computes the dependence parameters (latency, distance etc.), creates
188 a ddg_edge and adds it to the given DDG. */
189 static void
190 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
191 ddg_node_ptr dest_node, dep_t link)
193 ddg_edge_ptr e;
194 int latency, distance = 0;
195 dep_type t = TRUE_DEP;
196 dep_data_type dt = (mem_access_insn_p (src_node->insn)
197 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
198 : REG_DEP);
199 gcc_assert (src_node->cuid < dest_node->cuid);
200 gcc_assert (link);
202 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
203 if (DEP_TYPE (link) == REG_DEP_ANTI)
204 t = ANTI_DEP;
205 else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
206 t = OUTPUT_DEP;
208 gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
209 gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
211 /* We currently choose not to create certain anti-deps edges and
212 compensate for that by generating reg-moves based on the life-range
213 analysis. The anti-deps that will be deleted are the ones which
214 have true-deps edges in the opposite direction (in other words
215 the kernel has only one def of the relevant register).
216 If the address that is being auto-inc or auto-dec in DEST_NODE
217 is used in SRC_NODE then do not remove the edge to make sure
218 reg-moves will not be created for this address.
219 TODO: support the removal of all anti-deps edges, i.e. including those
220 whose register has multiple defs in the loop. */
221 if (flag_modulo_sched_allow_regmoves
222 && (t == ANTI_DEP && dt == REG_DEP)
223 && !def_has_ccmode_p (dest_node->insn)
224 && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
226 rtx set;
228 set = single_set (dest_node->insn);
229 /* TODO: Handle registers that REG_P is not true for them, i.e.
230 subregs and special registers. */
231 if (set && REG_P (SET_DEST (set)))
233 int regno = REGNO (SET_DEST (set));
234 df_ref first_def;
235 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
237 first_def = df_bb_regno_first_def_find (g->bb, regno);
238 gcc_assert (first_def);
240 if (bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)))
241 return;
245 latency = dep_cost (link);
246 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
247 add_edge_to_ddg (g, e);
250 /* The same as the above function, but it doesn't require a link parameter. */
251 static void
252 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
253 dep_type d_t, dep_data_type d_dt, int distance)
255 ddg_edge_ptr e;
256 int l;
257 enum reg_note dep_kind;
258 struct _dep _dep, *dep = &_dep;
260 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
261 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
263 if (d_t == ANTI_DEP)
264 dep_kind = REG_DEP_ANTI;
265 else if (d_t == OUTPUT_DEP)
266 dep_kind = REG_DEP_OUTPUT;
267 else
269 gcc_assert (d_t == TRUE_DEP);
271 dep_kind = REG_DEP_TRUE;
274 init_dep (dep, from->insn, to->insn, dep_kind);
276 l = dep_cost (dep);
278 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
279 if (distance > 0)
280 add_backarc_to_ddg (g, e);
281 else
282 add_edge_to_ddg (g, e);
286 /* Given a downwards exposed register def LAST_DEF (which is the last
287 definition of that register in the bb), add inter-loop true dependences
288 to all its uses in the next iteration, an output dependence to the
289 first def of the same register (possibly itself) in the next iteration
290 and anti-dependences from its uses in the current iteration to the
291 first definition in the next iteration. */
292 static void
293 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
295 int regno = DF_REF_REGNO (last_def);
296 struct df_link *r_use;
297 int has_use_in_bb_p = false;
298 rtx def_insn = DF_REF_INSN (last_def);
299 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
300 ddg_node_ptr use_node;
301 #ifdef ENABLE_CHECKING
302 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
303 #endif
304 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
306 gcc_assert (last_def_node);
307 gcc_assert (first_def);
309 #ifdef ENABLE_CHECKING
310 if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
311 gcc_assert (!bitmap_bit_p (&bb_info->gen,
312 DF_REF_ID (first_def)));
313 #endif
315 /* Create inter-loop true dependences and anti dependences. */
316 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
318 rtx use_insn = DF_REF_INSN (r_use->ref);
320 if (BLOCK_FOR_INSN (use_insn) != g->bb)
321 continue;
323 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
324 use_node = get_node_of_insn (g, use_insn);
325 gcc_assert (use_node);
326 has_use_in_bb_p = true;
327 if (use_node->cuid <= last_def_node->cuid)
329 /* Add true deps from last_def to it's uses in the next
330 iteration. Any such upwards exposed use appears before
331 the last_def def. */
332 create_ddg_dep_no_link (g, last_def_node, use_node,
333 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
334 REG_DEP, 1);
336 else if (!DEBUG_INSN_P (use_insn))
338 /* Add anti deps from last_def's uses in the current iteration
339 to the first def in the next iteration. We do not add ANTI
340 dep when there is an intra-loop TRUE dep in the opposite
341 direction, but use regmoves to fix such disregarded ANTI
342 deps when broken. If the first_def reaches the USE then
343 there is such a dep. */
344 ddg_node_ptr first_def_node = get_node_of_insn (g,
345 DF_REF_INSN (first_def));
347 gcc_assert (first_def_node);
349 /* Always create the edge if the use node is a branch in
350 order to prevent the creation of reg-moves.
351 If the address that is being auto-inc or auto-dec in LAST_DEF
352 is used in USE_INSN then do not remove the edge to make sure
353 reg-moves will not be created for that address. */
354 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
355 || !flag_modulo_sched_allow_regmoves
356 || JUMP_P (use_node->insn)
357 || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
358 || def_has_ccmode_p (DF_REF_INSN (last_def)))
359 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
360 REG_DEP, 1);
364 /* Create an inter-loop output dependence between LAST_DEF (which is the
365 last def in its block, being downwards exposed) and the first def in
366 its block. Avoid creating a self output dependence. Avoid creating
367 an output dependence if there is a dependence path between the two
368 defs starting with a true dependence to a use which can be in the
369 next iteration; followed by an anti dependence of that use to the
370 first def (i.e. if there is a use between the two defs.) */
371 if (!has_use_in_bb_p)
373 ddg_node_ptr dest_node;
375 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
376 return;
378 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
379 gcc_assert (dest_node);
380 create_ddg_dep_no_link (g, last_def_node, dest_node,
381 OUTPUT_DEP, REG_DEP, 1);
384 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
385 static void
386 build_inter_loop_deps (ddg_ptr g)
388 unsigned rd_num;
389 struct df_rd_bb_info *rd_bb_info;
390 bitmap_iterator bi;
392 rd_bb_info = DF_RD_BB_INFO (g->bb);
394 /* Find inter-loop register output, true and anti deps. */
395 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
397 df_ref rd = DF_DEFS_GET (rd_num);
399 add_cross_iteration_register_deps (g, rd);
404 static int
405 walk_mems_2 (rtx *x, rtx mem)
407 if (MEM_P (*x))
409 if (may_alias_p (*x, mem))
410 return 1;
412 return -1;
414 return 0;
417 static int
418 walk_mems_1 (rtx *x, rtx *pat)
420 if (MEM_P (*x))
422 /* Visit all MEMs in *PAT and check indepedence. */
423 if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x))
424 /* Indicate that dependence was determined and stop traversal. */
425 return 1;
427 return -1;
429 return 0;
432 /* Return 1 if two specified instructions have mem expr with conflict alias sets*/
433 static int
434 insns_may_alias_p (rtx insn1, rtx insn2)
436 /* For each pair of MEMs in INSN1 and INSN2 check their independence. */
437 return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1,
438 &PATTERN (insn2));
441 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
442 to ddg G. */
443 static void
444 add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
447 if ((from->cuid == to->cuid)
448 || !insns_may_alias_p (from->insn, to->insn))
449 /* Do not create edge if memory references have disjoint alias sets
450 or 'to' and 'from' are the same instruction. */
451 return;
453 if (mem_write_insn_p (from->insn))
455 if (mem_read_insn_p (to->insn))
456 create_ddg_dep_no_link (g, from, to,
457 DEBUG_INSN_P (to->insn)
458 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
459 else
460 create_ddg_dep_no_link (g, from, to,
461 DEBUG_INSN_P (to->insn)
462 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
464 else if (!mem_read_insn_p (to->insn))
465 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
468 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
469 to ddg G. */
470 static void
471 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
473 if (!insns_may_alias_p (from->insn, to->insn))
474 /* Do not create edge if memory references have disjoint alias sets. */
475 return;
477 if (mem_write_insn_p (from->insn))
479 if (mem_read_insn_p (to->insn))
480 create_ddg_dep_no_link (g, from, to,
481 DEBUG_INSN_P (to->insn)
482 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
483 else if (from->cuid != to->cuid)
484 create_ddg_dep_no_link (g, from, to,
485 DEBUG_INSN_P (to->insn)
486 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
488 else
490 if (mem_read_insn_p (to->insn))
491 return;
492 else if (from->cuid != to->cuid)
494 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
495 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
496 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
497 else
498 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
504 /* Perform intra-block Data Dependency analysis and connect the nodes in
505 the DDG. We assume the loop has a single basic block. */
506 static void
507 build_intra_loop_deps (ddg_ptr g)
509 int i;
510 /* Hold the dependency analysis state during dependency calculations. */
511 struct deps_desc tmp_deps;
512 rtx head, tail;
514 /* Build the dependence information, using the sched_analyze function. */
515 init_deps_global ();
516 init_deps (&tmp_deps, false);
518 /* Do the intra-block data dependence analysis for the given block. */
519 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
520 sched_analyze (&tmp_deps, head, tail);
522 /* Build intra-loop data dependencies using the scheduler dependency
523 analysis. */
524 for (i = 0; i < g->num_nodes; i++)
526 ddg_node_ptr dest_node = &g->nodes[i];
527 sd_iterator_def sd_it;
528 dep_t dep;
530 if (! INSN_P (dest_node->insn))
531 continue;
533 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
535 ddg_node_ptr src_node = get_node_of_insn (g, DEP_PRO (dep));
537 if (!src_node)
538 continue;
540 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
543 /* If this insn modifies memory, add an edge to all insns that access
544 memory. */
545 if (mem_access_insn_p (dest_node->insn))
547 int j;
549 for (j = 0; j <= i; j++)
551 ddg_node_ptr j_node = &g->nodes[j];
552 if (DEBUG_INSN_P (j_node->insn))
553 continue;
554 if (mem_access_insn_p (j_node->insn))
556 /* Don't bother calculating inter-loop dep if an intra-loop dep
557 already exists. */
558 if (! TEST_BIT (dest_node->successors, j))
559 add_inter_loop_mem_dep (g, dest_node, j_node);
560 /* If -fmodulo-sched-allow-regmoves
561 is set certain anti-dep edges are not created.
562 It might be that these anti-dep edges are on the
563 path from one memory instruction to another such that
564 removing these edges could cause a violation of the
565 memory dependencies. Thus we add intra edges between
566 every two memory instructions in this case. */
567 if (flag_modulo_sched_allow_regmoves
568 && !TEST_BIT (dest_node->predecessors, j))
569 add_intra_loop_mem_dep (g, j_node, dest_node);
575 /* Free the INSN_LISTs. */
576 finish_deps_global ();
577 free_deps (&tmp_deps);
579 /* Free dependencies. */
580 sched_free_deps (head, tail, false);
584 /* Given a basic block, create its DDG and return a pointer to a variable
585 of ddg type that represents it.
586 Initialize the ddg structure fields to the appropriate values. */
587 ddg_ptr
588 create_ddg (basic_block bb, int closing_branch_deps)
590 ddg_ptr g;
591 rtx insn, first_note;
592 int i;
593 int num_nodes = 0;
595 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
597 g->bb = bb;
598 g->closing_branch_deps = closing_branch_deps;
600 /* Count the number of insns in the BB. */
601 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
602 insn = NEXT_INSN (insn))
604 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
605 continue;
607 if (DEBUG_INSN_P (insn))
608 g->num_debug++;
609 else
611 if (mem_read_insn_p (insn))
612 g->num_loads++;
613 if (mem_write_insn_p (insn))
614 g->num_stores++;
616 num_nodes++;
619 /* There is nothing to do for this BB. */
620 if ((num_nodes - g->num_debug) <= 1)
622 free (g);
623 return NULL;
626 /* Allocate the nodes array, and initialize the nodes. */
627 g->num_nodes = num_nodes;
628 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
629 g->closing_branch = NULL;
630 i = 0;
631 first_note = NULL_RTX;
632 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
633 insn = NEXT_INSN (insn))
635 if (! INSN_P (insn))
637 if (! first_note && NOTE_P (insn)
638 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
639 first_note = insn;
640 continue;
642 if (JUMP_P (insn))
644 gcc_assert (!g->closing_branch);
645 g->closing_branch = &g->nodes[i];
647 else if (GET_CODE (PATTERN (insn)) == USE)
649 if (! first_note)
650 first_note = insn;
651 continue;
654 g->nodes[i].cuid = i;
655 g->nodes[i].successors = sbitmap_alloc (num_nodes);
656 sbitmap_zero (g->nodes[i].successors);
657 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
658 sbitmap_zero (g->nodes[i].predecessors);
659 g->nodes[i].first_note = (first_note ? first_note : insn);
660 g->nodes[i++].insn = insn;
661 first_note = NULL_RTX;
664 /* We must have found a branch in DDG. */
665 gcc_assert (g->closing_branch);
668 /* Build the data dependency graph. */
669 build_intra_loop_deps (g);
670 build_inter_loop_deps (g);
671 return g;
674 /* Free all the memory allocated for the DDG. */
675 void
676 free_ddg (ddg_ptr g)
678 int i;
680 if (!g)
681 return;
683 for (i = 0; i < g->num_nodes; i++)
685 ddg_edge_ptr e = g->nodes[i].out;
687 while (e)
689 ddg_edge_ptr next = e->next_out;
691 free (e);
692 e = next;
694 sbitmap_free (g->nodes[i].successors);
695 sbitmap_free (g->nodes[i].predecessors);
697 if (g->num_backarcs > 0)
698 free (g->backarcs);
699 free (g->nodes);
700 free (g);
703 void
704 print_ddg_edge (FILE *file, ddg_edge_ptr e)
706 char dep_c;
708 switch (e->type)
710 case OUTPUT_DEP :
711 dep_c = 'O';
712 break;
713 case ANTI_DEP :
714 dep_c = 'A';
715 break;
716 default:
717 dep_c = 'T';
720 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
721 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
724 /* Print the DDG nodes with there in/out edges to the dump file. */
725 void
726 print_ddg (FILE *file, ddg_ptr g)
728 int i;
730 for (i = 0; i < g->num_nodes; i++)
732 ddg_edge_ptr e;
734 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
735 print_rtl_single (file, g->nodes[i].insn);
736 fprintf (file, "OUT ARCS: ");
737 for (e = g->nodes[i].out; e; e = e->next_out)
738 print_ddg_edge (file, e);
740 fprintf (file, "\nIN ARCS: ");
741 for (e = g->nodes[i].in; e; e = e->next_in)
742 print_ddg_edge (file, e);
744 fprintf (file, "\n");
748 /* Print the given DDG in VCG format. */
749 void
750 vcg_print_ddg (FILE *file, ddg_ptr g)
752 int src_cuid;
754 fprintf (file, "graph: {\n");
755 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
757 ddg_edge_ptr e;
758 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
760 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
761 print_rtl_single (file, g->nodes[src_cuid].insn);
762 fprintf (file, "\"}\n");
763 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
765 int dst_uid = INSN_UID (e->dest->insn);
766 int dst_cuid = e->dest->cuid;
768 /* Give the backarcs a different color. */
769 if (e->distance > 0)
770 fprintf (file, "backedge: {color: red ");
771 else
772 fprintf (file, "edge: { ");
774 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
775 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
776 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
779 fprintf (file, "}\n");
782 /* Dump the sccs in SCCS. */
783 void
784 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
786 unsigned int u = 0;
787 sbitmap_iterator sbi;
788 int i;
790 if (!file)
791 return;
793 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
794 for (i = 0; i < sccs->num_sccs; i++)
796 fprintf (file, "SCC number: %d\n", i);
797 EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
799 fprintf (file, "insn num %d\n", u);
800 print_rtl_single (file, g->nodes[u].insn);
803 fprintf (file, "\n");
806 /* Create an edge and initialize it with given values. */
807 static ddg_edge_ptr
808 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
809 dep_type t, dep_data_type dt, int l, int d)
811 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
813 e->src = src;
814 e->dest = dest;
815 e->type = t;
816 e->data_type = dt;
817 e->latency = l;
818 e->distance = d;
819 e->next_in = e->next_out = NULL;
820 e->aux.info = 0;
821 return e;
824 /* Add the given edge to the in/out linked lists of the DDG nodes. */
825 static void
826 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
828 ddg_node_ptr src = e->src;
829 ddg_node_ptr dest = e->dest;
831 /* Should have allocated the sbitmaps. */
832 gcc_assert (src->successors && dest->predecessors);
834 SET_BIT (src->successors, dest->cuid);
835 SET_BIT (dest->predecessors, src->cuid);
836 e->next_in = dest->in;
837 dest->in = e;
838 e->next_out = src->out;
839 src->out = e;
844 /* Algorithm for computing the recurrence_length of an scc. We assume at
845 for now that cycles in the data dependence graph contain a single backarc.
846 This simplifies the algorithm, and can be generalized later. */
847 static void
848 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
850 int j;
851 int result = -1;
853 for (j = 0; j < scc->num_backarcs; j++)
855 ddg_edge_ptr backarc = scc->backarcs[j];
856 int length;
857 int distance = backarc->distance;
858 ddg_node_ptr src = backarc->dest;
859 ddg_node_ptr dest = backarc->src;
861 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
862 if (length < 0 )
864 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
865 continue;
867 length += backarc->latency;
868 result = MAX (result, (length / distance));
870 scc->recurrence_length = result;
873 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
874 and mark edges that belong to this scc as IN_SCC. */
875 static ddg_scc_ptr
876 create_scc (ddg_ptr g, sbitmap nodes)
878 ddg_scc_ptr scc;
879 unsigned int u = 0;
880 sbitmap_iterator sbi;
882 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
883 scc->backarcs = NULL;
884 scc->num_backarcs = 0;
885 scc->nodes = sbitmap_alloc (g->num_nodes);
886 sbitmap_copy (scc->nodes, nodes);
888 /* Mark the backarcs that belong to this SCC. */
889 EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
891 ddg_edge_ptr e;
892 ddg_node_ptr n = &g->nodes[u];
894 for (e = n->out; e; e = e->next_out)
895 if (TEST_BIT (nodes, e->dest->cuid))
897 e->aux.count = IN_SCC;
898 if (e->distance > 0)
899 add_backarc_to_scc (scc, e);
903 set_recurrence_length (scc, g);
904 return scc;
907 /* Cleans the memory allocation of a given SCC. */
908 static void
909 free_scc (ddg_scc_ptr scc)
911 if (!scc)
912 return;
914 sbitmap_free (scc->nodes);
915 if (scc->num_backarcs > 0)
916 free (scc->backarcs);
917 free (scc);
921 /* Add a given edge known to be a backarc to the given DDG. */
922 static void
923 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
925 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
927 add_edge_to_ddg (g, e);
928 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
929 g->backarcs[g->num_backarcs++] = e;
932 /* Add backarc to an SCC. */
933 static void
934 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
936 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
938 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
939 scc->backarcs[scc->num_backarcs++] = e;
942 /* Add the given SCC to the DDG. */
943 static void
944 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
946 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
948 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
949 g->sccs[g->num_sccs++] = scc;
952 /* Given the instruction INSN return the node that represents it. */
953 ddg_node_ptr
954 get_node_of_insn (ddg_ptr g, rtx insn)
956 int i;
958 for (i = 0; i < g->num_nodes; i++)
959 if (insn == g->nodes[i].insn)
960 return &g->nodes[i];
961 return NULL;
964 /* Given a set OPS of nodes in the DDG, find the set of their successors
965 which are not in OPS, and set their bits in SUCC. Bits corresponding to
966 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
967 void
968 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
970 unsigned int i = 0;
971 sbitmap_iterator sbi;
973 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
975 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
976 sbitmap_a_or_b (succ, succ, node_succ);
979 /* We want those that are not in ops. */
980 sbitmap_difference (succ, succ, ops);
983 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
984 which are not in OPS, and set their bits in PREDS. Bits corresponding to
985 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
986 void
987 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
989 unsigned int i = 0;
990 sbitmap_iterator sbi;
992 EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
994 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
995 sbitmap_a_or_b (preds, preds, node_preds);
998 /* We want those that are not in ops. */
999 sbitmap_difference (preds, preds, ops);
1003 /* Compare function to be passed to qsort to order the backarcs in descending
1004 recMII order. */
1005 static int
1006 compare_sccs (const void *s1, const void *s2)
1008 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
1009 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
1010 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
1014 /* Order the backarcs in descending recMII order using compare_sccs. */
1015 static void
1016 order_sccs (ddg_all_sccs_ptr g)
1018 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
1019 (int (*) (const void *, const void *)) compare_sccs);
1022 #ifdef ENABLE_CHECKING
1023 /* Check that every node in SCCS belongs to exactly one strongly connected
1024 component and that no element of SCCS is empty. */
1025 static void
1026 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
1028 int i = 0;
1029 sbitmap tmp = sbitmap_alloc (num_nodes);
1031 sbitmap_zero (tmp);
1032 for (i = 0; i < sccs->num_sccs; i++)
1034 gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes));
1035 /* Verify that every node in sccs is in exactly one strongly
1036 connected component. */
1037 gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes));
1038 sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes);
1040 sbitmap_free (tmp);
1042 #endif
1044 /* Perform the Strongly Connected Components decomposing algorithm on the
1045 DDG and return DDG_ALL_SCCS structure that contains them. */
1046 ddg_all_sccs_ptr
1047 create_ddg_all_sccs (ddg_ptr g)
1049 int i;
1050 int num_nodes = g->num_nodes;
1051 sbitmap from = sbitmap_alloc (num_nodes);
1052 sbitmap to = sbitmap_alloc (num_nodes);
1053 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
1054 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
1055 xmalloc (sizeof (struct ddg_all_sccs));
1057 sccs->ddg = g;
1058 sccs->sccs = NULL;
1059 sccs->num_sccs = 0;
1061 for (i = 0; i < g->num_backarcs; i++)
1063 ddg_scc_ptr scc;
1064 ddg_edge_ptr backarc = g->backarcs[i];
1065 ddg_node_ptr src = backarc->src;
1066 ddg_node_ptr dest = backarc->dest;
1068 /* If the backarc already belongs to an SCC, continue. */
1069 if (backarc->aux.count == IN_SCC)
1070 continue;
1072 sbitmap_zero (scc_nodes);
1073 sbitmap_zero (from);
1074 sbitmap_zero (to);
1075 SET_BIT (from, dest->cuid);
1076 SET_BIT (to, src->cuid);
1078 if (find_nodes_on_paths (scc_nodes, g, from, to))
1080 scc = create_scc (g, scc_nodes);
1081 add_scc_to_ddg (sccs, scc);
1084 order_sccs (sccs);
1085 sbitmap_free (from);
1086 sbitmap_free (to);
1087 sbitmap_free (scc_nodes);
1088 #ifdef ENABLE_CHECKING
1089 check_sccs (sccs, num_nodes);
1090 #endif
1091 return sccs;
1094 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1095 void
1096 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1098 int i;
1100 if (!all_sccs)
1101 return;
1103 for (i = 0; i < all_sccs->num_sccs; i++)
1104 free_scc (all_sccs->sccs[i]);
1106 free (all_sccs->sccs);
1107 free (all_sccs);
1111 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1112 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1113 nodes from FROM and TO). Return nonzero if nodes exist. */
1115 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1117 int answer;
1118 int change;
1119 unsigned int u = 0;
1120 int num_nodes = g->num_nodes;
1121 sbitmap_iterator sbi;
1123 sbitmap workset = sbitmap_alloc (num_nodes);
1124 sbitmap reachable_from = sbitmap_alloc (num_nodes);
1125 sbitmap reach_to = sbitmap_alloc (num_nodes);
1126 sbitmap tmp = sbitmap_alloc (num_nodes);
1128 sbitmap_copy (reachable_from, from);
1129 sbitmap_copy (tmp, from);
1131 change = 1;
1132 while (change)
1134 change = 0;
1135 sbitmap_copy (workset, tmp);
1136 sbitmap_zero (tmp);
1137 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1139 ddg_edge_ptr e;
1140 ddg_node_ptr u_node = &g->nodes[u];
1142 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1144 ddg_node_ptr v_node = e->dest;
1145 int v = v_node->cuid;
1147 if (!TEST_BIT (reachable_from, v))
1149 SET_BIT (reachable_from, v);
1150 SET_BIT (tmp, v);
1151 change = 1;
1157 sbitmap_copy (reach_to, to);
1158 sbitmap_copy (tmp, to);
1160 change = 1;
1161 while (change)
1163 change = 0;
1164 sbitmap_copy (workset, tmp);
1165 sbitmap_zero (tmp);
1166 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1168 ddg_edge_ptr e;
1169 ddg_node_ptr u_node = &g->nodes[u];
1171 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1173 ddg_node_ptr v_node = e->src;
1174 int v = v_node->cuid;
1176 if (!TEST_BIT (reach_to, v))
1178 SET_BIT (reach_to, v);
1179 SET_BIT (tmp, v);
1180 change = 1;
1186 answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
1187 sbitmap_free (workset);
1188 sbitmap_free (reachable_from);
1189 sbitmap_free (reach_to);
1190 sbitmap_free (tmp);
1191 return answer;
1195 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1196 at-least as large as the count of U_NODE plus the latency between them.
1197 Sets a bit in TMP for each successor whose count was changed (increased).
1198 Returns nonzero if any count was changed. */
1199 static int
1200 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1202 ddg_edge_ptr e;
1203 int result = 0;
1205 for (e = u_node->out; e; e = e->next_out)
1207 ddg_node_ptr v_node = e->dest;
1208 int v = v_node->cuid;
1210 if (TEST_BIT (nodes, v)
1211 && (e->distance == 0)
1212 && (v_node->aux.count < u_node->aux.count + e->latency))
1214 v_node->aux.count = u_node->aux.count + e->latency;
1215 SET_BIT (tmp, v);
1216 result = 1;
1219 return result;
1223 /* Find the length of a longest path from SRC to DEST in G,
1224 going only through NODES, and disregarding backarcs. */
1226 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1228 int i;
1229 unsigned int u = 0;
1230 int change = 1;
1231 int result;
1232 int num_nodes = g->num_nodes;
1233 sbitmap workset = sbitmap_alloc (num_nodes);
1234 sbitmap tmp = sbitmap_alloc (num_nodes);
1237 /* Data will hold the distance of the longest path found so far from
1238 src to each node. Initialize to -1 = less than minimum. */
1239 for (i = 0; i < g->num_nodes; i++)
1240 g->nodes[i].aux.count = -1;
1241 g->nodes[src].aux.count = 0;
1243 sbitmap_zero (tmp);
1244 SET_BIT (tmp, src);
1246 while (change)
1248 sbitmap_iterator sbi;
1250 change = 0;
1251 sbitmap_copy (workset, tmp);
1252 sbitmap_zero (tmp);
1253 EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1255 ddg_node_ptr u_node = &g->nodes[u];
1257 change |= update_dist_to_successors (u_node, nodes, tmp);
1260 result = g->nodes[dest].aux.count;
1261 sbitmap_free (workset);
1262 sbitmap_free (tmp);
1263 return result;
1266 #endif /* INSN_SCHEDULING */