OSDN Git Service

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