OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / ddg.c
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 \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   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, TRUE_DEP, MEM_DEP, 1);
363       else if (from->cuid != to->cuid)
364         create_ddg_dep_no_link (g, from, to, OUTPUT_DEP, MEM_DEP, 1);
365     }
366   else
367     {
368       if (mem_read_insn_p (to->insn))
369         return;
370       else if (from->cuid != to->cuid)
371         {
372           create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
373           create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
374         }
375     }
376
377 }
378
379 /* Perform intra-block Data Dependency analysis and connect the nodes in
380    the DDG.  We assume the loop has a single basic block.  */
381 static void
382 build_intra_loop_deps (ddg_ptr g)
383 {
384   int i;
385   /* Hold the dependency analysis state during dependency calculations.  */
386   struct deps tmp_deps;
387   rtx head, tail;
388
389   /* Build the dependence information, using the sched_analyze function.  */
390   init_deps_global ();
391   init_deps (&tmp_deps, false);
392
393   /* Do the intra-block data dependence analysis for the given block.  */
394   get_ebb_head_tail (g->bb, g->bb, &head, &tail);
395   sched_analyze (&tmp_deps, head, tail);
396
397   /* Build intra-loop data dependencies using the scheduler dependency
398      analysis.  */
399   for (i = 0; i < g->num_nodes; i++)
400     {
401       ddg_node_ptr dest_node = &g->nodes[i];
402       sd_iterator_def sd_it;
403       dep_t dep;
404
405       if (! INSN_P (dest_node->insn))
406         continue;
407
408       FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
409         {
410           ddg_node_ptr src_node = get_node_of_insn (g, DEP_PRO (dep));
411
412           if (!src_node)
413             continue;
414
415           create_ddg_dep_from_intra_loop_link (g, src_node, dest_node, dep);
416         }
417
418       /* If this insn modifies memory, add an edge to all insns that access
419          memory.  */
420       if (mem_access_insn_p (dest_node->insn))
421         {
422           int j;
423
424           for (j = 0; j <= i; j++)
425             {
426               ddg_node_ptr j_node = &g->nodes[j];
427               if (DEBUG_INSN_P (j_node->insn))
428                 continue;
429               if (mem_access_insn_p (j_node->insn))
430                 /* Don't bother calculating inter-loop dep if an intra-loop dep
431                    already exists.  */
432                   if (! TEST_BIT (dest_node->successors, j))
433                     add_inter_loop_mem_dep (g, dest_node, j_node);
434             }
435         }
436     }
437
438   /* Free the INSN_LISTs.  */
439   finish_deps_global ();
440   free_deps (&tmp_deps);
441
442   /* Free dependencies.  */
443   sched_free_deps (head, tail, false);
444 }
445
446
447 /* Given a basic block, create its DDG and return a pointer to a variable
448    of ddg type that represents it.
449    Initialize the ddg structure fields to the appropriate values.  */
450 ddg_ptr
451 create_ddg (basic_block bb, int closing_branch_deps)
452 {
453   ddg_ptr g;
454   rtx insn, first_note;
455   int i;
456   int num_nodes = 0;
457
458   g = (ddg_ptr) xcalloc (1, sizeof (struct ddg));
459
460   g->bb = bb;
461   g->closing_branch_deps = closing_branch_deps;
462
463   /* Count the number of insns in the BB.  */
464   for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
465        insn = NEXT_INSN (insn))
466     {
467       if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
468         continue;
469
470       if (DEBUG_INSN_P (insn))
471         g->num_debug++;
472       else
473         {
474           if (mem_read_insn_p (insn))
475             g->num_loads++;
476           if (mem_write_insn_p (insn))
477             g->num_stores++;
478         }
479       num_nodes++;
480     }
481
482   /* There is nothing to do for this BB.  */
483   if (num_nodes <= 1)
484     {
485       free (g);
486       return NULL;
487     }
488
489   /* Allocate the nodes array, and initialize the nodes.  */
490   g->num_nodes = num_nodes;
491   g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node));
492   g->closing_branch = NULL;
493   i = 0;
494   first_note = NULL_RTX;
495   for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
496        insn = NEXT_INSN (insn))
497     {
498       if (! INSN_P (insn))
499         {
500           if (! first_note && NOTE_P (insn)
501               && NOTE_KIND (insn) !=  NOTE_INSN_BASIC_BLOCK)
502             first_note = insn;
503           continue;
504         }
505       if (JUMP_P (insn))
506         {
507           gcc_assert (!g->closing_branch);
508           g->closing_branch = &g->nodes[i];
509         }
510       else if (GET_CODE (PATTERN (insn)) == USE)
511         {
512           if (! first_note)
513             first_note = insn;
514           continue;
515         }
516
517       g->nodes[i].cuid = i;
518       g->nodes[i].successors = sbitmap_alloc (num_nodes);
519       sbitmap_zero (g->nodes[i].successors);
520       g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
521       sbitmap_zero (g->nodes[i].predecessors);
522       g->nodes[i].first_note = (first_note ? first_note : insn);
523       g->nodes[i++].insn = insn;
524       first_note = NULL_RTX;
525     }
526   
527   /* We must have found a branch in DDG.  */
528   gcc_assert (g->closing_branch);
529   
530
531   /* Build the data dependency graph.  */
532   build_intra_loop_deps (g);
533   build_inter_loop_deps (g);
534   return g;
535 }
536
537 /* Free all the memory allocated for the DDG.  */
538 void
539 free_ddg (ddg_ptr g)
540 {
541   int i;
542
543   if (!g)
544     return;
545
546   for (i = 0; i < g->num_nodes; i++)
547     {
548       ddg_edge_ptr e = g->nodes[i].out;
549
550       while (e)
551         {
552           ddg_edge_ptr next = e->next_out;
553
554           free (e);
555           e = next;
556         }
557       sbitmap_free (g->nodes[i].successors);
558       sbitmap_free (g->nodes[i].predecessors);
559     }
560   if (g->num_backarcs > 0)
561     free (g->backarcs);
562   free (g->nodes);
563   free (g);
564 }
565
566 void
567 print_ddg_edge (FILE *file, ddg_edge_ptr e)
568 {
569   char dep_c;
570
571   switch (e->type)
572     {
573     case OUTPUT_DEP :
574       dep_c = 'O';
575       break;
576     case ANTI_DEP :
577       dep_c = 'A';
578       break;
579     default:
580       dep_c = 'T';
581     }
582
583   fprintf (file, " [%d -(%c,%d,%d)-> %d] ", INSN_UID (e->src->insn),
584            dep_c, e->latency, e->distance, INSN_UID (e->dest->insn));
585 }
586
587 /* Print the DDG nodes with there in/out edges to the dump file.  */
588 void
589 print_ddg (FILE *file, ddg_ptr g)
590 {
591   int i;
592
593   for (i = 0; i < g->num_nodes; i++)
594     {
595       ddg_edge_ptr e;
596
597       fprintf (file, "Node num: %d\n", g->nodes[i].cuid);
598       print_rtl_single (file, g->nodes[i].insn);
599       fprintf (file, "OUT ARCS: ");
600       for (e = g->nodes[i].out; e; e = e->next_out)
601         print_ddg_edge (file, e);
602
603       fprintf (file, "\nIN ARCS: ");
604       for (e = g->nodes[i].in; e; e = e->next_in)
605         print_ddg_edge (file, e);
606
607       fprintf (file, "\n");
608     }
609 }
610
611 /* Print the given DDG in VCG format.  */
612 void
613 vcg_print_ddg (FILE *file, ddg_ptr g)
614 {
615   int src_cuid;
616
617   fprintf (file, "graph: {\n");
618   for (src_cuid = 0; src_cuid < g->num_nodes; src_cuid++)
619     {
620       ddg_edge_ptr e;
621       int src_uid = INSN_UID (g->nodes[src_cuid].insn);
622
623       fprintf (file, "node: {title: \"%d_%d\" info1: \"", src_cuid, src_uid);
624       print_rtl_single (file, g->nodes[src_cuid].insn);
625       fprintf (file, "\"}\n");
626       for (e = g->nodes[src_cuid].out; e; e = e->next_out)
627         {
628           int dst_uid = INSN_UID (e->dest->insn);
629           int dst_cuid = e->dest->cuid;
630
631           /* Give the backarcs a different color.  */
632           if (e->distance > 0)
633             fprintf (file, "backedge: {color: red ");
634           else
635             fprintf (file, "edge: { ");
636
637           fprintf (file, "sourcename: \"%d_%d\" ", src_cuid, src_uid);
638           fprintf (file, "targetname: \"%d_%d\" ", dst_cuid, dst_uid);
639           fprintf (file, "label: \"%d_%d\"}\n", e->latency, e->distance);
640         }
641     }
642   fprintf (file, "}\n");
643 }
644
645 /* Dump the sccs in SCCS.  */
646 void
647 print_sccs (FILE *file, ddg_all_sccs_ptr sccs, ddg_ptr g)
648 {
649   unsigned int u = 0;
650   sbitmap_iterator sbi;
651   int i;
652
653   if (!file)
654     return;
655
656   fprintf (file, "\n;; Number of SCC nodes - %d\n", sccs->num_sccs);
657   for (i = 0; i < sccs->num_sccs; i++)
658     {
659       fprintf (file, "SCC number: %d\n", i);
660       EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi)
661       {
662         fprintf (file, "insn num %d\n", u);
663         print_rtl_single (file, g->nodes[u].insn);
664       }
665     }
666   fprintf (file, "\n");
667 }
668
669 /* Create an edge and initialize it with given values.  */
670 static ddg_edge_ptr
671 create_ddg_edge (ddg_node_ptr src, ddg_node_ptr dest,
672                  dep_type t, dep_data_type dt, int l, int d)
673 {
674   ddg_edge_ptr e = (ddg_edge_ptr) xmalloc (sizeof (struct ddg_edge));
675
676   e->src = src;
677   e->dest = dest;
678   e->type = t;
679   e->data_type = dt;
680   e->latency = l;
681   e->distance = d;
682   e->next_in = e->next_out = NULL;
683   e->aux.info = 0;
684   return e;
685 }
686
687 /* Add the given edge to the in/out linked lists of the DDG nodes.  */
688 static void
689 add_edge_to_ddg (ddg_ptr g ATTRIBUTE_UNUSED, ddg_edge_ptr e)
690 {
691   ddg_node_ptr src = e->src;
692   ddg_node_ptr dest = e->dest;
693
694   /* Should have allocated the sbitmaps.  */
695   gcc_assert (src->successors && dest->predecessors);
696
697   SET_BIT (src->successors, dest->cuid);
698   SET_BIT (dest->predecessors, src->cuid);
699   e->next_in = dest->in;
700   dest->in = e;
701   e->next_out = src->out;
702   src->out = e;
703 }
704
705
706 \f
707 /* Algorithm for computing the recurrence_length of an scc.  We assume at
708    for now that cycles in the data dependence graph contain a single backarc.
709    This simplifies the algorithm, and can be generalized later.  */
710 static void
711 set_recurrence_length (ddg_scc_ptr scc, ddg_ptr g)
712 {
713   int j;
714   int result = -1;
715
716   for (j = 0; j < scc->num_backarcs; j++)
717     {
718       ddg_edge_ptr backarc = scc->backarcs[j];
719       int length;
720       int distance = backarc->distance;
721       ddg_node_ptr src = backarc->dest;
722       ddg_node_ptr dest = backarc->src;
723
724       length = longest_simple_path (g, src->cuid, dest->cuid, scc->nodes);
725       if (length < 0 )
726         {
727           /* fprintf (stderr, "Backarc not on simple cycle in SCC.\n"); */
728           continue;
729         }
730       length += backarc->latency;
731       result = MAX (result, (length / distance));
732     }
733   scc->recurrence_length = result;
734 }
735
736 /* Create a new SCC given the set of its nodes.  Compute its recurrence_length
737    and mark edges that belong to this scc as IN_SCC.  */
738 static ddg_scc_ptr
739 create_scc (ddg_ptr g, sbitmap nodes)
740 {
741   ddg_scc_ptr scc;
742   unsigned int u = 0;
743   sbitmap_iterator sbi;
744
745   scc = (ddg_scc_ptr) xmalloc (sizeof (struct ddg_scc));
746   scc->backarcs = NULL;
747   scc->num_backarcs = 0;
748   scc->nodes = sbitmap_alloc (g->num_nodes);
749   sbitmap_copy (scc->nodes, nodes);
750
751   /* Mark the backarcs that belong to this SCC.  */
752   EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
753     {
754       ddg_edge_ptr e;
755       ddg_node_ptr n = &g->nodes[u];
756
757       for (e = n->out; e; e = e->next_out)
758         if (TEST_BIT (nodes, e->dest->cuid))
759           {
760             e->aux.count = IN_SCC;
761             if (e->distance > 0)
762               add_backarc_to_scc (scc, e);
763           }
764     }
765
766   set_recurrence_length (scc, g);
767   return scc;
768 }
769
770 /* Cleans the memory allocation of a given SCC.  */
771 static void
772 free_scc (ddg_scc_ptr scc)
773 {
774   if (!scc)
775     return;
776
777   sbitmap_free (scc->nodes);
778   if (scc->num_backarcs > 0)
779     free (scc->backarcs);
780   free (scc);
781 }
782
783
784 /* Add a given edge known to be a backarc to the given DDG.  */
785 static void
786 add_backarc_to_ddg (ddg_ptr g, ddg_edge_ptr e)
787 {
788   int size = (g->num_backarcs + 1) * sizeof (ddg_edge_ptr);
789
790   add_edge_to_ddg (g, e);
791   g->backarcs = (ddg_edge_ptr *) xrealloc (g->backarcs, size);
792   g->backarcs[g->num_backarcs++] = e;
793 }
794
795 /* Add backarc to an SCC.  */
796 static void
797 add_backarc_to_scc (ddg_scc_ptr scc, ddg_edge_ptr e)
798 {
799   int size = (scc->num_backarcs + 1) * sizeof (ddg_edge_ptr);
800
801   scc->backarcs = (ddg_edge_ptr *) xrealloc (scc->backarcs, size);
802   scc->backarcs[scc->num_backarcs++] = e;
803 }
804
805 /* Add the given SCC to the DDG.  */
806 static void
807 add_scc_to_ddg (ddg_all_sccs_ptr g, ddg_scc_ptr scc)
808 {
809   int size = (g->num_sccs + 1) * sizeof (ddg_scc_ptr);
810
811   g->sccs = (ddg_scc_ptr *) xrealloc (g->sccs, size);
812   g->sccs[g->num_sccs++] = scc;
813 }
814
815 /* Given the instruction INSN return the node that represents it.  */
816 ddg_node_ptr
817 get_node_of_insn (ddg_ptr g, rtx insn)
818 {
819   int i;
820
821   for (i = 0; i < g->num_nodes; i++)
822     if (insn == g->nodes[i].insn)
823       return &g->nodes[i];
824   return NULL;
825 }
826
827 /* Given a set OPS of nodes in the DDG, find the set of their successors
828    which are not in OPS, and set their bits in SUCC.  Bits corresponding to
829    OPS are cleared from SUCC.  Leaves the other bits in SUCC unchanged.  */
830 void
831 find_successors (sbitmap succ, ddg_ptr g, sbitmap ops)
832 {
833   unsigned int i = 0;
834   sbitmap_iterator sbi;
835
836   EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
837     {
838       const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]);
839       sbitmap_a_or_b (succ, succ, node_succ);
840     };
841
842   /* We want those that are not in ops.  */
843   sbitmap_difference (succ, succ, ops);
844 }
845
846 /* Given a set OPS of nodes in the DDG, find the set of their predecessors
847    which are not in OPS, and set their bits in PREDS.  Bits corresponding to
848    OPS are cleared from PREDS.  Leaves the other bits in PREDS unchanged.  */
849 void
850 find_predecessors (sbitmap preds, ddg_ptr g, sbitmap ops)
851 {
852   unsigned int i = 0;
853   sbitmap_iterator sbi;
854
855   EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi)
856     {
857       const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]);
858       sbitmap_a_or_b (preds, preds, node_preds);
859     };
860
861   /* We want those that are not in ops.  */
862   sbitmap_difference (preds, preds, ops);
863 }
864
865
866 /* Compare function to be passed to qsort to order the backarcs in descending
867    recMII order.  */
868 static int
869 compare_sccs (const void *s1, const void *s2)
870 {
871   const int rec_l1 = (*(const ddg_scc_ptr *)s1)->recurrence_length;
872   const int rec_l2 = (*(const ddg_scc_ptr *)s2)->recurrence_length; 
873   return ((rec_l2 > rec_l1) - (rec_l2 < rec_l1));
874           
875 }
876
877 /* Order the backarcs in descending recMII order using compare_sccs.  */
878 static void
879 order_sccs (ddg_all_sccs_ptr g)
880 {
881   qsort (g->sccs, g->num_sccs, sizeof (ddg_scc_ptr),
882          (int (*) (const void *, const void *)) compare_sccs);
883 }
884
885 #ifdef ENABLE_CHECKING
886 /* Check that every node in SCCS belongs to exactly one strongly connected
887    component and that no element of SCCS is empty.  */
888 static void
889 check_sccs (ddg_all_sccs_ptr sccs, int num_nodes)
890 {
891   int i = 0;
892   sbitmap tmp = sbitmap_alloc (num_nodes);
893
894   sbitmap_zero (tmp);
895   for (i = 0; i < sccs->num_sccs; i++)
896     {
897       gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes));
898       /* Verify that every node in sccs is in exactly one strongly
899          connected component.  */
900       gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes));
901       sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes);
902     }
903   sbitmap_free (tmp);
904 }
905 #endif
906
907 /* Perform the Strongly Connected Components decomposing algorithm on the
908    DDG and return DDG_ALL_SCCS structure that contains them.  */
909 ddg_all_sccs_ptr
910 create_ddg_all_sccs (ddg_ptr g)
911 {
912   int i;
913   int num_nodes = g->num_nodes;
914   sbitmap from = sbitmap_alloc (num_nodes);
915   sbitmap to = sbitmap_alloc (num_nodes);
916   sbitmap scc_nodes = sbitmap_alloc (num_nodes);
917   ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr)
918                           xmalloc (sizeof (struct ddg_all_sccs));
919
920   sccs->ddg = g;
921   sccs->sccs = NULL;
922   sccs->num_sccs = 0;
923
924   for (i = 0; i < g->num_backarcs; i++)
925     {
926       ddg_scc_ptr  scc;
927       ddg_edge_ptr backarc = g->backarcs[i];
928       ddg_node_ptr src = backarc->src;
929       ddg_node_ptr dest = backarc->dest;
930
931       /* If the backarc already belongs to an SCC, continue.  */
932       if (backarc->aux.count == IN_SCC)
933         continue;
934
935       sbitmap_zero (scc_nodes);
936       sbitmap_zero (from);
937       sbitmap_zero (to);
938       SET_BIT (from, dest->cuid);
939       SET_BIT (to, src->cuid);
940
941       if (find_nodes_on_paths (scc_nodes, g, from, to))
942         {
943           scc = create_scc (g, scc_nodes);
944           add_scc_to_ddg (sccs, scc);
945         }
946     }
947   order_sccs (sccs);
948   sbitmap_free (from);
949   sbitmap_free (to);
950   sbitmap_free (scc_nodes);
951 #ifdef ENABLE_CHECKING
952   check_sccs (sccs, num_nodes);
953 #endif
954   return sccs;
955 }
956
957 /* Frees the memory allocated for all SCCs of the DDG, but keeps the DDG.  */
958 void
959 free_ddg_all_sccs (ddg_all_sccs_ptr all_sccs)
960 {
961   int i;
962
963   if (!all_sccs)
964     return;
965
966   for (i = 0; i < all_sccs->num_sccs; i++)
967     free_scc (all_sccs->sccs[i]);
968
969   free (all_sccs);
970 }
971
972 \f
973 /* Given FROM - a bitmap of source nodes - and TO - a bitmap of destination
974    nodes - find all nodes that lie on paths from FROM to TO (not excluding
975    nodes from FROM and TO).  Return nonzero if nodes exist.  */
976 int
977 find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to)
978 {
979   int answer;
980   int change;
981   unsigned int u = 0;
982   int num_nodes = g->num_nodes;
983   sbitmap_iterator sbi;
984
985   sbitmap workset = sbitmap_alloc (num_nodes);
986   sbitmap reachable_from = sbitmap_alloc (num_nodes);
987   sbitmap reach_to = sbitmap_alloc (num_nodes);
988   sbitmap tmp = sbitmap_alloc (num_nodes);
989
990   sbitmap_copy (reachable_from, from);
991   sbitmap_copy (tmp, from);
992
993   change = 1;
994   while (change)
995     {
996       change = 0;
997       sbitmap_copy (workset, tmp);
998       sbitmap_zero (tmp);
999       EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1000         {
1001           ddg_edge_ptr e;
1002           ddg_node_ptr u_node = &g->nodes[u];
1003
1004           for (e = u_node->out; e != (ddg_edge_ptr) 0; e = e->next_out)
1005             {
1006               ddg_node_ptr v_node = e->dest;
1007               int v = v_node->cuid;
1008
1009               if (!TEST_BIT (reachable_from, v))
1010                 {
1011                   SET_BIT (reachable_from, v);
1012                   SET_BIT (tmp, v);
1013                   change = 1;
1014                 }
1015             }
1016         }
1017     }
1018
1019   sbitmap_copy (reach_to, to);
1020   sbitmap_copy (tmp, to);
1021
1022   change = 1;
1023   while (change)
1024     {
1025       change = 0;
1026       sbitmap_copy (workset, tmp);
1027       sbitmap_zero (tmp);
1028       EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1029         {
1030           ddg_edge_ptr e;
1031           ddg_node_ptr u_node = &g->nodes[u];
1032
1033           for (e = u_node->in; e != (ddg_edge_ptr) 0; e = e->next_in)
1034             {
1035               ddg_node_ptr v_node = e->src;
1036               int v = v_node->cuid;
1037
1038               if (!TEST_BIT (reach_to, v))
1039                 {
1040                   SET_BIT (reach_to, v);
1041                   SET_BIT (tmp, v);
1042                   change = 1;
1043                 }
1044             }
1045         }
1046     }
1047
1048   answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to);
1049   sbitmap_free (workset);
1050   sbitmap_free (reachable_from);
1051   sbitmap_free (reach_to);
1052   sbitmap_free (tmp);
1053   return answer;
1054 }
1055
1056
1057 /* Updates the counts of U_NODE's successors (that belong to NODES) to be
1058    at-least as large as the count of U_NODE plus the latency between them.
1059    Sets a bit in TMP for each successor whose count was changed (increased).
1060    Returns nonzero if any count was changed.  */
1061 static int
1062 update_dist_to_successors (ddg_node_ptr u_node, sbitmap nodes, sbitmap tmp)
1063 {
1064   ddg_edge_ptr e;
1065   int result = 0;
1066
1067   for (e = u_node->out; e; e = e->next_out)
1068     {
1069       ddg_node_ptr v_node = e->dest;
1070       int v = v_node->cuid;
1071
1072       if (TEST_BIT (nodes, v)
1073           && (e->distance == 0)
1074           && (v_node->aux.count < u_node->aux.count + e->latency))
1075         {
1076           v_node->aux.count = u_node->aux.count + e->latency;
1077           SET_BIT (tmp, v);
1078           result = 1;
1079         }
1080     }
1081   return result;
1082 }
1083
1084
1085 /* Find the length of a longest path from SRC to DEST in G,
1086    going only through NODES, and disregarding backarcs.  */
1087 int
1088 longest_simple_path (struct ddg * g, int src, int dest, sbitmap nodes)
1089 {
1090   int i;
1091   unsigned int u = 0;
1092   int change = 1;
1093   int result;
1094   int num_nodes = g->num_nodes;
1095   sbitmap workset = sbitmap_alloc (num_nodes);
1096   sbitmap tmp = sbitmap_alloc (num_nodes);
1097
1098
1099   /* Data will hold the distance of the longest path found so far from
1100      src to each node.  Initialize to -1 = less than minimum.  */
1101   for (i = 0; i < g->num_nodes; i++)
1102     g->nodes[i].aux.count = -1;
1103   g->nodes[src].aux.count = 0;
1104
1105   sbitmap_zero (tmp);
1106   SET_BIT (tmp, src);
1107
1108   while (change)
1109     {
1110       sbitmap_iterator sbi;
1111
1112       change = 0;
1113       sbitmap_copy (workset, tmp);
1114       sbitmap_zero (tmp);
1115       EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi)
1116         {
1117           ddg_node_ptr u_node = &g->nodes[u];
1118
1119           change |= update_dist_to_successors (u_node, nodes, tmp);
1120         }
1121     }
1122   result = g->nodes[dest].aux.count;
1123   sbitmap_free (workset);
1124   sbitmap_free (tmp);
1125   return result;
1126 }
1127
1128 #endif /* INSN_SCHEDULING */