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