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