2015-09-25 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / ddg.c
blobada465725cbe386c8e1beaaea7777c00dcb99a2a
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 "backend.h"
26 #include "tree.h"
27 #include "rtl.h"
28 #include "df.h"
29 #include "diagnostic-core.h"
30 #include "tm_p.h"
31 #include "regs.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 "alias.h"
41 #include "expmed.h"
42 #include "dojump.h"
43 #include "explow.h"
44 #include "calls.h"
45 #include "emit-rtl.h"
46 #include "varasm.h"
47 #include "stmt.h"
48 #include "expr.h"
49 #include "ddg.h"
50 #include "rtl-iter.h"
52 #ifdef INSN_SCHEDULING
54 /* A flag indicating that a ddg edge belongs to an SCC or not. */
55 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
57 /* Forward declarations. */
58 static void add_backarc_to_ddg (ddg_ptr, ddg_edge_ptr);
59 static void add_backarc_to_scc (ddg_scc_ptr, ddg_edge_ptr);
60 static void add_scc_to_ddg (ddg_all_sccs_ptr, ddg_scc_ptr);
61 static void create_ddg_dep_from_intra_loop_link (ddg_ptr, ddg_node_ptr,
62 ddg_node_ptr, dep_t);
63 static void create_ddg_dep_no_link (ddg_ptr, ddg_node_ptr, ddg_node_ptr,
64 dep_type, dep_data_type, int);
65 static ddg_edge_ptr create_ddg_edge (ddg_node_ptr, ddg_node_ptr, dep_type,
66 dep_data_type, int, int);
67 static void add_edge_to_ddg (ddg_ptr g, ddg_edge_ptr);
69 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p. */
70 static bool mem_ref_p;
72 /* Auxiliary function for mem_read_insn_p. */
73 static void
74 mark_mem_use (rtx *x, void *)
76 subrtx_iterator::array_type array;
77 FOR_EACH_SUBRTX (iter, array, *x, NONCONST)
78 if (MEM_P (*iter))
80 mem_ref_p = true;
81 break;
85 /* Returns nonzero if INSN reads from memory. */
86 static bool
87 mem_read_insn_p (rtx_insn *insn)
89 mem_ref_p = false;
90 note_uses (&PATTERN (insn), mark_mem_use, NULL);
91 return mem_ref_p;
94 static void
95 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
97 if (MEM_P (loc))
98 mem_ref_p = true;
101 /* Returns nonzero if INSN writes to memory. */
102 static bool
103 mem_write_insn_p (rtx_insn *insn)
105 mem_ref_p = false;
106 note_stores (PATTERN (insn), mark_mem_store, NULL);
107 return mem_ref_p;
110 /* Returns nonzero if X has access to memory. */
111 static bool
112 rtx_mem_access_p (rtx x)
114 int i, j;
115 const char *fmt;
116 enum rtx_code code;
118 if (x == 0)
119 return false;
121 if (MEM_P (x))
122 return true;
124 code = GET_CODE (x);
125 fmt = GET_RTX_FORMAT (code);
126 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
128 if (fmt[i] == 'e')
130 if (rtx_mem_access_p (XEXP (x, i)))
131 return true;
133 else if (fmt[i] == 'E')
134 for (j = 0; j < XVECLEN (x, i); j++)
136 if (rtx_mem_access_p (XVECEXP (x, i, j)))
137 return true;
140 return false;
143 /* Returns nonzero if INSN reads to or writes from memory. */
144 static bool
145 mem_access_insn_p (rtx_insn *insn)
147 return rtx_mem_access_p (PATTERN (insn));
150 /* Return true if DEF_INSN contains address being auto-inc or auto-dec
151 which is used in USE_INSN. Otherwise return false. The result is
152 being used to decide whether to remove the edge between def_insn and
153 use_insn when -fmodulo-sched-allow-regmoves is set. This function
154 doesn't need to consider the specific address register; no reg_moves
155 will be allowed for any life range defined by def_insn and used
156 by use_insn, if use_insn uses an address register auto-inc'ed by
157 def_insn. */
158 bool
159 autoinc_var_is_used_p (rtx_insn *def_insn, rtx_insn *use_insn)
161 rtx note;
163 for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
164 if (REG_NOTE_KIND (note) == REG_INC
165 && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
166 return true;
168 return false;
171 /* Return true if one of the definitions in INSN has MODE_CC. Otherwise
172 return false. */
173 static bool
174 def_has_ccmode_p (rtx_insn *insn)
176 df_ref def;
178 FOR_EACH_INSN_DEF (def, insn)
180 machine_mode mode = GET_MODE (DF_REF_REG (def));
182 if (GET_MODE_CLASS (mode) == MODE_CC)
183 return true;
186 return false;
189 /* Computes the dependence parameters (latency, distance etc.), creates
190 a ddg_edge and adds it to the given DDG. */
191 static void
192 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
193 ddg_node_ptr dest_node, dep_t link)
195 ddg_edge_ptr e;
196 int latency, distance = 0;
197 dep_type t = TRUE_DEP;
198 dep_data_type dt = (mem_access_insn_p (src_node->insn)
199 && mem_access_insn_p (dest_node->insn) ? MEM_DEP
200 : REG_DEP);
201 gcc_assert (src_node->cuid < dest_node->cuid);
202 gcc_assert (link);
204 /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!! */
205 if (DEP_TYPE (link) == REG_DEP_ANTI)
206 t = ANTI_DEP;
207 else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
208 t = OUTPUT_DEP;
210 gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
211 gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
213 /* We currently choose not to create certain anti-deps edges and
214 compensate for that by generating reg-moves based on the life-range
215 analysis. The anti-deps that will be deleted are the ones which
216 have true-deps edges in the opposite direction (in other words
217 the kernel has only one def of the relevant register).
218 If the address that is being auto-inc or auto-dec in DEST_NODE
219 is used in SRC_NODE then do not remove the edge to make sure
220 reg-moves will not be created for this address.
221 TODO: support the removal of all anti-deps edges, i.e. including those
222 whose register has multiple defs in the loop. */
223 if (flag_modulo_sched_allow_regmoves
224 && (t == ANTI_DEP && dt == REG_DEP)
225 && !def_has_ccmode_p (dest_node->insn)
226 && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
228 rtx set;
230 set = single_set (dest_node->insn);
231 /* TODO: Handle registers that REG_P is not true for them, i.e.
232 subregs and special registers. */
233 if (set && REG_P (SET_DEST (set)))
235 int regno = REGNO (SET_DEST (set));
236 df_ref first_def;
237 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
239 first_def = df_bb_regno_first_def_find (g->bb, regno);
240 gcc_assert (first_def);
242 if (bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def)))
243 return;
247 latency = dep_cost (link);
248 e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
249 add_edge_to_ddg (g, e);
252 /* The same as the above function, but it doesn't require a link parameter. */
253 static void
254 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
255 dep_type d_t, dep_data_type d_dt, int distance)
257 ddg_edge_ptr e;
258 int l;
259 enum reg_note dep_kind;
260 struct _dep _dep, *dep = &_dep;
262 gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
263 gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
265 if (d_t == ANTI_DEP)
266 dep_kind = REG_DEP_ANTI;
267 else if (d_t == OUTPUT_DEP)
268 dep_kind = REG_DEP_OUTPUT;
269 else
271 gcc_assert (d_t == TRUE_DEP);
273 dep_kind = REG_DEP_TRUE;
276 init_dep (dep, from->insn, to->insn, dep_kind);
278 l = dep_cost (dep);
280 e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
281 if (distance > 0)
282 add_backarc_to_ddg (g, e);
283 else
284 add_edge_to_ddg (g, e);
288 /* Given a downwards exposed register def LAST_DEF (which is the last
289 definition of that register in the bb), add inter-loop true dependences
290 to all its uses in the next iteration, an output dependence to the
291 first def of the same register (possibly itself) in the next iteration
292 and anti-dependences from its uses in the current iteration to the
293 first definition in the next iteration. */
294 static void
295 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
297 int regno = DF_REF_REGNO (last_def);
298 struct df_link *r_use;
299 int has_use_in_bb_p = false;
300 rtx_insn *def_insn = DF_REF_INSN (last_def);
301 ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
302 ddg_node_ptr use_node;
303 #ifdef ENABLE_CHECKING
304 struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
305 #endif
306 df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
308 gcc_assert (last_def_node);
309 gcc_assert (first_def);
311 #ifdef ENABLE_CHECKING
312 if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
313 gcc_assert (!bitmap_bit_p (&bb_info->gen,
314 DF_REF_ID (first_def)));
315 #endif
317 /* Create inter-loop true dependences and anti dependences. */
318 for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
320 rtx_insn *use_insn = DF_REF_INSN (r_use->ref);
322 if (BLOCK_FOR_INSN (use_insn) != g->bb)
323 continue;
325 /* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
326 use_node = get_node_of_insn (g, use_insn);
327 gcc_assert (use_node);
328 has_use_in_bb_p = true;
329 if (use_node->cuid <= last_def_node->cuid)
331 /* Add true deps from last_def to it's uses in the next
332 iteration. Any such upwards exposed use appears before
333 the last_def def. */
334 create_ddg_dep_no_link (g, last_def_node, use_node,
335 DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
336 REG_DEP, 1);
338 else if (!DEBUG_INSN_P (use_insn))
340 /* Add anti deps from last_def's uses in the current iteration
341 to the first def in the next iteration. We do not add ANTI
342 dep when there is an intra-loop TRUE dep in the opposite
343 direction, but use regmoves to fix such disregarded ANTI
344 deps when broken. If the first_def reaches the USE then
345 there is such a dep. */
346 ddg_node_ptr first_def_node = get_node_of_insn (g,
347 DF_REF_INSN (first_def));
349 gcc_assert (first_def_node);
351 /* Always create the edge if the use node is a branch in
352 order to prevent the creation of reg-moves.
353 If the address that is being auto-inc or auto-dec in LAST_DEF
354 is used in USE_INSN then do not remove the edge to make sure
355 reg-moves will not be created for that address. */
356 if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
357 || !flag_modulo_sched_allow_regmoves
358 || JUMP_P (use_node->insn)
359 || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
360 || def_has_ccmode_p (DF_REF_INSN (last_def)))
361 create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
362 REG_DEP, 1);
366 /* Create an inter-loop output dependence between LAST_DEF (which is the
367 last def in its block, being downwards exposed) and the first def in
368 its block. Avoid creating a self output dependence. Avoid creating
369 an output dependence if there is a dependence path between the two
370 defs starting with a true dependence to a use which can be in the
371 next iteration; followed by an anti dependence of that use to the
372 first def (i.e. if there is a use between the two defs.) */
373 if (!has_use_in_bb_p)
375 ddg_node_ptr dest_node;
377 if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
378 return;
380 dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
381 gcc_assert (dest_node);
382 create_ddg_dep_no_link (g, last_def_node, dest_node,
383 OUTPUT_DEP, REG_DEP, 1);
386 /* Build inter-loop dependencies, by looking at DF analysis backwards. */
387 static void
388 build_inter_loop_deps (ddg_ptr g)
390 unsigned rd_num;
391 struct df_rd_bb_info *rd_bb_info;
392 bitmap_iterator bi;
394 rd_bb_info = DF_RD_BB_INFO (g->bb);
396 /* Find inter-loop register output, true and anti deps. */
397 EXECUTE_IF_SET_IN_BITMAP (&rd_bb_info->gen, 0, rd_num, bi)
399 df_ref rd = DF_DEFS_GET (rd_num);
401 add_cross_iteration_register_deps (g, rd);
406 /* Return true if two specified instructions have mem expr with conflict
407 alias sets. */
408 static bool
409 insns_may_alias_p (rtx_insn *insn1, rtx_insn *insn2)
411 subrtx_iterator::array_type array1;
412 subrtx_iterator::array_type array2;
413 FOR_EACH_SUBRTX (iter1, array1, PATTERN (insn1), NONCONST)
415 const_rtx x1 = *iter1;
416 if (MEM_P (x1))
417 FOR_EACH_SUBRTX (iter2, array2, PATTERN (insn2), NONCONST)
419 const_rtx x2 = *iter2;
420 if (MEM_P (x2) && may_alias_p (x2, x1))
421 return true;
424 return false;
427 /* Given two nodes, analyze their RTL insns and add intra-loop mem deps
428 to ddg G. */
429 static void
430 add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
433 if ((from->cuid == to->cuid)
434 || !insns_may_alias_p (from->insn, to->insn))
435 /* Do not create edge if memory references have disjoint alias sets
436 or 'to' and 'from' are the same instruction. */
437 return;
439 if (mem_write_insn_p (from->insn))
441 if (mem_read_insn_p (to->insn))
442 create_ddg_dep_no_link (g, from, to,
443 DEBUG_INSN_P (to->insn)
444 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
445 else
446 create_ddg_dep_no_link (g, from, to,
447 DEBUG_INSN_P (to->insn)
448 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
450 else if (!mem_read_insn_p (to->insn))
451 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
454 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
455 to ddg G. */
456 static void
457 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
459 if (!insns_may_alias_p (from->insn, to->insn))
460 /* Do not create edge if memory references have disjoint alias sets. */
461 return;
463 if (mem_write_insn_p (from->insn))
465 if (mem_read_insn_p (to->insn))
466 create_ddg_dep_no_link (g, from, to,
467 DEBUG_INSN_P (to->insn)
468 ? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
469 else if (from->cuid != to->cuid)
470 create_ddg_dep_no_link (g, from, to,
471 DEBUG_INSN_P (to->insn)
472 ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
474 else
476 if (mem_read_insn_p (to->insn))
477 return;
478 else if (from->cuid != to->cuid)
480 create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
481 if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
482 create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
483 else
484 create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
490 /* Perform intra-block Data Dependency analysis and connect the nodes in
491 the DDG. We assume the loop has a single basic block. */
492 static void
493 build_intra_loop_deps (ddg_ptr g)
495 int i;
496 /* Hold the dependency analysis state during dependency calculations. */
497 struct deps_desc tmp_deps;
498 rtx_insn *head, *tail;
500 /* Build the dependence information, using the sched_analyze function. */
501 init_deps_global ();
502 init_deps (&tmp_deps, false);
504 /* Do the intra-block data dependence analysis for the given block. */
505 get_ebb_head_tail (g->bb, g->bb, &head, &tail);
506 sched_analyze (&tmp_deps, head, tail);
508 /* Build intra-loop data dependencies using the scheduler dependency
509 analysis. */
510 for (i = 0; i < g->num_nodes; i++)
512 ddg_node_ptr dest_node = &g->nodes[i];
513 sd_iterator_def sd_it;
514 dep_t dep;
516 if (! INSN_P (dest_node->insn))
517 continue;
519 FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
521 rtx_insn *src_insn = DEP_PRO (dep);
522 ddg_node_ptr src_node;
524 /* Don't add dependencies on debug insns to non-debug insns
525 to avoid codegen differences between -g and -g0. */
526 if (DEBUG_INSN_P (src_insn) && !DEBUG_INSN_P (dest_node->insn))
527 continue;
529 src_node = get_node_of_insn (g, src_insn);
531 if (!src_node)
532 continue;
534 create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
537 /* If this insn modifies memory, add an edge to all insns that access
538 memory. */
539 if (mem_access_insn_p (dest_node->insn))
541 int j;
543 for (j = 0; j <= i; j++)
545 ddg_node_ptr j_node = &g->nodes[j];
546 if (DEBUG_INSN_P (j_node->insn))
547 continue;
548 if (mem_access_insn_p (j_node->insn))
550 /* Don't bother calculating inter-loop dep if an intra-loop dep
551 already exists. */
552 if (! bitmap_bit_p (dest_node->successors, j))
553 add_inter_loop_mem_dep (g, dest_node, j_node);
554 /* If -fmodulo-sched-allow-regmoves
555 is set certain anti-dep edges are not created.
556 It might be that these anti-dep edges are on the
557 path from one memory instruction to another such that
558 removing these edges could cause a violation of the
559 memory dependencies. Thus we add intra edges between
560 every two memory instructions in this case. */
561 if (flag_modulo_sched_allow_regmoves
562 && !bitmap_bit_p (dest_node->predecessors, j))
563 add_intra_loop_mem_dep (g, j_node, dest_node);
569 /* Free the INSN_LISTs. */
570 finish_deps_global ();
571 free_deps (&tmp_deps);
573 /* Free dependencies. */
574 sched_free_deps (head, tail, false);
578 /* Given a basic block, create its DDG and return a pointer to a variable
579 of ddg type that represents it.
580 Initialize the ddg structure fields to the appropriate values. */
581 ddg_ptr
582 create_ddg (basic_block bb, int closing_branch_deps)
584 ddg_ptr g;
585 rtx_insn *insn, *first_note;
586 int i;
587 int num_nodes = 0;
589 g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
591 g->bb = bb;
592 g->closing_branch_deps = closing_branch_deps;
594 /* Count the number of insns in the BB. */
595 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
596 insn = NEXT_INSN (insn))
598 if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
599 continue;
601 if (DEBUG_INSN_P (insn))
602 g->num_debug++;
603 else
605 if (mem_read_insn_p (insn))
606 g->num_loads++;
607 if (mem_write_insn_p (insn))
608 g->num_stores++;
610 num_nodes++;
613 /* There is nothing to do for this BB. */
614 if ((num_nodes - g->num_debug) <= 1)
616 free (g);
617 return NULL;
620 /* Allocate the nodes array, and initialize the nodes. */
621 g->num_nodes = num_nodes;
622 g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
623 g->closing_branch = NULL;
624 i = 0;
625 first_note = NULL;
626 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
627 insn = NEXT_INSN (insn))
629 if (! INSN_P (insn))
631 if (! first_note && NOTE_P (insn)
632 && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
633 first_note = insn;
634 continue;
636 if (JUMP_P (insn))
638 gcc_assert (!g->closing_branch);
639 g->closing_branch = &g->nodes[i];
641 else if (GET_CODE (PATTERN (insn)) == USE)
643 if (! first_note)
644 first_note = insn;
645 continue;
648 g->nodes[i].cuid = i;
649 g->nodes[i].successors = sbitmap_alloc (num_nodes);
650 bitmap_clear (g->nodes[i].successors);
651 g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
652 bitmap_clear (g->nodes[i].predecessors);
653 g->nodes[i].first_note = (first_note ? first_note : insn);
654 g->nodes[i++].insn = insn;
655 first_note = NULL;
658 /* We must have found a branch in DDG. */
659 gcc_assert (g->closing_branch);
662 /* Build the data dependency graph. */
663 build_intra_loop_deps (g);
664 build_inter_loop_deps (g);
665 return g;
668 /* Free all the memory allocated for the DDG. */
669 void
670 free_ddg (ddg_ptr g)
672 int i;
674 if (!g)
675 return;
677 for (i = 0; i < g->num_nodes; i++)
679 ddg_edge_ptr e = g->nodes[i].out;
681 while (e)
683 ddg_edge_ptr next = e->next_out;
685 free (e);
686 e = next;
688 sbitmap_free (g->nodes[i].successors);
689 sbitmap_free (g->nodes[i].predecessors);
691 if (g->num_backarcs > 0)
692 free (g->backarcs);
693 free (g->nodes);
694 free (g);
697 void
698 print_ddg_edge (FILE *file, ddg_edge_ptr e)
700 char dep_c;
702 switch (e->type)
704 case OUTPUT_DEP :
705 dep_c = 'O';
706 break;
707 case ANTI_DEP :
708 dep_c = 'A';
709 break;
710 default:
711 dep_c = 'T';
714 fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
715 dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
718 /* Print the DDG nodes with there in/out edges to the dump file. */
719 void
720 print_ddg (FILE *file, ddg_ptr g)
722 int i;
724 for (i = 0; i < g->num_nodes; i++)
726 ddg_edge_ptr e;
728 fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
729 print_rtl_single (file, g->nodes[i].insn);
730 fprintf (file, "OUT ARCS: ");
731 for (e = g->nodes[i].out; e; e = e->next_out)
732 print_ddg_edge (file, e);
734 fprintf (file, "\nIN ARCS: ");
735 for (e = g->nodes[i].in; e; e = e->next_in)
736 print_ddg_edge (file, e);
738 fprintf (file, "\n");
742 /* Print the given DDG in VCG format. */
743 DEBUG_FUNCTION void
744 vcg_print_ddg (FILE *file, ddg_ptr g)
746 int src_cuid;
748 fprintf (file, "graph: {\n");
749 for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
751 ddg_edge_ptr e;
752 int src_uid = INSN_UID (g->nodes[src_cuid].insn);
754 fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
755 print_rtl_single (file, g->nodes[src_cuid].insn);
756 fprintf (file, "\"}\n");
757 for (e = g->nodes[src_cuid].out; e; e = e->next_out)
759 int dst_uid = INSN_UID (e->dest->insn);
760 int dst_cuid = e->dest->cuid;
762 /* Give the backarcs a different color. */
763 if (e->distance > 0)
764 fprintf (file, "backedge: {color: red ");
765 else
766 fprintf (file, "edge: { ");
768 fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
769 fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
770 fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
773 fprintf (file, "}\n");
776 /* Dump the sccs in SCCS. */
777 void
778 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
780 unsigned int u = 0;
781 sbitmap_iterator sbi;
782 int i;
784 if (!file)
785 return;
787 fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
788 for (i = 0; i < sccs->num_sccs; i++)
790 fprintf (file, "SCC number: %d\n", i);
791 EXECUTE_IF_SET_IN_BITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
793 fprintf (file, "insn num %d\n", u);
794 print_rtl_single (file, g->nodes[u].insn);
797 fprintf (file, "\n");
800 /* Create an edge and initialize it with given values. */
801 static ddg_edge_ptr
802 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
803 dep_type t, dep_data_type dt, int l, int d)
805 ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
807 e->src = src;
808 e->dest = dest;
809 e->type = t;
810 e->data_type = dt;
811 e->latency = l;
812 e->distance = d;
813 e->next_in = e->next_out = NULL;
814 e->aux.info = 0;
815 return e;
818 /* Add the given edge to the in/out linked lists of the DDG nodes. */
819 static void
820 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
822 ddg_node_ptr src = e->src;
823 ddg_node_ptr dest = e->dest;
825 /* Should have allocated the sbitmaps. */
826 gcc_assert (src->successors && dest->predecessors);
828 bitmap_set_bit (src->successors, dest->cuid);
829 bitmap_set_bit (dest->predecessors, src->cuid);
830 e->next_in = dest->in;
831 dest->in = e;
832 e->next_out = src->out;
833 src->out = e;
838 /* Algorithm for computing the recurrence_length of an scc. We assume at
839 for now that cycles in the data dependence graph contain a single backarc.
840 This simplifies the algorithm, and can be generalized later. */
841 static void
842 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
844 int j;
845 int result = -1;
847 for (j = 0; j < scc->num_backarcs; j++)
849 ddg_edge_ptr backarc = scc->backarcs[j];
850 int length;
851 int distance = backarc->distance;
852 ddg_node_ptr src = backarc->dest;
853 ddg_node_ptr dest = backarc->src;
855 length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
856 if (length < 0 )
858 /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
859 continue;
861 length += backarc->latency;
862 result = MAX (result, (length / distance));
864 scc->recurrence_length = result;
867 /* Create a new SCC given the set of its nodes. Compute its recurrence_length
868 and mark edges that belong to this scc as IN_SCC. */
869 static ddg_scc_ptr
870 create_scc (ddg_ptr g, sbitmap nodes)
872 ddg_scc_ptr scc;
873 unsigned int u = 0;
874 sbitmap_iterator sbi;
876 scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
877 scc->backarcs = NULL;
878 scc->num_backarcs = 0;
879 scc->nodes = sbitmap_alloc (g->num_nodes);
880 bitmap_copy (scc->nodes, nodes);
882 /* Mark the backarcs that belong to this SCC. */
883 EXECUTE_IF_SET_IN_BITMAP (nodes, 0, u, sbi)
885 ddg_edge_ptr e;
886 ddg_node_ptr n = &g->nodes[u];
888 for (e = n->out; e; e = e->next_out)
889 if (bitmap_bit_p (nodes, e->dest->cuid))
891 e->aux.count = IN_SCC;
892 if (e->distance > 0)
893 add_backarc_to_scc (scc, e);
897 set_recurrence_length (scc, g);
898 return scc;
901 /* Cleans the memory allocation of a given SCC. */
902 static void
903 free_scc (ddg_scc_ptr scc)
905 if (!scc)
906 return;
908 sbitmap_free (scc->nodes);
909 if (scc->num_backarcs > 0)
910 free (scc->backarcs);
911 free (scc);
915 /* Add a given edge known to be a backarc to the given DDG. */
916 static void
917 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
919 int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
921 add_edge_to_ddg (g, e);
922 g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
923 g->backarcs[g->num_backarcs++] = e;
926 /* Add backarc to an SCC. */
927 static void
928 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
930 int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
932 scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
933 scc->backarcs[scc->num_backarcs++] = e;
936 /* Add the given SCC to the DDG. */
937 static void
938 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
940 int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
942 g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
943 g->sccs[g->num_sccs++] = scc;
946 /* Given the instruction INSN return the node that represents it. */
947 ddg_node_ptr
948 get_node_of_insn (ddg_ptr g, rtx_insn *insn)
950 int i;
952 for (i = 0; i < g->num_nodes; i++)
953 if (insn == g->nodes[i].insn)
954 return &g->nodes[i];
955 return NULL;
958 /* Given a set OPS of nodes in the DDG, find the set of their successors
959 which are not in OPS, and set their bits in SUCC. Bits corresponding to
960 OPS are cleared from SUCC. Leaves the other bits in SUCC unchanged. */
961 void
962 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
964 unsigned int i = 0;
965 sbitmap_iterator sbi;
967 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
969 const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
970 bitmap_ior (succ, succ, node_succ);
973 /* We want those that are not in ops. */
974 bitmap_and_compl (succ, succ, ops);
977 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
978 which are not in OPS, and set their bits in PREDS. Bits corresponding to
979 OPS are cleared from PREDS. Leaves the other bits in PREDS unchanged. */
980 void
981 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
983 unsigned int i = 0;
984 sbitmap_iterator sbi;
986 EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi)
988 const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
989 bitmap_ior (preds, preds, node_preds);
992 /* We want those that are not in ops. */
993 bitmap_and_compl (preds, preds, ops);
997 /* Compare function to be passed to qsort to order the backarcs in descending
998 recMII order. */
999 static int
1000 compare_sccs (const void *s1, const void *s2)
1002 const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
1003 const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
1004 return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
1008 /* Order the backarcs in descending recMII order using compare_sccs. */
1009 static void
1010 order_sccs (ddg_all_sccs_ptr g)
1012 qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
1013 (int (*) (const void *, const void *)) compare_sccs);
1016 #ifdef ENABLE_CHECKING
1017 /* Check that every node in SCCS belongs to exactly one strongly connected
1018 component and that no element of SCCS is empty. */
1019 static void
1020 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
1022 int i = 0;
1023 sbitmap tmp = sbitmap_alloc (num_nodes);
1025 bitmap_clear (tmp);
1026 for (i = 0; i < sccs->num_sccs; i++)
1028 gcc_assert (!bitmap_empty_p (sccs->sccs[i]->nodes));
1029 /* Verify that every node in sccs is in exactly one strongly
1030 connected component. */
1031 gcc_assert (!bitmap_intersect_p (tmp, sccs->sccs[i]->nodes));
1032 bitmap_ior (tmp, tmp, sccs->sccs[i]->nodes);
1034 sbitmap_free (tmp);
1036 #endif
1038 /* Perform the Strongly Connected Components decomposing algorithm on the
1039 DDG and return DDG_ALL_SCCS structure that contains them. */
1040 ddg_all_sccs_ptr
1041 create_ddg_all_sccs (ddg_ptr g)
1043 int i;
1044 int num_nodes = g->num_nodes;
1045 sbitmap from = sbitmap_alloc (num_nodes);
1046 sbitmap to = sbitmap_alloc (num_nodes);
1047 sbitmap scc_nodes = sbitmap_alloc (num_nodes);
1048 ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
1049 xmalloc (sizeof (struct ddg_all_sccs));
1051 sccs->ddg = g;
1052 sccs->sccs = NULL;
1053 sccs->num_sccs = 0;
1055 for (i = 0; i < g->num_backarcs; i++)
1057 ddg_scc_ptr scc;
1058 ddg_edge_ptr backarc = g->backarcs[i];
1059 ddg_node_ptr src = backarc->src;
1060 ddg_node_ptr dest = backarc->dest;
1062 /* If the backarc already belongs to an SCC, continue. */
1063 if (backarc->aux.count == IN_SCC)
1064 continue;
1066 bitmap_clear (scc_nodes);
1067 bitmap_clear (from);
1068 bitmap_clear (to);
1069 bitmap_set_bit (from, dest->cuid);
1070 bitmap_set_bit (to, src->cuid);
1072 if (find_nodes_on_paths (scc_nodes, g, from, to))
1074 scc = create_scc (g, scc_nodes);
1075 add_scc_to_ddg (sccs, scc);
1078 order_sccs (sccs);
1079 sbitmap_free (from);
1080 sbitmap_free (to);
1081 sbitmap_free (scc_nodes);
1082 #ifdef ENABLE_CHECKING
1083 check_sccs (sccs, num_nodes);
1084 #endif
1085 return sccs;
1088 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG. */
1089 void
1090 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
1092 int i;
1094 if (!all_sccs)
1095 return;
1097 for (i = 0; i < all_sccs->num_sccs; i++)
1098 free_scc (all_sccs->sccs[i]);
1100 free (all_sccs->sccs);
1101 free (all_sccs);
1105 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
1106 nodes - find all nodes that lie on paths from FROM to TO (not excluding
1107 nodes from FROM and TO). Return nonzero if nodes exist. */
1109 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
1111 int answer;
1112 int change;
1113 unsigned int u = 0;
1114 int num_nodes = g->num_nodes;
1115 sbitmap_iterator sbi;
1117 sbitmap workset = sbitmap_alloc (num_nodes);
1118 sbitmap reachable_from = sbitmap_alloc (num_nodes);
1119 sbitmap reach_to = sbitmap_alloc (num_nodes);
1120 sbitmap tmp = sbitmap_alloc (num_nodes);
1122 bitmap_copy (reachable_from, from);
1123 bitmap_copy (tmp, from);
1125 change = 1;
1126 while (change)
1128 change = 0;
1129 bitmap_copy (workset, tmp);
1130 bitmap_clear (tmp);
1131 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1133 ddg_edge_ptr e;
1134 ddg_node_ptr u_node = &g->nodes[u];
1136 for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1138 ddg_node_ptr v_node = e->dest;
1139 int v = v_node->cuid;
1141 if (!bitmap_bit_p (reachable_from, v))
1143 bitmap_set_bit (reachable_from, v);
1144 bitmap_set_bit (tmp, v);
1145 change = 1;
1151 bitmap_copy (reach_to, to);
1152 bitmap_copy (tmp, to);
1154 change = 1;
1155 while (change)
1157 change = 0;
1158 bitmap_copy (workset, tmp);
1159 bitmap_clear (tmp);
1160 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1162 ddg_edge_ptr e;
1163 ddg_node_ptr u_node = &g->nodes[u];
1165 for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1167 ddg_node_ptr v_node = e->src;
1168 int v = v_node->cuid;
1170 if (!bitmap_bit_p (reach_to, v))
1172 bitmap_set_bit (reach_to, v);
1173 bitmap_set_bit (tmp, v);
1174 change = 1;
1180 answer = bitmap_and (result, reachable_from, reach_to);
1181 sbitmap_free (workset);
1182 sbitmap_free (reachable_from);
1183 sbitmap_free (reach_to);
1184 sbitmap_free (tmp);
1185 return answer;
1189 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1190 at-least as large as the count of U_NODE plus the latency between them.
1191 Sets a bit in TMP for each successor whose count was changed (increased).
1192 Returns nonzero if any count was changed. */
1193 static int
1194 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1196 ddg_edge_ptr e;
1197 int result = 0;
1199 for (e = u_node->out; e; e = e->next_out)
1201 ddg_node_ptr v_node = e->dest;
1202 int v = v_node->cuid;
1204 if (bitmap_bit_p (nodes, v)
1205 && (e->distance == 0)
1206 && (v_node->aux.count < u_node->aux.count + e->latency))
1208 v_node->aux.count = u_node->aux.count + e->latency;
1209 bitmap_set_bit (tmp, v);
1210 result = 1;
1213 return result;
1217 /* Find the length of a longest path from SRC to DEST in G,
1218 going only through NODES, and disregarding backarcs. */
1220 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1222 int i;
1223 unsigned int u = 0;
1224 int change = 1;
1225 int result;
1226 int num_nodes = g->num_nodes;
1227 sbitmap workset = sbitmap_alloc (num_nodes);
1228 sbitmap tmp = sbitmap_alloc (num_nodes);
1231 /* Data will hold the distance of the longest path found so far from
1232 src to each node. Initialize to -1 = less than minimum. */
1233 for (i = 0; i < g->num_nodes; i++)
1234 g->nodes[i].aux.count = -1;
1235 g->nodes[src].aux.count = 0;
1237 bitmap_clear (tmp);
1238 bitmap_set_bit (tmp, src);
1240 while (change)
1242 sbitmap_iterator sbi;
1244 change = 0;
1245 bitmap_copy (workset, tmp);
1246 bitmap_clear (tmp);
1247 EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi)
1249 ddg_node_ptr u_node = &g->nodes[u];
1251 change |= update_dist_to_successors (u_node, nodes, tmp);
1254 result = g->nodes[dest].aux.count;
1255 sbitmap_free (workset);
1256 sbitmap_free (tmp);
1257 return result;
1260 #endif /* INSN_SCHEDULING */