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