xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/ddg.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /* DDG - Data Dependence Graph implementation.
2    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4    Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
5 
6 This file is part of GCC.
7 
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.
12 
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.
17 
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/>.  */
21 
22 
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "toplev.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"
46 
47 #ifdef INSN_SCHEDULING
48 
49 /* A flag indicating that a ddg edge belongs to an SCC or not.  */
50 enum edge_flag {NOT_IN_SCC = 0, IN_SCC};
51 
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);
63 
64 /* Auxiliary variable for mem_read_insn_p/mem_write_insn_p.  */
65 static bool mem_ref_p;
66 
67 /* Auxiliary function for mem_read_insn_p.  */
68 static int
69 mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED)
70 {
71   if (MEM_P (*x))
72     mem_ref_p = true;
73   return 0;
74 }
75 
76 /* Auxiliary function for mem_read_insn_p.  */
77 static void
78 mark_mem_use_1 (rtx *x, void *data)
79 {
80   for_each_rtx (x, mark_mem_use, data);
81 }
82 
83 /* Returns nonzero if INSN reads from memory.  */
84 static bool
85 mem_read_insn_p (rtx insn)
86 {
87   mem_ref_p = false;
88   note_uses (&PATTERN (insn), mark_mem_use_1, NULL);
89   return mem_ref_p;
90 }
91 
92 static void
93 mark_mem_store (rtx loc, const_rtx setter ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
94 {
95   if (MEM_P (loc))
96     mem_ref_p = true;
97 }
98 
99 /* Returns nonzero if INSN writes to memory.  */
100 static bool
101 mem_write_insn_p (rtx insn)
102 {
103   mem_ref_p = false;
104   note_stores (PATTERN (insn), mark_mem_store, NULL);
105   return mem_ref_p;
106 }
107 
108 /* Returns nonzero if X has access to memory.  */
109 static bool
110 rtx_mem_access_p (rtx x)
111 {
112   int i, j;
113   const char *fmt;
114   enum rtx_code code;
115 
116   if (x == 0)
117     return false;
118 
119   if (MEM_P (x))
120     return true;
121 
122   code = GET_CODE (x);
123   fmt = GET_RTX_FORMAT (code);
124   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
125     {
126       if (fmt[i] == 'e')
127 	{
128 	  if (rtx_mem_access_p (XEXP (x, i)))
129             return true;
130         }
131       else if (fmt[i] == 'E')
132 	for (j = 0; j < XVECLEN (x, i); j++)
133 	  {
134 	    if (rtx_mem_access_p (XVECEXP (x, i, j)))
135               return true;
136           }
137     }
138   return false;
139 }
140 
141 /* Returns nonzero if INSN reads to or writes from memory.  */
142 static bool
143 mem_access_insn_p (rtx insn)
144 {
145   return rtx_mem_access_p (PATTERN (insn));
146 }
147 
148 /* Computes the dependence parameters (latency, distance etc.), creates
149    a ddg_edge and adds it to the given DDG.  */
150 static void
151 create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
152                                      ddg_node_ptr dest_node, dep_t link)
153 {
154   ddg_edge_ptr e;
155   int latency, distance = 0;
156   dep_type t = TRUE_DEP;
157   dep_data_type dt = (mem_access_insn_p (src_node->insn)
158 		      && mem_access_insn_p (dest_node->insn) ? MEM_DEP
159 							     : REG_DEP);
160   gcc_assert (src_node->cuid < dest_node->cuid);
161   gcc_assert (link);
162 
163   /* Note: REG_DEP_ANTI applies to MEM ANTI_DEP as well!!  */
164   if (DEP_TYPE (link) == REG_DEP_ANTI)
165     t = ANTI_DEP;
166   else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
167     t = OUTPUT_DEP;
168 
169   gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
170   gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
171 
172   /* We currently choose not to create certain anti-deps edges and
173      compensate for that by generating reg-moves based on the life-range
174      analysis.  The anti-deps that will be deleted are the ones which
175      have true-deps edges in the opposite direction (in other words
176      the kernel has only one def of the relevant register).  TODO:
177      support the removal of all anti-deps edges, i.e. including those
178      whose register has multiple defs in the loop.  */
179   if (flag_modulo_sched_allow_regmoves && (t == ANTI_DEP && dt == REG_DEP))
180     {
181       rtx set;
182 
183       set = single_set (dest_node->insn);
184       /* TODO: Handle registers that REG_P is not true for them, i.e.
185          subregs and special registers.  */
186       if (set && REG_P (SET_DEST (set)))
187         {
188           int regno = REGNO (SET_DEST (set));
189           df_ref first_def;
190           struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
191 
192           first_def = df_bb_regno_first_def_find (g->bb, regno);
193           gcc_assert (first_def);
194 
195           if (bitmap_bit_p (bb_info->gen, DF_REF_ID (first_def)))
196             return;
197         }
198     }
199 
200    latency = dep_cost (link);
201    e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
202    add_edge_to_ddg (g, e);
203 }
204 
205 /* The same as the above function, but it doesn't require a link parameter.  */
206 static void
207 create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
208 			dep_type d_t, dep_data_type d_dt, int distance)
209 {
210   ddg_edge_ptr e;
211   int l;
212   enum reg_note dep_kind;
213   struct _dep _dep, *dep = &_dep;
214 
215   gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
216   gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
217 
218   if (d_t == ANTI_DEP)
219     dep_kind = REG_DEP_ANTI;
220   else if (d_t == OUTPUT_DEP)
221     dep_kind = REG_DEP_OUTPUT;
222   else
223     {
224       gcc_assert (d_t == TRUE_DEP);
225 
226       dep_kind = REG_DEP_TRUE;
227     }
228 
229   init_dep (dep, from->insn, to->insn, dep_kind);
230 
231   l = dep_cost (dep);
232 
233   e = create_ddg_edge (from, to, d_t, d_dt, l, distance);
234   if (distance > 0)
235     add_backarc_to_ddg (g, e);
236   else
237     add_edge_to_ddg (g, e);
238 }
239 
240 
241 /* Given a downwards exposed register def LAST_DEF (which is the last
242    definition of that register in the bb), add inter-loop true dependences
243    to all its uses in the next iteration, an output dependence to the
244    first def of the same register (possibly itself) in the next iteration
245    and anti-dependences from its uses in the current iteration to the
246    first definition in the next iteration.  */
247 static void
248 add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
249 {
250   int regno = DF_REF_REGNO (last_def);
251   struct df_link *r_use;
252   int has_use_in_bb_p = false;
253   rtx def_insn = DF_REF_INSN (last_def);
254   ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
255   ddg_node_ptr use_node;
256 #ifdef ENABLE_CHECKING
257   struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb);
258 #endif
259   df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
260 
261   gcc_assert (last_def_node);
262   gcc_assert (first_def);
263 
264 #ifdef ENABLE_CHECKING
265   if (DF_REF_ID (last_def) != DF_REF_ID (first_def))
266     gcc_assert (!bitmap_bit_p (bb_info->gen, DF_REF_ID (first_def)));
267 #endif
268 
269   /* Create inter-loop true dependences and anti dependences.  */
270   for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next)
271     {
272       rtx use_insn = DF_REF_INSN (r_use->ref);
273 
274       if (BLOCK_FOR_INSN (use_insn) != g->bb)
275 	continue;
276 
277       /* ??? Do not handle uses with DF_REF_IN_NOTE notes.  */
278       use_node = get_node_of_insn (g, use_insn);
279       gcc_assert (use_node);
280       has_use_in_bb_p = true;
281       if (use_node->cuid <= last_def_node->cuid)
282 	{
283 	  /* Add true deps from last_def to it's uses in the next
284 	     iteration.  Any such upwards exposed use appears before
285 	     the last_def def.  */
286 	  create_ddg_dep_no_link (g, last_def_node, use_node,
287 				  DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
288 				  REG_DEP, 1);
289 	}
290       else if (!DEBUG_INSN_P (use_insn))
291 	{
292 	  /* Add anti deps from last_def's uses in the current iteration
293 	     to the first def in the next iteration.  We do not add ANTI
294 	     dep when there is an intra-loop TRUE dep in the opposite
295 	     direction, but use regmoves to fix such disregarded ANTI
296 	     deps when broken.	If the first_def reaches the USE then
297 	     there is such a dep.  */
298 	  ddg_node_ptr first_def_node = get_node_of_insn (g,
299 							  DF_REF_INSN (first_def));
300 
301 	  gcc_assert (first_def_node);
302 
303           if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
304               || !flag_modulo_sched_allow_regmoves)
305             create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
306                                     REG_DEP, 1);
307 
308 	}
309     }
310   /* Create an inter-loop output dependence between LAST_DEF (which is the
311      last def in its block, being downwards exposed) and the first def in
312      its block.  Avoid creating a self output dependence.  Avoid creating
313      an output dependence if there is a dependence path between the two
314      defs starting with a true dependence to a use which can be in the
315      next iteration; followed by an anti dependence of that use to the
316      first def (i.e. if there is a use between the two defs.)  */
317   if (!has_use_in_bb_p)
318     {
319       ddg_node_ptr dest_node;
320 
321       if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
322 	return;
323 
324       dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
325       gcc_assert (dest_node);
326       create_ddg_dep_no_link (g, last_def_node, dest_node,
327 			      OUTPUT_DEP, REG_DEP, 1);
328     }
329 }
330 /* Build inter-loop dependencies, by looking at DF analysis backwards.  */
331 static void
332 build_inter_loop_deps (ddg_ptr g)
333 {
334   unsigned rd_num;
335   struct df_rd_bb_info *rd_bb_info;
336   bitmap_iterator bi;
337 
338   rd_bb_info = DF_RD_BB_INFO (g->bb);
339 
340   /* Find inter-loop register output, true and anti deps.  */
341   EXECUTE_IF_SET_IN_BITMAP (rd_bb_info->gen, 0, rd_num, bi)
342   {
343     df_ref rd = DF_DEFS_GET (rd_num);
344 
345     add_cross_iteration_register_deps (g, rd);
346   }
347 }
348 
349 
350 /* Given two nodes, analyze their RTL insns and add inter-loop mem deps
351    to ddg G.  */
352 static void
353 add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
354 {
355   if (!insn_alias_sets_conflict_p (from->insn, to->insn))
356     /* Do not create edge if memory references have disjoint alias sets.  */
357     return;
358 
359   if (mem_write_insn_p (from->insn))
360     {
361       if (mem_read_insn_p (to->insn))
362   	create_ddg_dep_no_link (g, from, to,
363 				DEBUG_INSN_P (to->insn)
364 				? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
365       else if (from->cuid != to->cuid)
366   	create_ddg_dep_no_link (g, from, to,
367 				DEBUG_INSN_P (to->insn)
368 				? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
369     }
370   else
371     {
372       if (mem_read_insn_p (to->insn))
373 	return;
374       else if (from->cuid != to->cuid)
375 	{
376 	  create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
377 	  if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
378 	    create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
379 	  else
380 	    create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
381 	}
382     }
383 
384 }
385 
386 /* Perform intra-block Data Dependency analysis and connect the nodes in
387    the DDG.  We assume the loop has a single basic block.  */
388 static void
389 build_intra_loop_deps (ddg_ptr g)
390 {
391   int i;
392   /* Hold the dependency analysis state during dependency calculations.  */
393   struct deps_desc tmp_deps;
394   rtx head, tail;
395 
396   /* Build the dependence information, using the sched_analyze function.  */
397   init_deps_global ();
398   init_deps (&tmp_deps, false);
399 
400   /* Do the intra-block data dependence analysis for the given block.  */
401   get_ebb_head_tail (g->bb, g->bb, &head, &tail);
402   sched_analyze (&tmp_deps, head, tail);
403 
404   /* Build intra-loop data dependencies using the scheduler dependency
405      analysis.  */
406   for (i = 0; i < g->num_nodes; i++)
407     {
408       ddg_node_ptr dest_node = &g->nodes[i];
409       sd_iterator_def sd_it;
410       dep_t dep;
411 
412       if (! INSN_P (dest_node->insn))
413 	continue;
414 
415       FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
416 	{
417 	  ddg_node_ptr src_node = get_node_of_insn (g, DEP_PRO (dep));
418 
419 	  if (!src_node)
420 	    continue;
421 
422 	  create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
423 	}
424 
425       /* If this insn modifies memory, add an edge to all insns that access
426 	 memory.  */
427       if (mem_access_insn_p (dest_node->insn))
428 	{
429 	  int j;
430 
431 	  for (j = 0; j <= i; j++)
432 	    {
433 	      ddg_node_ptr j_node = &g->nodes[j];
434 	      if (DEBUG_INSN_P (j_node->insn))
435 		continue;
436 	      if (mem_access_insn_p (j_node->insn))
437  		/* Don't bother calculating inter-loop dep if an intra-loop dep
438 		   already exists.  */
439 	      	  if (! TEST_BIT (dest_node->successors, j))
440 		    add_inter_loop_mem_dep (g, dest_node, j_node);
441             }
442         }
443     }
444 
445   /* Free the INSN_LISTs.  */
446   finish_deps_global ();
447   free_deps (&tmp_deps);
448 
449   /* Free dependencies.  */
450   sched_free_deps (head, tail, false);
451 }
452 
453 
454 /* Given a basic block, create its DDG and return a pointer to a variable
455    of ddg type that represents it.
456    Initialize the ddg structure fields to the appropriate values.  */
457 ddg_ptr
458 create_ddg (basic_block bb, int closing_branch_deps)
459 {
460   ddg_ptr g;
461   rtx insn, first_note;
462   int i;
463   int num_nodes = 0;
464 
465   g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
466 
467   g->bb = bb;
468   g->closing_branch_deps = closing_branch_deps;
469 
470   /* Count the number of insns in the BB.  */
471   for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
472        insn = NEXT_INSN (insn))
473     {
474       if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
475 	continue;
476 
477       if (DEBUG_INSN_P (insn))
478 	g->num_debug++;
479       else
480 	{
481 	  if (mem_read_insn_p (insn))
482 	    g->num_loads++;
483 	  if (mem_write_insn_p (insn))
484 	    g->num_stores++;
485 	}
486       num_nodes++;
487     }
488 
489   /* There is nothing to do for this BB.  */
490   if ((num_nodes - g->num_debug) <= 1)
491     {
492       free (g);
493       return NULL;
494     }
495 
496   /* Allocate the nodes array, and initialize the nodes.  */
497   g->num_nodes = num_nodes;
498   g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
499   g->closing_branch = NULL;
500   i = 0;
501   first_note = NULL_RTX;
502   for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
503        insn = NEXT_INSN (insn))
504     {
505       if (! INSN_P (insn))
506 	{
507 	  if (! first_note && NOTE_P (insn)
508 	      && NOTE_KIND (insn) !=  NOTE_INSN_BASIC_BLOCK)
509 	    first_note = insn;
510 	  continue;
511 	}
512       if (JUMP_P (insn))
513 	{
514 	  gcc_assert (!g->closing_branch);
515 	  g->closing_branch = &g->nodes[i];
516 	}
517       else if (GET_CODE (PATTERN (insn)) == USE)
518 	{
519 	  if (! first_note)
520 	    first_note = insn;
521 	  continue;
522 	}
523 
524       g->nodes[i].cuid = i;
525       g->nodes[i].successors = sbitmap_alloc (num_nodes);
526       sbitmap_zero (g->nodes[i].successors);
527       g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
528       sbitmap_zero (g->nodes[i].predecessors);
529       g->nodes[i].first_note = (first_note ? first_note : insn);
530       g->nodes[i++].insn = insn;
531       first_note = NULL_RTX;
532     }
533 
534   /* We must have found a branch in DDG.  */
535   gcc_assert (g->closing_branch);
536 
537 
538   /* Build the data dependency graph.  */
539   build_intra_loop_deps (g);
540   build_inter_loop_deps (g);
541   return g;
542 }
543 
544 /* Free all the memory allocated for the DDG.  */
545 void
546 free_ddg (ddg_ptr g)
547 {
548   int i;
549 
550   if (!g)
551     return;
552 
553   for (i = 0; i < g->num_nodes; i++)
554     {
555       ddg_edge_ptr e = g->nodes[i].out;
556 
557       while (e)
558 	{
559 	  ddg_edge_ptr next = e->next_out;
560 
561 	  free (e);
562 	  e = next;
563 	}
564       sbitmap_free (g->nodes[i].successors);
565       sbitmap_free (g->nodes[i].predecessors);
566     }
567   if (g->num_backarcs > 0)
568     free (g->backarcs);
569   free (g->nodes);
570   free (g);
571 }
572 
573 void
574 print_ddg_edge (FILE *file, ddg_edge_ptr e)
575 {
576   char dep_c;
577 
578   switch (e->type)
579     {
580     case OUTPUT_DEP :
581       dep_c = 'O';
582       break;
583     case ANTI_DEP :
584       dep_c = 'A';
585       break;
586     default:
587       dep_c = 'T';
588     }
589 
590   fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
591 	   dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
592 }
593 
594 /* Print the DDG nodes with there in/out edges to the dump file.  */
595 void
596 print_ddg (FILE *file, ddg_ptr g)
597 {
598   int i;
599 
600   for (i = 0; i < g->num_nodes; i++)
601     {
602       ddg_edge_ptr e;
603 
604       fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
605       print_rtl_single (file, g->nodes[i].insn);
606       fprintf (file, "OUT ARCS: ");
607       for (e = g->nodes[i].out; e; e = e->next_out)
608 	print_ddg_edge (file, e);
609 
610       fprintf (file, "\nIN ARCS: ");
611       for (e = g->nodes[i].in; e; e = e->next_in)
612 	print_ddg_edge (file, e);
613 
614       fprintf (file, "\n");
615     }
616 }
617 
618 /* Print the given DDG in VCG format.  */
619 void
620 vcg_print_ddg (FILE *file, ddg_ptr g)
621 {
622   int src_cuid;
623 
624   fprintf (file, "graph: {\n");
625   for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
626     {
627       ddg_edge_ptr e;
628       int src_uid = INSN_UID (g->nodes[src_cuid].insn);
629 
630       fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
631       print_rtl_single (file, g->nodes[src_cuid].insn);
632       fprintf (file, "\"}\n");
633       for (e = g->nodes[src_cuid].out; e; e = e->next_out)
634 	{
635 	  int dst_uid = INSN_UID (e->dest->insn);
636 	  int dst_cuid = e->dest->cuid;
637 
638 	  /* Give the backarcs a different color.  */
639 	  if (e->distance > 0)
640 	    fprintf (file, "backedge: {color: red ");
641 	  else
642 	    fprintf (file, "edge: { ");
643 
644 	  fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
645 	  fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
646 	  fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
647 	}
648     }
649   fprintf (file, "}\n");
650 }
651 
652 /* Dump the sccs in SCCS.  */
653 void
654 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
655 {
656   unsigned int u = 0;
657   sbitmap_iterator sbi;
658   int i;
659 
660   if (!file)
661     return;
662 
663   fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
664   for (i = 0; i < sccs->num_sccs; i++)
665     {
666       fprintf (file, "SCC number: %d\n", i);
667       EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
668       {
669         fprintf (file, "insn num %d\n", u);
670         print_rtl_single (file, g->nodes[u].insn);
671       }
672     }
673   fprintf (file, "\n");
674 }
675 
676 /* Create an edge and initialize it with given values.  */
677 static ddg_edge_ptr
678 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
679 		 dep_type t, dep_data_type dt, int l, int d)
680 {
681   ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
682 
683   e->src = src;
684   e->dest = dest;
685   e->type = t;
686   e->data_type = dt;
687   e->latency = l;
688   e->distance = d;
689   e->next_in = e->next_out = NULL;
690   e->aux.info = 0;
691   return e;
692 }
693 
694 /* Add the given edge to the in/out linked lists of the DDG nodes.  */
695 static void
696 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
697 {
698   ddg_node_ptr src = e->src;
699   ddg_node_ptr dest = e->dest;
700 
701   /* Should have allocated the sbitmaps.  */
702   gcc_assert (src->successors && dest->predecessors);
703 
704   SET_BIT (src->successors, dest->cuid);
705   SET_BIT (dest->predecessors, src->cuid);
706   e->next_in = dest->in;
707   dest->in = e;
708   e->next_out = src->out;
709   src->out = e;
710 }
711 
712 
713 
714 /* Algorithm for computing the recurrence_length of an scc.  We assume at
715    for now that cycles in the data dependence graph contain a single backarc.
716    This simplifies the algorithm, and can be generalized later.  */
717 static void
718 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
719 {
720   int j;
721   int result = -1;
722 
723   for (j = 0; j < scc->num_backarcs; j++)
724     {
725       ddg_edge_ptr backarc = scc->backarcs[j];
726       int length;
727       int distance = backarc->distance;
728       ddg_node_ptr src = backarc->dest;
729       ddg_node_ptr dest = backarc->src;
730 
731       length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
732       if (length < 0 )
733 	{
734 	  /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
735 	  continue;
736 	}
737       length += backarc->latency;
738       result = MAX (result, (length / distance));
739     }
740   scc->recurrence_length = result;
741 }
742 
743 /* Create a new SCC given the set of its nodes.  Compute its recurrence_length
744    and mark edges that belong to this scc as IN_SCC.  */
745 static ddg_scc_ptr
746 create_scc (ddg_ptr g, sbitmap nodes)
747 {
748   ddg_scc_ptr scc;
749   unsigned int u = 0;
750   sbitmap_iterator sbi;
751 
752   scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
753   scc->backarcs = NULL;
754   scc->num_backarcs = 0;
755   scc->nodes = sbitmap_alloc (g->num_nodes);
756   sbitmap_copy (scc->nodes, nodes);
757 
758   /* Mark the backarcs that belong to this SCC.  */
759   EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
760     {
761       ddg_edge_ptr e;
762       ddg_node_ptr n = &g->nodes[u];
763 
764       for (e = n->out; e; e = e->next_out)
765 	if (TEST_BIT (nodes, e->dest->cuid))
766 	  {
767 	    e->aux.count = IN_SCC;
768 	    if (e->distance > 0)
769 	      add_backarc_to_scc (scc, e);
770 	  }
771     }
772 
773   set_recurrence_length (scc, g);
774   return scc;
775 }
776 
777 /* Cleans the memory allocation of a given SCC.  */
778 static void
779 free_scc (ddg_scc_ptr scc)
780 {
781   if (!scc)
782     return;
783 
784   sbitmap_free (scc->nodes);
785   if (scc->num_backarcs > 0)
786     free (scc->backarcs);
787   free (scc);
788 }
789 
790 
791 /* Add a given edge known to be a backarc to the given DDG.  */
792 static void
793 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
794 {
795   int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
796 
797   add_edge_to_ddg (g, e);
798   g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
799   g->backarcs[g->num_backarcs++] = e;
800 }
801 
802 /* Add backarc to an SCC.  */
803 static void
804 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
805 {
806   int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
807 
808   scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
809   scc->backarcs[scc->num_backarcs++] = e;
810 }
811 
812 /* Add the given SCC to the DDG.  */
813 static void
814 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
815 {
816   int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
817 
818   g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
819   g->sccs[g->num_sccs++] = scc;
820 }
821 
822 /* Given the instruction INSN return the node that represents it.  */
823 ddg_node_ptr
824 get_node_of_insn (ddg_ptr g, rtx insn)
825 {
826   int i;
827 
828   for (i = 0; i < g->num_nodes; i++)
829     if (insn == g->nodes[i].insn)
830       return &g->nodes[i];
831   return NULL;
832 }
833 
834 /* Given a set OPS of nodes in the DDG, find the set of their successors
835    which are not in OPS, and set their bits in SUCC.  Bits corresponding to
836    OPS are cleared from SUCC.  Leaves the other bits in SUCC unchanged.  */
837 void
838 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
839 {
840   unsigned int i = 0;
841   sbitmap_iterator sbi;
842 
843   EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
844     {
845       const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
846       sbitmap_a_or_b (succ, succ, node_succ);
847     };
848 
849   /* We want those that are not in ops.  */
850   sbitmap_difference (succ, succ, ops);
851 }
852 
853 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
854    which are not in OPS, and set their bits in PREDS.  Bits corresponding to
855    OPS are cleared from PREDS.  Leaves the other bits in PREDS unchanged.  */
856 void
857 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
858 {
859   unsigned int i = 0;
860   sbitmap_iterator sbi;
861 
862   EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
863     {
864       const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
865       sbitmap_a_or_b (preds, preds, node_preds);
866     };
867 
868   /* We want those that are not in ops.  */
869   sbitmap_difference (preds, preds, ops);
870 }
871 
872 
873 /* Compare function to be passed to qsort to order the backarcs in descending
874    recMII order.  */
875 static int
876 compare_sccs (const void *s1, const void *s2)
877 {
878   const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
879   const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length;
880   return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
881 
882 }
883 
884 /* Order the backarcs in descending recMII order using compare_sccs.  */
885 static void
886 order_sccs (ddg_all_sccs_ptr g)
887 {
888   qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
889 	 (int (*) (const void *, const void *)) compare_sccs);
890 }
891 
892 #ifdef ENABLE_CHECKING
893 /* Check that every node in SCCS belongs to exactly one strongly connected
894    component and that no element of SCCS is empty.  */
895 static void
896 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
897 {
898   int i = 0;
899   sbitmap tmp = sbitmap_alloc (num_nodes);
900 
901   sbitmap_zero (tmp);
902   for (i = 0; i < sccs->num_sccs; i++)
903     {
904       gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes));
905       /* Verify that every node in sccs is in exactly one strongly
906          connected component.  */
907       gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes));
908       sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes);
909     }
910   sbitmap_free (tmp);
911 }
912 #endif
913 
914 /* Perform the Strongly Connected Components decomposing algorithm on the
915    DDG and return DDG_ALL_SCCS structure that contains them.  */
916 ddg_all_sccs_ptr
917 create_ddg_all_sccs (ddg_ptr g)
918 {
919   int i;
920   int num_nodes = g->num_nodes;
921   sbitmap from = sbitmap_alloc (num_nodes);
922   sbitmap to = sbitmap_alloc (num_nodes);
923   sbitmap scc_nodes = sbitmap_alloc (num_nodes);
924   ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
925 			  xmalloc (sizeof (struct ddg_all_sccs));
926 
927   sccs->ddg = g;
928   sccs->sccs = NULL;
929   sccs->num_sccs = 0;
930 
931   for (i = 0; i < g->num_backarcs; i++)
932     {
933       ddg_scc_ptr  scc;
934       ddg_edge_ptr backarc = g->backarcs[i];
935       ddg_node_ptr src = backarc->src;
936       ddg_node_ptr dest = backarc->dest;
937 
938       /* If the backarc already belongs to an SCC, continue.  */
939       if (backarc->aux.count == IN_SCC)
940 	continue;
941 
942       sbitmap_zero (scc_nodes);
943       sbitmap_zero (from);
944       sbitmap_zero (to);
945       SET_BIT (from, dest->cuid);
946       SET_BIT (to, src->cuid);
947 
948       if (find_nodes_on_paths (scc_nodes, g, from, to))
949 	{
950 	  scc = create_scc (g, scc_nodes);
951 	  add_scc_to_ddg (sccs, scc);
952 	}
953     }
954   order_sccs (sccs);
955   sbitmap_free (from);
956   sbitmap_free (to);
957   sbitmap_free (scc_nodes);
958 #ifdef ENABLE_CHECKING
959   check_sccs (sccs, num_nodes);
960 #endif
961   return sccs;
962 }
963 
964 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG.  */
965 void
966 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
967 {
968   int i;
969 
970   if (!all_sccs)
971     return;
972 
973   for (i = 0; i < all_sccs->num_sccs; i++)
974     free_scc (all_sccs->sccs[i]);
975 
976   free (all_sccs);
977 }
978 
979 
980 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
981    nodes - find all nodes that lie on paths from FROM to TO (not excluding
982    nodes from FROM and TO).  Return nonzero if nodes exist.  */
983 int
984 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
985 {
986   int answer;
987   int change;
988   unsigned int u = 0;
989   int num_nodes = g->num_nodes;
990   sbitmap_iterator sbi;
991 
992   sbitmap workset = sbitmap_alloc (num_nodes);
993   sbitmap reachable_from = sbitmap_alloc (num_nodes);
994   sbitmap reach_to = sbitmap_alloc (num_nodes);
995   sbitmap tmp = sbitmap_alloc (num_nodes);
996 
997   sbitmap_copy (reachable_from, from);
998   sbitmap_copy (tmp, from);
999 
1000   change = 1;
1001   while (change)
1002     {
1003       change = 0;
1004       sbitmap_copy (workset, tmp);
1005       sbitmap_zero (tmp);
1006       EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1007 	{
1008 	  ddg_edge_ptr e;
1009 	  ddg_node_ptr u_node = &g->nodes[u];
1010 
1011 	  for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1012 	    {
1013 	      ddg_node_ptr v_node = e->dest;
1014 	      int v = v_node->cuid;
1015 
1016 	      if (!TEST_BIT (reachable_from, v))
1017 		{
1018 		  SET_BIT (reachable_from, v);
1019 		  SET_BIT (tmp, v);
1020 		  change = 1;
1021 		}
1022 	    }
1023 	}
1024     }
1025 
1026   sbitmap_copy (reach_to, to);
1027   sbitmap_copy (tmp, to);
1028 
1029   change = 1;
1030   while (change)
1031     {
1032       change = 0;
1033       sbitmap_copy (workset, tmp);
1034       sbitmap_zero (tmp);
1035       EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1036 	{
1037 	  ddg_edge_ptr e;
1038 	  ddg_node_ptr u_node = &g->nodes[u];
1039 
1040 	  for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1041 	    {
1042 	      ddg_node_ptr v_node = e->src;
1043 	      int v = v_node->cuid;
1044 
1045 	      if (!TEST_BIT (reach_to, v))
1046 		{
1047 		  SET_BIT (reach_to, v);
1048 		  SET_BIT (tmp, v);
1049 		  change = 1;
1050 		}
1051 	    }
1052 	}
1053     }
1054 
1055   answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
1056   sbitmap_free (workset);
1057   sbitmap_free (reachable_from);
1058   sbitmap_free (reach_to);
1059   sbitmap_free (tmp);
1060   return answer;
1061 }
1062 
1063 
1064 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1065    at-least as large as the count of U_NODE plus the latency between them.
1066    Sets a bit in TMP for each successor whose count was changed (increased).
1067    Returns nonzero if any count was changed.  */
1068 static int
1069 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1070 {
1071   ddg_edge_ptr e;
1072   int result = 0;
1073 
1074   for (e = u_node->out; e; e = e->next_out)
1075     {
1076       ddg_node_ptr v_node = e->dest;
1077       int v = v_node->cuid;
1078 
1079       if (TEST_BIT (nodes, v)
1080 	  && (e->distance == 0)
1081 	  && (v_node->aux.count < u_node->aux.count + e->latency))
1082 	{
1083 	  v_node->aux.count = u_node->aux.count + e->latency;
1084 	  SET_BIT (tmp, v);
1085 	  result = 1;
1086 	}
1087     }
1088   return result;
1089 }
1090 
1091 
1092 /* Find the length of a longest path from SRC to DEST in G,
1093    going only through NODES, and disregarding backarcs.  */
1094 int
1095 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1096 {
1097   int i;
1098   unsigned int u = 0;
1099   int change = 1;
1100   int result;
1101   int num_nodes = g->num_nodes;
1102   sbitmap workset = sbitmap_alloc (num_nodes);
1103   sbitmap tmp = sbitmap_alloc (num_nodes);
1104 
1105 
1106   /* Data will hold the distance of the longest path found so far from
1107      src to each node.  Initialize to -1 = less than minimum.  */
1108   for (i = 0; i < g->num_nodes; i++)
1109     g->nodes[i].aux.count = -1;
1110   g->nodes[src].aux.count = 0;
1111 
1112   sbitmap_zero (tmp);
1113   SET_BIT (tmp, src);
1114 
1115   while (change)
1116     {
1117       sbitmap_iterator sbi;
1118 
1119       change = 0;
1120       sbitmap_copy (workset, tmp);
1121       sbitmap_zero (tmp);
1122       EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1123 	{
1124 	  ddg_node_ptr u_node = &g->nodes[u];
1125 
1126 	  change |= update_dist_to_successors (u_node, nodes, tmp);
1127 	}
1128     }
1129   result = g->nodes[dest].aux.count;
1130   sbitmap_free (workset);
1131   sbitmap_free (tmp);
1132   return result;
1133 }
1134 
1135 #endif /* INSN_SCHEDULING */
1136