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