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