OSDN Git Service

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