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