PR middle-end/66633
[official-gcc.git] / gcc / ddg.c
blobca7ebe20499d9e46caceae2718d6e0103463c6e6
1 /* DDG - Data Dependence Graph implementation.
2 Copyright (C) 2004-2015 Free Software Foundation, Inc.
3 Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
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 "predict.h"
38 #include "basic-block.h"
39 #include "sched-int.h"
40 #include "target.h"
41 #include "cfgloop.h"
42 #include "sbitmap.h"
43 #include "symtab.h"
44 #include "alias.h"
45 #include "tree.h"
46 #include "expmed.h"
47 #include "dojump.h"
48 #include "explow.h"
49 #include "calls.h"
50 #include "emit-rtl.h"
51 #include "varasm.h"
52 #include "stmt.h"
53 #include "expr.h"
54 #include "bitmap.h"
55 #include "df.h"
56 #include "ddg.h"
57 #include "rtl-iter.h"
59 #ifdef INSN_SCHEDULING
61 /* A flag indicating that a ddg edge belongs to an SCC or not. */
62 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
64 /* Forward declarations. */
65 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
66 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
67 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
68 static void create_ddg_dep_from_intra_loop_link (ddg_ptr, ddg_node_ptr,
69 ddg_node_ptr, dep_t);
70 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
71 dep_type, dep_data_type, int);
72 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
73 dep_data_type, int, int);
74 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
76 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
77 static bool mem_ref_p;
79 /* Auxiliary function for mem_read_insn_p. */
80 static void
81 mark_mem_use (rtx *x, void *)
83 subrtx_iterator::array_type array;
84 FOR_EACH_SUBRTX (iter, array, *x, NONCONST)
85 if (MEM_P (*iter))
87 mem_ref_p = true;
88 break;
92 /* Returns nonzero if INSN reads from memory. */
93 static bool
94 mem_read_insn_p (rtx_insn *insn)
96 mem_ref_p = false;
97 note_uses (&PATTERN (insn), mark_mem_use, NULL);
98 return mem_ref_p;
101 static void
102 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
104 if (MEM_P (loc))
105 mem_ref_p = true;
108 /* Returns nonzero if INSN writes to memory. */
109 static bool
110 mem_write_insn_p (rtx_insn *insn)
112 mem_ref_p = false;
113 note_stores (PATTERN (insn), mark_mem_store, NULL);
114 return mem_ref_p;
117 /* Returns nonzero if X has access to memory. */
118 static bool
119 rtx_mem_access_p (rtx x)
121 int i, j;
122 const char *fmt;
123 enum rtx_code code;
125 if (x == 0)
126 return false;
128 if (MEM_P (x))
129 return true;
131 code = GET_CODE (x);
132 fmt = GET_RTX_FORMAT (code);
133 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
135 if (fmt[i] == 'e')
137 if (rtx_mem_access_p (XEXP (x, i)))
138 return true;
140 else if (fmt[i] == 'E')
141 for (j = 0; j < XVECLEN (x, i); j++)
143 if (rtx_mem_access_p (XVECEXP (x, i, j)))
144 return true;
147 return false;
150 /* Returns nonzero if INSN reads to or writes from memory. */
151 static bool
152 mem_access_insn_p (rtx_insn *insn)
154 return rtx_mem_access_p (PATTERN (insn));
157 /* Return true if DEF_INSN contains address being auto-inc or auto-dec
158 which is used in USE_INSN. Otherwise return false. The result is
159 being used to decide whether to remove the edge between def_insn and
160 use_insn when -fmodulo-sched-allow-regmoves is set. This function
161 doesn't need to consider the specific address register; no reg_moves
162 will be allowed for any life range defined by def_insn and used
163 by use_insn, if use_insn uses an address register auto-inc'ed by
164 def_insn. */
165 bool
166 autoinc_var_is_used_p (rtx_insn *def_insn, rtx_insn *use_insn)
168 rtx note;
170 for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
171 if (REG_NOTE_KIND (note) == REG_INC
172 && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
173 return true;
175 return false;
178 /* Return true if one of the definitions in INSN has MODE_CC. Otherwise
179 return false. */
180 static bool
181 def_has_ccmode_p (rtx_insn *insn)
183 df_ref def;
185 FOR_EACH_INSN_DEF (def, insn)
187 machine_mode mode = GET_MODE (DF_REF_REG (def));
189 if (GET_MODE_CLASS (mode) == MODE_CC)
190 return true;
193 return false;
196 /* Computes the dependence parameters (latency, distance etc.), creates
197 a ddg_edge and adds it to the given DDG. */
198 static void
199 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
200 ddg_node_ptr dest_node, dep_t link)
202 ddg_edge_ptr e;
203 int latency, distance = 0;
204 dep_type t = TRUE_DEP;
205 dep_data_type dt = (mem_access_insn_p (src_node->insn)
206 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
207 : REG_DEP);
208 gcc_assert (src_node->cuid < dest_node->cuid);
209 gcc_assert (link);
211 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
212 if (DEP_TYPE (link) == REG_DEP_ANTI)
213 t = ANTI_DEP;
214 else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
215 t = OUTPUT_DEP;
217 gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
218 gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
220 /* We currently choose not to create certain anti-deps edges and
221 compensate for that by generating reg-moves based on the life-range
222 analysis. The anti-deps that will be deleted are the ones which
223 have true-deps edges in the opposite direction (in other words
224 the kernel has only one def of the relevant register).
225 If the address that is being auto-inc or auto-dec in DEST_NODE
226 is used in SRC_NODE then do not remove the edge to make sure
227 reg-moves will not be created for this address.
228 TODO: support the removal of all anti-deps edges, i.e. including those
229 whose register has multiple defs in the loop. */
230 if (flag_modulo_sched_allow_regmoves
231 && (t == ANTI_DEP && dt == REG_DEP)
232 && !def_has_ccmode_p (dest_node->insn)
233 && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
235 rtx set;
237 set = single_set (dest_node->insn);
238 /* TODO: Handle registers that REG_P is not true for them, i.e.
239 subregs and special registers. */
240 if (set && REG_P (SET_DEST (set)))
242 int regno = REGNO (SET_DEST (set));
243 df_ref first_def;
244 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
246 first_def = df_bb_regno_first_def_find (g->bb, regno);
247 gcc_assert (first_def);
249 if (bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)))
250 return;
254 latency = dep_cost (link);
255 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
256 add_edge_to_ddg (g, e);
259 /* The same as the above function, but it doesn't require a link parameter. */
260 static void
261 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
262 dep_type d_t, dep_data_type d_dt, int distance)
264 ddg_edge_ptr e;
265 int l;
266 enum reg_note dep_kind;
267 struct _dep _dep, *dep = &_dep;
269 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
270 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
272 if (d_t == ANTI_DEP)
273 dep_kind = REG_DEP_ANTI;
274 else if (d_t == OUTPUT_DEP)
275 dep_kind = REG_DEP_OUTPUT;
276 else
278 gcc_assert (d_t == TRUE_DEP);
280 dep_kind = REG_DEP_TRUE;
283 init_dep (dep, from->insn, to->insn, dep_kind);
285 l = dep_cost (dep);
287 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
288 if (distance > 0)
289 add_backarc_to_ddg (g, e);
290 else
291 add_edge_to_ddg (g, e);
295 /* Given a downwards exposed register def LAST_DEF (which is the last
296 definition of that register in the bb), add inter-loop true dependences
297 to all its uses in the next iteration, an output dependence to the
298 first def of the same register (possibly itself) in the next iteration
299 and anti-dependences from its uses in the current iteration to the
300 first definition in the next iteration. */
301 static void
302 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
304 int regno = DF_REF_REGNO (last_def);
305 struct df_link *r_use;
306 int has_use_in_bb_p = false;
307 rtx_insn *def_insn = DF_REF_INSN (last_def);
308 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
309 ddg_node_ptr use_node;
310 #ifdef ENABLE_CHECKING
311 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
312 #endif
313 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
315 gcc_assert (last_def_node);
316 gcc_assert (first_def);
318 #ifdef ENABLE_CHECKING
319 if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
320 gcc_assert (!bitmap_bit_p (&bb_info->gen,
321 DF_REF_ID (first_def)));
322 #endif
324 /* Create inter-loop true dependences and anti dependences. */
325 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
327 rtx_insn *use_insn = DF_REF_INSN (r_use->ref);
329 if (BLOCK_FOR_INSN (use_insn) != g->bb)
330 continue;
332 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
333 use_node = get_node_of_insn (g, use_insn);
334 gcc_assert (use_node);
335 has_use_in_bb_p = true;
336 if (use_node->cuid <= last_def_node->cuid)
338 /* Add true deps from last_def to it's uses in the next
339 iteration. Any such upwards exposed use appears before
340 the last_def def. */
341 create_ddg_dep_no_link (g, last_def_node, use_node,
342 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
343 REG_DEP, 1);
345 else if (!DEBUG_INSN_P (use_insn))
347 /* Add anti deps from last_def's uses in the current iteration
348 to the first def in the next iteration. We do not add ANTI
349 dep when there is an intra-loop TRUE dep in the opposite
350 direction, but use regmoves to fix such disregarded ANTI
351 deps when broken. If the first_def reaches the USE then
352 there is such a dep. */
353 ddg_node_ptr first_def_node = get_node_of_insn (g,
354 DF_REF_INSN (first_def));
356 gcc_assert (first_def_node);
358 /* Always create the edge if the use node is a branch in
359 order to prevent the creation of reg-moves.
360 If the address that is being auto-inc or auto-dec in LAST_DEF
361 is used in USE_INSN then do not remove the edge to make sure
362 reg-moves will not be created for that address. */
363 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
364 || !flag_modulo_sched_allow_regmoves
365 || JUMP_P (use_node->insn)
366 || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
367 || def_has_ccmode_p (DF_REF_INSN (last_def)))
368 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
369 REG_DEP, 1);
373 /* Create an inter-loop output dependence between LAST_DEF (which is the
374 last def in its block, being downwards exposed) and the first def in
375 its block. Avoid creating a self output dependence. Avoid creating
376 an output dependence if there is a dependence path between the two
377 defs starting with a true dependence to a use which can be in the
378 next iteration; followed by an anti dependence of that use to the
379 first def (i.e. if there is a use between the two defs.) */
380 if (!has_use_in_bb_p)
382 ddg_node_ptr dest_node;
384 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
385 return;
387 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
388 gcc_assert (dest_node);
389 create_ddg_dep_no_link (g, last_def_node, dest_node,
390 OUTPUT_DEP, REG_DEP, 1);
393 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
394 static void
395 build_inter_loop_deps (ddg_ptr g)
397 unsigned rd_num;
398 struct df_rd_bb_info *rd_bb_info;
399 bitmap_iterator bi;
401 rd_bb_info = DF_RD_BB_INFO (g->bb);
403 /* Find inter-loop register output, true and anti deps. */
404 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
406 df_ref rd = DF_DEFS_GET (rd_num);
408 add_cross_iteration_register_deps (g, rd);
413 /* Return true if two specified instructions have mem expr with conflict
414 alias sets. */
415 static bool
416 insns_may_alias_p (rtx_insn *insn1, rtx_insn *insn2)
418 subrtx_iterator::array_type array1;
419 subrtx_iterator::array_type array2;
420 FOR_EACH_SUBRTX (iter1, array1, PATTERN (insn1), NONCONST)
422 const_rtx x1 = *iter1;
423 if (MEM_P (x1))
424 FOR_EACH_SUBRTX (iter2, array2, PATTERN (insn2), NONCONST)
426 const_rtx x2 = *iter2;
427 if (MEM_P (x2) && may_alias_p (x2, x1))
428 return true;
431 return false;
434 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
435 to ddg G. */
436 static void
437 add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
440 if ((from->cuid == to->cuid)
441 || !insns_may_alias_p (from->insn, to->insn))
442 /* Do not create edge if memory references have disjoint alias sets
443 or 'to' and 'from' are the same instruction. */
444 return;
446 if (mem_write_insn_p (from->insn))
448 if (mem_read_insn_p (to->insn))
449 create_ddg_dep_no_link (g, from, to,
450 DEBUG_INSN_P (to->insn)
451 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
452 else
453 create_ddg_dep_no_link (g, from, to,
454 DEBUG_INSN_P (to->insn)
455 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
457 else if (!mem_read_insn_p (to->insn))
458 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
461 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
462 to ddg G. */
463 static void
464 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
466 if (!insns_may_alias_p (from->insn, to->insn))
467 /* Do not create edge if memory references have disjoint alias sets. */
468 return;
470 if (mem_write_insn_p (from->insn))
472 if (mem_read_insn_p (to->insn))
473 create_ddg_dep_no_link (g, from, to,
474 DEBUG_INSN_P (to->insn)
475 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
476 else if (from->cuid != to->cuid)
477 create_ddg_dep_no_link (g, from, to,
478 DEBUG_INSN_P (to->insn)
479 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
481 else
483 if (mem_read_insn_p (to->insn))
484 return;
485 else if (from->cuid != to->cuid)
487 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
488 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
489 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
490 else
491 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
497 /* Perform intra-block Data Dependency analysis and connect the nodes in
498 the DDG. We assume the loop has a single basic block. */
499 static void
500 build_intra_loop_deps (ddg_ptr g)
502 int i;
503 /* Hold the dependency analysis state during dependency calculations. */
504 struct deps_desc tmp_deps;
505 rtx_insn *head, *tail;
507 /* Build the dependence information, using the sched_analyze function. */
508 init_deps_global ();
509 init_deps (&tmp_deps, false);
511 /* Do the intra-block data dependence analysis for the given block. */
512 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
513 sched_analyze (&tmp_deps, head, tail);
515 /* Build intra-loop data dependencies using the scheduler dependency
516 analysis. */
517 for (i = 0; i < g->num_nodes; i++)
519 ddg_node_ptr dest_node = &g->nodes[i];
520 sd_iterator_def sd_it;
521 dep_t dep;
523 if (! INSN_P (dest_node->insn))
524 continue;
526 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
528 rtx_insn *src_insn = DEP_PRO (dep);
529 ddg_node_ptr src_node;
531 /* Don't add dependencies on debug insns to non-debug insns
532 to avoid codegen differences between -g and -g0. */
533 if (DEBUG_INSN_P (src_insn) && !DEBUG_INSN_P (dest_node->insn))
534 continue;
536 src_node = get_node_of_insn (g, src_insn);
538 if (!src_node)
539 continue;
541 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
544 /* If this insn modifies memory, add an edge to all insns that access
545 memory. */
546 if (mem_access_insn_p (dest_node->insn))
548 int j;
550 for (j = 0; j <= i; j++)
552 ddg_node_ptr j_node = &g->nodes[j];
553 if (DEBUG_INSN_P (j_node->insn))
554 continue;
555 if (mem_access_insn_p (j_node->insn))
557 /* Don't bother calculating inter-loop dep if an intra-loop dep
558 already exists. */
559 if (! bitmap_bit_p (dest_node->successors, j))
560 add_inter_loop_mem_dep (g, dest_node, j_node);
561 /* If -fmodulo-sched-allow-regmoves
562 is set certain anti-dep edges are not created.
563 It might be that these anti-dep edges are on the
564 path from one memory instruction to another such that
565 removing these edges could cause a violation of the
566 memory dependencies. Thus we add intra edges between
567 every two memory instructions in this case. */
568 if (flag_modulo_sched_allow_regmoves
569 && !bitmap_bit_p (dest_node->predecessors, j))
570 add_intra_loop_mem_dep (g, j_node, dest_node);
576 /* Free the INSN_LISTs. */
577 finish_deps_global ();
578 free_deps (&tmp_deps);
580 /* Free dependencies. */
581 sched_free_deps (head, tail, false);
585 /* Given a basic block, create its DDG and return a pointer to a variable
586 of ddg type that represents it.
587 Initialize the ddg structure fields to the appropriate values. */
588 ddg_ptr
589 create_ddg (basic_block bb, int closing_branch_deps)
591 ddg_ptr g;
592 rtx_insn *insn, *first_note;
593 int i;
594 int num_nodes = 0;
596 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
598 g->bb = bb;
599 g->closing_branch_deps = closing_branch_deps;
601 /* Count the number of insns in the BB. */
602 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
603 insn = NEXT_INSN (insn))
605 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
606 continue;
608 if (DEBUG_INSN_P (insn))
609 g->num_debug++;
610 else
612 if (mem_read_insn_p (insn))
613 g->num_loads++;
614 if (mem_write_insn_p (insn))
615 g->num_stores++;
617 num_nodes++;
620 /* There is nothing to do for this BB. */
621 if ((num_nodes - g->num_debug) <= 1)
623 free (g);
624 return NULL;
627 /* Allocate the nodes array, and initialize the nodes. */
628 g->num_nodes = num_nodes;
629 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
630 g->closing_branch = NULL;
631 i = 0;
632 first_note = NULL;
633 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
634 insn = NEXT_INSN (insn))
636 if (! INSN_P (insn))
638 if (! first_note && NOTE_P (insn)
639 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
640 first_note = insn;
641 continue;
643 if (JUMP_P (insn))
645 gcc_assert (!g->closing_branch);
646 g->closing_branch = &g->nodes[i];
648 else if (GET_CODE (PATTERN (insn)) == USE)
650 if (! first_note)
651 first_note = insn;
652 continue;
655 g->nodes[i].cuid = i;
656 g->nodes[i].successors = sbitmap_alloc (num_nodes);
657 bitmap_clear (g->nodes[i].successors);
658 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
659 bitmap_clear (g->nodes[i].predecessors);
660 g->nodes[i].first_note = (first_note ? first_note : insn);
661 g->nodes[i++].insn = insn;
662 first_note = NULL;
665 /* We must have found a branch in DDG. */
666 gcc_assert (g->closing_branch);
669 /* Build the data dependency graph. */
670 build_intra_loop_deps (g);
671 build_inter_loop_deps (g);
672 return g;
675 /* Free all the memory allocated for the DDG. */
676 void
677 free_ddg (ddg_ptr g)
679 int i;
681 if (!g)
682 return;
684 for (i = 0; i < g->num_nodes; i++)
686 ddg_edge_ptr e = g->nodes[i].out;
688 while (e)
690 ddg_edge_ptr next = e->next_out;
692 free (e);
693 e = next;
695 sbitmap_free (g->nodes[i].successors);
696 sbitmap_free (g->nodes[i].predecessors);
698 if (g->num_backarcs > 0)
699 free (g->backarcs);
700 free (g->nodes);
701 free (g);
704 void
705 print_ddg_edge (FILE *file, ddg_edge_ptr e)
707 char dep_c;
709 switch (e->type)
711 case OUTPUT_DEP :
712 dep_c = 'O';
713 break;
714 case ANTI_DEP :
715 dep_c = 'A';
716 break;
717 default:
718 dep_c = 'T';
721 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
722 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
725 /* Print the DDG nodes with there in/out edges to the dump file. */
726 void
727 print_ddg (FILE *file, ddg_ptr g)
729 int i;
731 for (i = 0; i < g->num_nodes; i++)
733 ddg_edge_ptr e;
735 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
736 print_rtl_single (file, g->nodes[i].insn);
737 fprintf (file, "OUT ARCS: ");
738 for (e = g->nodes[i].out; e; e = e->next_out)
739 print_ddg_edge (file, e);
741 fprintf (file, "\nIN ARCS: ");
742 for (e = g->nodes[i].in; e; e = e->next_in)
743 print_ddg_edge (file, e);
745 fprintf (file, "\n");
749 /* Print the given DDG in VCG format. */
750 DEBUG_FUNCTION void
751 vcg_print_ddg (FILE *file, ddg_ptr g)
753 int src_cuid;
755 fprintf (file, "graph: {\n");
756 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
758 ddg_edge_ptr e;
759 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
761 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
762 print_rtl_single (file, g->nodes[src_cuid].insn);
763 fprintf (file, "\"}\n");
764 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
766 int dst_uid = INSN_UID (e->dest->insn);
767 int dst_cuid = e->dest->cuid;
769 /* Give the backarcs a different color. */
770 if (e->distance > 0)
771 fprintf (file, "backedge: {color: red ");
772 else
773 fprintf (file, "edge: { ");
775 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
776 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
777 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
780 fprintf (file, "}\n");
783 /* Dump the sccs in SCCS. */
784 void
785 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
787 unsigned int u = 0;
788 sbitmap_iterator sbi;
789 int i;
791 if (!file)
792 return;
794 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
795 for (i = 0; i < sccs->num_sccs; i++)
797 fprintf (file, "SCC number: %d\n", i);
798 EXECUTE_IF_SET_IN_BITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
800 fprintf (file, "insn num %d\n", u);
801 print_rtl_single (file, g->nodes[u].insn);
804 fprintf (file, "\n");
807 /* Create an edge and initialize it with given values. */
808 static ddg_edge_ptr
809 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
810 dep_type t, dep_data_type dt, int l, int d)
812 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
814 e->src = src;
815 e->dest = dest;
816 e->type = t;
817 e->data_type = dt;
818 e->latency = l;
819 e->distance = d;
820 e->next_in = e->next_out = NULL;
821 e->aux.info = 0;
822 return e;
825 /* Add the given edge to the in/out linked lists of the DDG nodes. */
826 static void
827 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
829 ddg_node_ptr src = e->src;
830 ddg_node_ptr dest = e->dest;
832 /* Should have allocated the sbitmaps. */
833 gcc_assert (src->successors && dest->predecessors);
835 bitmap_set_bit (src->successors, dest->cuid);
836 bitmap_set_bit (dest->predecessors, src->cuid);
837 e->next_in = dest->in;
838 dest->in = e;
839 e->next_out = src->out;
840 src->out = e;
845 /* Algorithm for computing the recurrence_length of an scc. We assume at
846 for now that cycles in the data dependence graph contain a single backarc.
847 This simplifies the algorithm, and can be generalized later. */
848 static void
849 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
851 int j;
852 int result = -1;
854 for (j = 0; j < scc->num_backarcs; j++)
856 ddg_edge_ptr backarc = scc->backarcs[j];
857 int length;
858 int distance = backarc->distance;
859 ddg_node_ptr src = backarc->dest;
860 ddg_node_ptr dest = backarc->src;
862 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
863 if (length < 0 )
865 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
866 continue;
868 length += backarc->latency;
869 result = MAX (result, (length / distance));
871 scc->recurrence_length = result;
874 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
875 and mark edges that belong to this scc as IN_SCC. */
876 static ddg_scc_ptr
877 create_scc (ddg_ptr g, sbitmap nodes)
879 ddg_scc_ptr scc;
880 unsigned int u = 0;
881 sbitmap_iterator sbi;
883 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
884 scc->backarcs = NULL;
885 scc->num_backarcs = 0;
886 scc->nodes = sbitmap_alloc (g->num_nodes);
887 bitmap_copy (scc->nodes, nodes);
889 /* Mark the backarcs that belong to this SCC. */
890 EXECUTE_IF_SET_IN_BITMAP (nodes, 0, u, sbi)
892 ddg_edge_ptr e;
893 ddg_node_ptr n = &g->nodes[u];
895 for (e = n->out; e; e = e->next_out)
896 if (bitmap_bit_p (nodes, e->dest->cuid))
898 e->aux.count = IN_SCC;
899 if (e->distance > 0)
900 add_backarc_to_scc (scc, e);
904 set_recurrence_length (scc, g);
905 return scc;
908 /* Cleans the memory allocation of a given SCC. */
909 static void
910 free_scc (ddg_scc_ptr scc)
912 if (!scc)
913 return;
915 sbitmap_free (scc->nodes);
916 if (scc->num_backarcs > 0)
917 free (scc->backarcs);
918 free (scc);
922 /* Add a given edge known to be a backarc to the given DDG. */
923 static void
924 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
926 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
928 add_edge_to_ddg (g, e);
929 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
930 g->backarcs[g->num_backarcs++] = e;
933 /* Add backarc to an SCC. */
934 static void
935 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
937 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
939 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
940 scc->backarcs[scc->num_backarcs++] = e;
943 /* Add the given SCC to the DDG. */
944 static void
945 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
947 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
949 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
950 g->sccs[g->num_sccs++] = scc;
953 /* Given the instruction INSN return the node that represents it. */
954 ddg_node_ptr
955 get_node_of_insn (ddg_ptr g, rtx_insn *insn)
957 int i;
959 for (i = 0; i < g->num_nodes; i++)
960 if (insn == g->nodes[i].insn)
961 return &g->nodes[i];
962 return NULL;
965 /* Given a set OPS of nodes in the DDG, find the set of their successors
966 which are not in OPS, and set their bits in SUCC. Bits corresponding to
967 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
968 void
969 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
971 unsigned int i = 0;
972 sbitmap_iterator sbi;
974 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
976 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
977 bitmap_ior (succ, succ, node_succ);
980 /* We want those that are not in ops. */
981 bitmap_and_compl (succ, succ, ops);
984 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
985 which are not in OPS, and set their bits in PREDS. Bits corresponding to
986 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
987 void
988 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
990 unsigned int i = 0;
991 sbitmap_iterator sbi;
993 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
995 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
996 bitmap_ior (preds, preds, node_preds);
999 /* We want those that are not in ops. */
1000 bitmap_and_compl (preds, preds, ops);
1004 /* Compare function to be passed to qsort to order the backarcs in descending
1005 recMII order. */
1006 static int
1007 compare_sccs (const void *s1, const void *s2)
1009 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
1010 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
1011 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
1015 /* Order the backarcs in descending recMII order using compare_sccs. */
1016 static void
1017 order_sccs (ddg_all_sccs_ptr g)
1019 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
1020 (int (*) (const void *, const void *)) compare_sccs);
1023 #ifdef ENABLE_CHECKING
1024 /* Check that every node in SCCS belongs to exactly one strongly connected
1025 component and that no element of SCCS is empty. */
1026 static void
1027 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
1029 int i = 0;
1030 sbitmap tmp = sbitmap_alloc (num_nodes);
1032 bitmap_clear (tmp);
1033 for (i = 0; i < sccs->num_sccs; i++)
1035 gcc_assert (!bitmap_empty_p (sccs->sccs[i]->nodes));
1036 /* Verify that every node in sccs is in exactly one strongly
1037 connected component. */
1038 gcc_assert (!bitmap_intersect_p (tmp, sccs->sccs[i]->nodes));
1039 bitmap_ior (tmp, tmp, sccs->sccs[i]->nodes);
1041 sbitmap_free (tmp);
1043 #endif
1045 /* Perform the Strongly Connected Components decomposing algorithm on the
1046 DDG and return DDG_ALL_SCCS structure that contains them. */
1047 ddg_all_sccs_ptr
1048 create_ddg_all_sccs (ddg_ptr g)
1050 int i;
1051 int num_nodes = g->num_nodes;
1052 sbitmap from = sbitmap_alloc (num_nodes);
1053 sbitmap to = sbitmap_alloc (num_nodes);
1054 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
1055 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
1056 xmalloc (sizeof (struct ddg_all_sccs));
1058 sccs->ddg = g;
1059 sccs->sccs = NULL;
1060 sccs->num_sccs = 0;
1062 for (i = 0; i < g->num_backarcs; i++)
1064 ddg_scc_ptr scc;
1065 ddg_edge_ptr backarc = g->backarcs[i];
1066 ddg_node_ptr src = backarc->src;
1067 ddg_node_ptr dest = backarc->dest;
1069 /* If the backarc already belongs to an SCC, continue. */
1070 if (backarc->aux.count == IN_SCC)
1071 continue;
1073 bitmap_clear (scc_nodes);
1074 bitmap_clear (from);
1075 bitmap_clear (to);
1076 bitmap_set_bit (from, dest->cuid);
1077 bitmap_set_bit (to, src->cuid);
1079 if (find_nodes_on_paths (scc_nodes, g, from, to))
1081 scc = create_scc (g, scc_nodes);
1082 add_scc_to_ddg (sccs, scc);
1085 order_sccs (sccs);
1086 sbitmap_free (from);
1087 sbitmap_free (to);
1088 sbitmap_free (scc_nodes);
1089 #ifdef ENABLE_CHECKING
1090 check_sccs (sccs, num_nodes);
1091 #endif
1092 return sccs;
1095 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1096 void
1097 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1099 int i;
1101 if (!all_sccs)
1102 return;
1104 for (i = 0; i < all_sccs->num_sccs; i++)
1105 free_scc (all_sccs->sccs[i]);
1107 free (all_sccs->sccs);
1108 free (all_sccs);
1112 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1113 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1114 nodes from FROM and TO). Return nonzero if nodes exist. */
1116 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1118 int answer;
1119 int change;
1120 unsigned int u = 0;
1121 int num_nodes = g->num_nodes;
1122 sbitmap_iterator sbi;
1124 sbitmap workset = sbitmap_alloc (num_nodes);
1125 sbitmap reachable_from = sbitmap_alloc (num_nodes);
1126 sbitmap reach_to = sbitmap_alloc (num_nodes);
1127 sbitmap tmp = sbitmap_alloc (num_nodes);
1129 bitmap_copy (reachable_from, from);
1130 bitmap_copy (tmp, from);
1132 change = 1;
1133 while (change)
1135 change = 0;
1136 bitmap_copy (workset, tmp);
1137 bitmap_clear (tmp);
1138 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1140 ddg_edge_ptr e;
1141 ddg_node_ptr u_node = &g->nodes[u];
1143 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1145 ddg_node_ptr v_node = e->dest;
1146 int v = v_node->cuid;
1148 if (!bitmap_bit_p (reachable_from, v))
1150 bitmap_set_bit (reachable_from, v);
1151 bitmap_set_bit (tmp, v);
1152 change = 1;
1158 bitmap_copy (reach_to, to);
1159 bitmap_copy (tmp, to);
1161 change = 1;
1162 while (change)
1164 change = 0;
1165 bitmap_copy (workset, tmp);
1166 bitmap_clear (tmp);
1167 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1169 ddg_edge_ptr e;
1170 ddg_node_ptr u_node = &g->nodes[u];
1172 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1174 ddg_node_ptr v_node = e->src;
1175 int v = v_node->cuid;
1177 if (!bitmap_bit_p (reach_to, v))
1179 bitmap_set_bit (reach_to, v);
1180 bitmap_set_bit (tmp, v);
1181 change = 1;
1187 answer = bitmap_and (result, reachable_from, reach_to);
1188 sbitmap_free (workset);
1189 sbitmap_free (reachable_from);
1190 sbitmap_free (reach_to);
1191 sbitmap_free (tmp);
1192 return answer;
1196 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1197 at-least as large as the count of U_NODE plus the latency between them.
1198 Sets a bit in TMP for each successor whose count was changed (increased).
1199 Returns nonzero if any count was changed. */
1200 static int
1201 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1203 ddg_edge_ptr e;
1204 int result = 0;
1206 for (e = u_node->out; e; e = e->next_out)
1208 ddg_node_ptr v_node = e->dest;
1209 int v = v_node->cuid;
1211 if (bitmap_bit_p (nodes, v)
1212 && (e->distance == 0)
1213 && (v_node->aux.count < u_node->aux.count + e->latency))
1215 v_node->aux.count = u_node->aux.count + e->latency;
1216 bitmap_set_bit (tmp, v);
1217 result = 1;
1220 return result;
1224 /* Find the length of a longest path from SRC to DEST in G,
1225 going only through NODES, and disregarding backarcs. */
1227 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1229 int i;
1230 unsigned int u = 0;
1231 int change = 1;
1232 int result;
1233 int num_nodes = g->num_nodes;
1234 sbitmap workset = sbitmap_alloc (num_nodes);
1235 sbitmap tmp = sbitmap_alloc (num_nodes);
1238 /* Data will hold the distance of the longest path found so far from
1239 src to each node. Initialize to -1 = less than minimum. */
1240 for (i = 0; i < g->num_nodes; i++)
1241 g->nodes[i].aux.count = -1;
1242 g->nodes[src].aux.count = 0;
1244 bitmap_clear (tmp);
1245 bitmap_set_bit (tmp, src);
1247 while (change)
1249 sbitmap_iterator sbi;
1251 change = 0;
1252 bitmap_copy (workset, tmp);
1253 bitmap_clear (tmp);
1254 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1256 ddg_node_ptr u_node = &g->nodes[u];
1258 change |= update_dist_to_successors (u_node, nodes, tmp);
1261 result = g->nodes[dest].aux.count;
1262 sbitmap_free (workset);
1263 sbitmap_free (tmp);
1264 return result;
1267 #endif /* INSN_SCHEDULING */