OSDN Git Service

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