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