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