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