annotate gcc/cfganal.c @ 141:ce508c72660f

copy cbc flang in cfgexpand
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 22 Nov 2018 19:44:39 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Control flow graph analysis code for GNU compiler.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 1987-2018 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 /* This file contains various simple utilities to analyze the CFG. */
111
kono
parents: 67
diff changeset
21
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 #include "coretypes.h"
111
kono
parents: 67
diff changeset
25 #include "backend.h"
kono
parents: 67
diff changeset
26 #include "cfghooks.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 #include "timevar.h"
111
kono
parents: 67
diff changeset
28 #include "cfganal.h"
kono
parents: 67
diff changeset
29 #include "cfgloop.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30
111
kono
parents: 67
diff changeset
31 namespace {
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 /* Store the data structures necessary for depth-first search. */
111
kono
parents: 67
diff changeset
33 class depth_first_search
kono
parents: 67
diff changeset
34 {
kono
parents: 67
diff changeset
35 public:
kono
parents: 67
diff changeset
36 depth_first_search ();
kono
parents: 67
diff changeset
37
kono
parents: 67
diff changeset
38 basic_block execute (basic_block);
kono
parents: 67
diff changeset
39 void add_bb (basic_block);
kono
parents: 67
diff changeset
40
kono
parents: 67
diff changeset
41 private:
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 /* stack for backtracking during the algorithm */
111
kono
parents: 67
diff changeset
43 auto_vec<basic_block, 20> m_stack;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 /* record of basic blocks already seen by depth-first search */
111
kono
parents: 67
diff changeset
46 auto_sbitmap m_visited_blocks;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 /* Mark the back edges in DFS traversal.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 Return nonzero if a loop (natural or otherwise) is present.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 Inspired by Depth_First_Search_PP described in:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 Advanced Compiler Design and Implementation
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 Steven Muchnick
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 Morgan Kaufmann, 1997
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 and heavily borrowed from pre_and_rev_post_order_compute. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 mark_dfs_back_edges (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 int *pre;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 int *post;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 int prenum = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 int postnum = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 bool found = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 /* Allocate the preorder and postorder number arrays. */
111
kono
parents: 67
diff changeset
70 pre = XCNEWVEC (int, last_basic_block_for_fn (cfun));
kono
parents: 67
diff changeset
71 post = XCNEWVEC (int, last_basic_block_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 /* Allocate stack for back-tracking up CFG. */
111
kono
parents: 67
diff changeset
74 auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (cfun) + 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 /* Allocate bitmap to track nodes that have been visited. */
111
kono
parents: 67
diff changeset
77 auto_sbitmap visited (last_basic_block_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 /* None of the nodes in the CFG have been visited yet. */
111
kono
parents: 67
diff changeset
80 bitmap_clear (visited);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 /* Push the first edge on to the stack. */
111
kono
parents: 67
diff changeset
83 stack.quick_push (ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84
111
kono
parents: 67
diff changeset
85 while (!stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 basic_block src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 basic_block dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 /* Look at the edge on the top of the stack. */
111
kono
parents: 67
diff changeset
91 edge_iterator ei = stack.last ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 src = ei_edge (ei)->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 dest = ei_edge (ei)->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 ei_edge (ei)->flags &= ~EDGE_DFS_BACK;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 /* Check if the edge destination has been visited yet. */
111
kono
parents: 67
diff changeset
97 if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun) && ! bitmap_bit_p (visited,
kono
parents: 67
diff changeset
98 dest->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 /* Mark that we have visited the destination. */
111
kono
parents: 67
diff changeset
101 bitmap_set_bit (visited, dest->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 pre[dest->index] = prenum++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 if (EDGE_COUNT (dest->succs) > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 /* Since the DEST node has been visited for the first
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 time, check its successors. */
111
kono
parents: 67
diff changeset
108 stack.quick_push (ei_start (dest->succs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 post[dest->index] = postnum++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 {
111
kono
parents: 67
diff changeset
115 if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
kono
parents: 67
diff changeset
116 && src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 && pre[src->index] >= pre[dest->index]
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118 && post[dest->index] == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 ei_edge (ei)->flags |= EDGE_DFS_BACK, found = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120
111
kono
parents: 67
diff changeset
121 if (ei_one_before_end_p (ei)
kono
parents: 67
diff changeset
122 && src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 post[src->index] = postnum++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 if (!ei_one_before_end_p (ei))
111
kono
parents: 67
diff changeset
126 ei_next (&stack.last ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 else
111
kono
parents: 67
diff changeset
128 stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 free (pre);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 free (post);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 return found;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 /* Find unreachable blocks. An unreachable block will have 0 in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 the reachable bit in block->flags. A nonzero value indicates the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 block is reachable. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 find_unreachable_blocks (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 basic_block *tos, *worklist, bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148
111
kono
parents: 67
diff changeset
149 tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
151 /* Clear all the reachability flags. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152
111
kono
parents: 67
diff changeset
153 FOR_EACH_BB_FN (bb, cfun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 bb->flags &= ~BB_REACHABLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 /* Add our starting points to the worklist. Almost always there will
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 be only one. It isn't inconceivable that we might one day directly
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 support Fortran alternate entry points. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159
111
kono
parents: 67
diff changeset
160 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 *tos++ = e->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 /* Mark the block reachable. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 e->dest->flags |= BB_REACHABLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 /* Iterate: find everything reachable from what we've already seen. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 while (tos != worklist)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 basic_block b = *--tos;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 FOR_EACH_EDGE (e, ei, b->succs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 basic_block dest = e->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 if (!(dest->flags & BB_REACHABLE))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 *tos++ = dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 dest->flags |= BB_REACHABLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 free (worklist);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 }
111
kono
parents: 67
diff changeset
188
kono
parents: 67
diff changeset
189 /* Verify that there are no unreachable blocks in the current function. */
kono
parents: 67
diff changeset
190
kono
parents: 67
diff changeset
191 void
kono
parents: 67
diff changeset
192 verify_no_unreachable_blocks (void)
kono
parents: 67
diff changeset
193 {
kono
parents: 67
diff changeset
194 find_unreachable_blocks ();
kono
parents: 67
diff changeset
195
kono
parents: 67
diff changeset
196 basic_block bb;
kono
parents: 67
diff changeset
197 FOR_EACH_BB_FN (bb, cfun)
kono
parents: 67
diff changeset
198 gcc_assert ((bb->flags & BB_REACHABLE) != 0);
kono
parents: 67
diff changeset
199 }
kono
parents: 67
diff changeset
200
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 /* Functions to access an edge list with a vector representation.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 Enough data is kept such that given an index number, the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 pred and succ that edge represents can be determined, or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 given a pred and a succ, its index number can be returned.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 This allows algorithms which consume a lot of memory to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 represent the normally full matrix of edge (pred,succ) with a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 single indexed vector, edge (EDGE_INDEX (pred, succ)), with no
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 wasted space in the client code due to sparse flow graphs. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 /* This functions initializes the edge list. Basically the entire
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 flowgraph is processed, and all edges are assigned a number,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 and the data structure is filled in. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 struct edge_list *
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 create_edge_list (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 struct edge_list *elist;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 int num_edges;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 /* Determine the number of edges in the flow graph by counting successor
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 edges on each basic block. */
111
kono
parents: 67
diff changeset
226 num_edges = 0;
kono
parents: 67
diff changeset
227 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
228 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 num_edges += EDGE_COUNT (bb->succs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 elist = XNEW (struct edge_list);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 elist->num_edges = num_edges;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 elist->index_to_edge = XNEWVEC (edge, num_edges);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 num_edges = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 /* Follow successors of blocks, and register these edges. */
111
kono
parents: 67
diff changeset
240 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
241 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 FOR_EACH_EDGE (e, ei, bb->succs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 elist->index_to_edge[num_edges++] = e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 return elist;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 /* This function free's memory associated with an edge list. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 free_edge_list (struct edge_list *elist)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 if (elist)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 free (elist->index_to_edge);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 free (elist);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 /* This function provides debug output showing an edge list. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
262 DEBUG_FUNCTION void
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 print_edge_list (FILE *f, struct edge_list *elist)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 int x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 fprintf (f, "Compressed edge list, %d BBs + entry & exit, and %d edges\n",
111
kono
parents: 67
diff changeset
268 n_basic_blocks_for_fn (cfun), elist->num_edges);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 for (x = 0; x < elist->num_edges; x++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 fprintf (f, " %-4d - edge(", x);
111
kono
parents: 67
diff changeset
273 if (INDEX_EDGE_PRED_BB (elist, x) == ENTRY_BLOCK_PTR_FOR_FN (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 fprintf (f, "entry,");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 fprintf (f, "%d,", INDEX_EDGE_PRED_BB (elist, x)->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277
111
kono
parents: 67
diff changeset
278 if (INDEX_EDGE_SUCC_BB (elist, x) == EXIT_BLOCK_PTR_FOR_FN (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 fprintf (f, "exit)\n");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 fprintf (f, "%d)\n", INDEX_EDGE_SUCC_BB (elist, x)->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 /* This function provides an internal consistency check of an edge list,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
286 verifying that all edges are present, and that there are no
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 extra edges. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
289 DEBUG_FUNCTION void
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 verify_edge_list (FILE *f, struct edge_list *elist)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 int pred, succ, index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 basic_block bb, p, s;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
296
111
kono
parents: 67
diff changeset
297 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
298 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
299 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 FOR_EACH_EDGE (e, ei, bb->succs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 pred = e->src->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 succ = e->dest->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 index = EDGE_INDEX (elist, e->src, e->dest);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 if (index == EDGE_INDEX_NO_EDGE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 fprintf (f, "*p* No index for edge from %d to %d\n", pred, succ);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 if (INDEX_EDGE_PRED_BB (elist, index)->index != pred)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 fprintf (f, "*p* Pred for index %d should be %d not %d\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313 index, pred, INDEX_EDGE_PRED_BB (elist, index)->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 if (INDEX_EDGE_SUCC_BB (elist, index)->index != succ)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 fprintf (f, "*p* Succ for index %d should be %d not %d\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 index, succ, INDEX_EDGE_SUCC_BB (elist, index)->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 /* We've verified that all the edges are in the list, now lets make sure
111
kono
parents: 67
diff changeset
321 there are no spurious edges in the list. This is an expensive check! */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
322
111
kono
parents: 67
diff changeset
323 FOR_BB_BETWEEN (p, ENTRY_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
324 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
kono
parents: 67
diff changeset
325 FOR_BB_BETWEEN (s, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb, NULL, next_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
327 int found_edge = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 FOR_EACH_EDGE (e, ei, p->succs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 if (e->dest == s)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
331 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 found_edge = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 FOR_EACH_EDGE (e, ei, s->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 if (e->src == p)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 found_edge = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
342
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 if (EDGE_INDEX (elist, p, s)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 == EDGE_INDEX_NO_EDGE && found_edge != 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 fprintf (f, "*** Edge (%d, %d) appears to not have an index\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 p->index, s->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 if (EDGE_INDEX (elist, p, s)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 != EDGE_INDEX_NO_EDGE && found_edge == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 fprintf (f, "*** Edge (%d, %d) has index %d, but there is no edge\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 p->index, s->index, EDGE_INDEX (elist, p, s));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353
111
kono
parents: 67
diff changeset
354
kono
parents: 67
diff changeset
355 /* Functions to compute control dependences. */
kono
parents: 67
diff changeset
356
kono
parents: 67
diff changeset
357 /* Indicate block BB is control dependent on an edge with index EDGE_INDEX. */
kono
parents: 67
diff changeset
358 void
kono
parents: 67
diff changeset
359 control_dependences::set_control_dependence_map_bit (basic_block bb,
kono
parents: 67
diff changeset
360 int edge_index)
kono
parents: 67
diff changeset
361 {
kono
parents: 67
diff changeset
362 if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
363 return;
kono
parents: 67
diff changeset
364 gcc_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
kono
parents: 67
diff changeset
365 bitmap_set_bit (control_dependence_map[bb->index], edge_index);
kono
parents: 67
diff changeset
366 }
kono
parents: 67
diff changeset
367
kono
parents: 67
diff changeset
368 /* Clear all control dependences for block BB. */
kono
parents: 67
diff changeset
369 void
kono
parents: 67
diff changeset
370 control_dependences::clear_control_dependence_bitmap (basic_block bb)
kono
parents: 67
diff changeset
371 {
kono
parents: 67
diff changeset
372 bitmap_clear (control_dependence_map[bb->index]);
kono
parents: 67
diff changeset
373 }
kono
parents: 67
diff changeset
374
kono
parents: 67
diff changeset
375 /* Find the immediate postdominator PDOM of the specified basic block BLOCK.
kono
parents: 67
diff changeset
376 This function is necessary because some blocks have negative numbers. */
kono
parents: 67
diff changeset
377
kono
parents: 67
diff changeset
378 static inline basic_block
kono
parents: 67
diff changeset
379 find_pdom (basic_block block)
kono
parents: 67
diff changeset
380 {
kono
parents: 67
diff changeset
381 gcc_assert (block != ENTRY_BLOCK_PTR_FOR_FN (cfun));
kono
parents: 67
diff changeset
382
kono
parents: 67
diff changeset
383 if (block == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
384 return EXIT_BLOCK_PTR_FOR_FN (cfun);
kono
parents: 67
diff changeset
385 else
kono
parents: 67
diff changeset
386 {
kono
parents: 67
diff changeset
387 basic_block bb = get_immediate_dominator (CDI_POST_DOMINATORS, block);
kono
parents: 67
diff changeset
388 if (! bb)
kono
parents: 67
diff changeset
389 return EXIT_BLOCK_PTR_FOR_FN (cfun);
kono
parents: 67
diff changeset
390 return bb;
kono
parents: 67
diff changeset
391 }
kono
parents: 67
diff changeset
392 }
kono
parents: 67
diff changeset
393
kono
parents: 67
diff changeset
394 /* Determine all blocks' control dependences on the given edge with edge_list
kono
parents: 67
diff changeset
395 EL index EDGE_INDEX, ala Morgan, Section 3.6. */
kono
parents: 67
diff changeset
396
kono
parents: 67
diff changeset
397 void
kono
parents: 67
diff changeset
398 control_dependences::find_control_dependence (int edge_index)
kono
parents: 67
diff changeset
399 {
kono
parents: 67
diff changeset
400 basic_block current_block;
kono
parents: 67
diff changeset
401 basic_block ending_block;
kono
parents: 67
diff changeset
402
kono
parents: 67
diff changeset
403 gcc_assert (get_edge_src (edge_index) != EXIT_BLOCK_PTR_FOR_FN (cfun));
kono
parents: 67
diff changeset
404
kono
parents: 67
diff changeset
405 /* For abnormal edges, we don't make current_block control
kono
parents: 67
diff changeset
406 dependent because instructions that throw are always necessary
kono
parents: 67
diff changeset
407 anyway. */
kono
parents: 67
diff changeset
408 edge e = find_edge (get_edge_src (edge_index), get_edge_dest (edge_index));
kono
parents: 67
diff changeset
409 if (e->flags & EDGE_ABNORMAL)
kono
parents: 67
diff changeset
410 return;
kono
parents: 67
diff changeset
411
kono
parents: 67
diff changeset
412 if (get_edge_src (edge_index) == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
413 ending_block = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
kono
parents: 67
diff changeset
414 else
kono
parents: 67
diff changeset
415 ending_block = find_pdom (get_edge_src (edge_index));
kono
parents: 67
diff changeset
416
kono
parents: 67
diff changeset
417 for (current_block = get_edge_dest (edge_index);
kono
parents: 67
diff changeset
418 current_block != ending_block
kono
parents: 67
diff changeset
419 && current_block != EXIT_BLOCK_PTR_FOR_FN (cfun);
kono
parents: 67
diff changeset
420 current_block = find_pdom (current_block))
kono
parents: 67
diff changeset
421 set_control_dependence_map_bit (current_block, edge_index);
kono
parents: 67
diff changeset
422 }
kono
parents: 67
diff changeset
423
kono
parents: 67
diff changeset
424 /* Record all blocks' control dependences on all edges in the edge
kono
parents: 67
diff changeset
425 list EL, ala Morgan, Section 3.6. */
kono
parents: 67
diff changeset
426
kono
parents: 67
diff changeset
427 control_dependences::control_dependences ()
kono
parents: 67
diff changeset
428 {
kono
parents: 67
diff changeset
429 timevar_push (TV_CONTROL_DEPENDENCES);
kono
parents: 67
diff changeset
430
kono
parents: 67
diff changeset
431 /* Initialize the edge list. */
kono
parents: 67
diff changeset
432 int num_edges = 0;
kono
parents: 67
diff changeset
433 basic_block bb;
kono
parents: 67
diff changeset
434 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
435 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
kono
parents: 67
diff changeset
436 num_edges += EDGE_COUNT (bb->succs);
kono
parents: 67
diff changeset
437 m_el.create (num_edges);
kono
parents: 67
diff changeset
438 edge e;
kono
parents: 67
diff changeset
439 edge_iterator ei;
kono
parents: 67
diff changeset
440 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
441 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
kono
parents: 67
diff changeset
442 FOR_EACH_EDGE (e, ei, bb->succs)
kono
parents: 67
diff changeset
443 m_el.quick_push (std::make_pair (e->src->index, e->dest->index));
kono
parents: 67
diff changeset
444
kono
parents: 67
diff changeset
445 control_dependence_map.create (last_basic_block_for_fn (cfun));
kono
parents: 67
diff changeset
446 for (int i = 0; i < last_basic_block_for_fn (cfun); ++i)
kono
parents: 67
diff changeset
447 control_dependence_map.quick_push (BITMAP_ALLOC (NULL));
kono
parents: 67
diff changeset
448 for (int i = 0; i < num_edges; ++i)
kono
parents: 67
diff changeset
449 find_control_dependence (i);
kono
parents: 67
diff changeset
450
kono
parents: 67
diff changeset
451 timevar_pop (TV_CONTROL_DEPENDENCES);
kono
parents: 67
diff changeset
452 }
kono
parents: 67
diff changeset
453
kono
parents: 67
diff changeset
454 /* Free control dependences and the associated edge list. */
kono
parents: 67
diff changeset
455
kono
parents: 67
diff changeset
456 control_dependences::~control_dependences ()
kono
parents: 67
diff changeset
457 {
kono
parents: 67
diff changeset
458 for (unsigned i = 0; i < control_dependence_map.length (); ++i)
kono
parents: 67
diff changeset
459 BITMAP_FREE (control_dependence_map[i]);
kono
parents: 67
diff changeset
460 control_dependence_map.release ();
kono
parents: 67
diff changeset
461 m_el.release ();
kono
parents: 67
diff changeset
462 }
kono
parents: 67
diff changeset
463
kono
parents: 67
diff changeset
464 /* Returns the bitmap of edges the basic-block I is dependent on. */
kono
parents: 67
diff changeset
465
kono
parents: 67
diff changeset
466 bitmap
kono
parents: 67
diff changeset
467 control_dependences::get_edges_dependent_on (int i)
kono
parents: 67
diff changeset
468 {
kono
parents: 67
diff changeset
469 return control_dependence_map[i];
kono
parents: 67
diff changeset
470 }
kono
parents: 67
diff changeset
471
kono
parents: 67
diff changeset
472 /* Returns the edge source with index I from the edge list. */
kono
parents: 67
diff changeset
473
kono
parents: 67
diff changeset
474 basic_block
kono
parents: 67
diff changeset
475 control_dependences::get_edge_src (int i)
kono
parents: 67
diff changeset
476 {
kono
parents: 67
diff changeset
477 return BASIC_BLOCK_FOR_FN (cfun, m_el[i].first);
kono
parents: 67
diff changeset
478 }
kono
parents: 67
diff changeset
479
kono
parents: 67
diff changeset
480 /* Returns the edge destination with index I from the edge list. */
kono
parents: 67
diff changeset
481
kono
parents: 67
diff changeset
482 basic_block
kono
parents: 67
diff changeset
483 control_dependences::get_edge_dest (int i)
kono
parents: 67
diff changeset
484 {
kono
parents: 67
diff changeset
485 return BASIC_BLOCK_FOR_FN (cfun, m_el[i].second);
kono
parents: 67
diff changeset
486 }
kono
parents: 67
diff changeset
487
kono
parents: 67
diff changeset
488
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489 /* Given PRED and SUCC blocks, return the edge which connects the blocks.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 If no such edge exists, return NULL. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492 edge
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493 find_edge (basic_block pred, basic_block succ)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
495 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
496 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
497
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498 if (EDGE_COUNT (pred->succs) <= EDGE_COUNT (succ->preds))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
500 FOR_EACH_EDGE (e, ei, pred->succs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
501 if (e->dest == succ)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
502 return e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
503 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
505 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
506 FOR_EACH_EDGE (e, ei, succ->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
507 if (e->src == pred)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
508 return e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
509 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
511 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
512 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
513
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514 /* This routine will determine what, if any, edge there is between
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515 a specified predecessor and successor. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
516
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
517 int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
518 find_edge_index (struct edge_list *edge_list, basic_block pred, basic_block succ)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
519 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
520 int x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522 for (x = 0; x < NUM_EDGES (edge_list); x++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 if (INDEX_EDGE_PRED_BB (edge_list, x) == pred
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
524 && INDEX_EDGE_SUCC_BB (edge_list, x) == succ)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
526
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527 return (EDGE_INDEX_NO_EDGE);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
528 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
529
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
530 /* This routine will remove any fake predecessor edges for a basic block.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
531 When the edge is removed, it is also removed from whatever successor
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532 list it is in. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
534 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535 remove_fake_predecessors (basic_block bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
537 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
539
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540 for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
541 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542 if ((e->flags & EDGE_FAKE) == EDGE_FAKE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 remove_edge (e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 ei_next (&ei);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
546 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
549 /* This routine will remove all fake edges from the flow graph. If
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 we remove all fake successors, it will automatically remove all
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 fake predecessors. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
552
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
554 remove_fake_edges (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557
111
kono
parents: 67
diff changeset
558 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb, NULL, next_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559 remove_fake_predecessors (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
561
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
562 /* This routine will remove all fake edges to the EXIT_BLOCK. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
563
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
565 remove_fake_exit_edges (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566 {
111
kono
parents: 67
diff changeset
567 remove_fake_predecessors (EXIT_BLOCK_PTR_FOR_FN (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
568 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
569
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
570
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 /* This function will add a fake edge between any block which has no
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572 successors, and the exit block. Some data flow equations require these
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
573 edges to exist. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
574
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
575 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576 add_noreturn_fake_exit_edges (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
577 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579
111
kono
parents: 67
diff changeset
580 FOR_EACH_BB_FN (bb, cfun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 if (EDGE_COUNT (bb->succs) == 0)
111
kono
parents: 67
diff changeset
582 make_single_succ_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
583 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
584
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585 /* This function adds a fake edge between any infinite loops to the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586 exit block. Some optimizations require a path from each node to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587 the exit node.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589 See also Morgan, Figure 3.10, pp. 82-83.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
591 The current implementation is ugly, not attempting to minimize the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 number of inserted fake edges. To reduce the number of fake edges
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
593 to insert, add fake edges from _innermost_ loops containing only
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594 nodes not reachable from the exit block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
596 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
597 connect_infinite_loops_to_exit (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
598 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
599 /* Perform depth-first search in the reverse graph to find nodes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600 reachable from the exit block. */
111
kono
parents: 67
diff changeset
601 depth_first_search dfs;
kono
parents: 67
diff changeset
602 dfs.add_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
604 /* Repeatedly add fake edges, updating the unreachable nodes. */
111
kono
parents: 67
diff changeset
605 basic_block unvisited_block = EXIT_BLOCK_PTR_FOR_FN (cfun);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 {
111
kono
parents: 67
diff changeset
608 unvisited_block = dfs.execute (unvisited_block);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
609 if (!unvisited_block)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
611
111
kono
parents: 67
diff changeset
612 basic_block deadend_block = dfs_find_deadend (unvisited_block);
kono
parents: 67
diff changeset
613 edge e = make_edge (deadend_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
614 EDGE_FAKE);
kono
parents: 67
diff changeset
615 e->probability = profile_probability::never ();
kono
parents: 67
diff changeset
616 dfs.add_bb (deadend_block);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
618 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
619
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
620 /* Compute reverse top sort order. This is computing a post order
111
kono
parents: 67
diff changeset
621 numbering of the graph. If INCLUDE_ENTRY_EXIT is true, then
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 ENTRY_BLOCK and EXIT_BLOCK are included. If DELETE_UNREACHABLE is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
623 true, unreachable blocks are deleted. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 int
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
626 post_order_compute (int *post_order, bool include_entry_exit,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627 bool delete_unreachable)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
628 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629 int post_order_num = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
630 int count;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
631
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 if (include_entry_exit)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 post_order[post_order_num++] = EXIT_BLOCK;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635 /* Allocate stack for back-tracking up CFG. */
111
kono
parents: 67
diff changeset
636 auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (cfun) + 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 /* Allocate bitmap to track nodes that have been visited. */
111
kono
parents: 67
diff changeset
639 auto_sbitmap visited (last_basic_block_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 /* None of the nodes in the CFG have been visited yet. */
111
kono
parents: 67
diff changeset
642 bitmap_clear (visited);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
643
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
644 /* Push the first edge on to the stack. */
111
kono
parents: 67
diff changeset
645 stack.quick_push (ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646
111
kono
parents: 67
diff changeset
647 while (!stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
648 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 basic_block src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650 basic_block dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
651
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
652 /* Look at the edge on the top of the stack. */
111
kono
parents: 67
diff changeset
653 edge_iterator ei = stack.last ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
654 src = ei_edge (ei)->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
655 dest = ei_edge (ei)->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
656
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
657 /* Check if the edge destination has been visited yet. */
111
kono
parents: 67
diff changeset
658 if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
kono
parents: 67
diff changeset
659 && ! bitmap_bit_p (visited, dest->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
660 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
661 /* Mark that we have visited the destination. */
111
kono
parents: 67
diff changeset
662 bitmap_set_bit (visited, dest->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
663
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
664 if (EDGE_COUNT (dest->succs) > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
665 /* Since the DEST node has been visited for the first
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
666 time, check its successors. */
111
kono
parents: 67
diff changeset
667 stack.quick_push (ei_start (dest->succs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
668 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
669 post_order[post_order_num++] = dest->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
670 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
671 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
672 {
111
kono
parents: 67
diff changeset
673 if (ei_one_before_end_p (ei)
kono
parents: 67
diff changeset
674 && src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
675 post_order[post_order_num++] = src->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
676
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
677 if (!ei_one_before_end_p (ei))
111
kono
parents: 67
diff changeset
678 ei_next (&stack.last ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
679 else
111
kono
parents: 67
diff changeset
680 stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
681 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
682 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
683
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
684 if (include_entry_exit)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
685 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
686 post_order[post_order_num++] = ENTRY_BLOCK;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
687 count = post_order_num;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
688 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
689 else
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
690 count = post_order_num + 2;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
691
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
692 /* Delete the unreachable blocks if some were found and we are
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
693 supposed to do it. */
111
kono
parents: 67
diff changeset
694 if (delete_unreachable && (count != n_basic_blocks_for_fn (cfun)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
695 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
696 basic_block b;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
697 basic_block next_bb;
111
kono
parents: 67
diff changeset
698 for (b = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; b
kono
parents: 67
diff changeset
699 != EXIT_BLOCK_PTR_FOR_FN (cfun); b = next_bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
700 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
701 next_bb = b->next_bb;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
702
111
kono
parents: 67
diff changeset
703 if (!(bitmap_bit_p (visited, b->index)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
704 delete_basic_block (b);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
705 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
706
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
707 tidy_fallthru_edges ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
708 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
709
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
710 return post_order_num;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
711 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
712
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
713
111
kono
parents: 67
diff changeset
714 /* Helper routine for inverted_post_order_compute
kono
parents: 67
diff changeset
715 flow_dfs_compute_reverse_execute, and the reverse-CFG
kono
parents: 67
diff changeset
716 deapth first search in dominance.c.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
717 BB has to belong to a region of CFG
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
718 unreachable by inverted traversal from the exit.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
719 i.e. there's no control flow path from ENTRY to EXIT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
720 that contains this BB.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
721 This can happen in two cases - if there's an infinite loop
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
722 or if there's a block that has no successor
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
723 (call to a function with no return).
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
724 Some RTL passes deal with this condition by
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
725 calling connect_infinite_loops_to_exit () and/or
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
726 add_noreturn_fake_exit_edges ().
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
727 However, those methods involve modifying the CFG itself
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
728 which may not be desirable.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
729 Hence, we deal with the infinite loop/no return cases
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
730 by identifying a unique basic block that can reach all blocks
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
731 in such a region by inverted traversal.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
732 This function returns a basic block that guarantees
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
733 that all blocks in the region are reachable
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
734 by starting an inverted traversal from the returned block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
735
111
kono
parents: 67
diff changeset
736 basic_block
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
737 dfs_find_deadend (basic_block bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
738 {
111
kono
parents: 67
diff changeset
739 auto_bitmap visited;
kono
parents: 67
diff changeset
740 basic_block next = bb;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
741
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
742 for (;;)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
743 {
111
kono
parents: 67
diff changeset
744 if (EDGE_COUNT (next->succs) == 0)
kono
parents: 67
diff changeset
745 return next;
kono
parents: 67
diff changeset
746
kono
parents: 67
diff changeset
747 if (! bitmap_set_bit (visited, next->index))
kono
parents: 67
diff changeset
748 return bb;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
749
111
kono
parents: 67
diff changeset
750 bb = next;
kono
parents: 67
diff changeset
751 /* If we are in an analyzed cycle make sure to try exiting it.
kono
parents: 67
diff changeset
752 Note this is a heuristic only and expected to work when loop
kono
parents: 67
diff changeset
753 fixup is needed as well. */
kono
parents: 67
diff changeset
754 if (! bb->loop_father
kono
parents: 67
diff changeset
755 || ! loop_outer (bb->loop_father))
kono
parents: 67
diff changeset
756 next = EDGE_SUCC (bb, 0)->dest;
kono
parents: 67
diff changeset
757 else
kono
parents: 67
diff changeset
758 {
kono
parents: 67
diff changeset
759 edge_iterator ei;
kono
parents: 67
diff changeset
760 edge e;
kono
parents: 67
diff changeset
761 FOR_EACH_EDGE (e, ei, bb->succs)
kono
parents: 67
diff changeset
762 if (loop_exit_edge_p (bb->loop_father, e))
kono
parents: 67
diff changeset
763 break;
kono
parents: 67
diff changeset
764 next = e ? e->dest : EDGE_SUCC (bb, 0)->dest;
kono
parents: 67
diff changeset
765 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
766 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
767
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768 gcc_unreachable ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
769 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
770
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
771
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
772 /* Compute the reverse top sort order of the inverted CFG
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
773 i.e. starting from the exit block and following the edges backward
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
774 (from successors to predecessors).
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
775 This ordering can be used for forward dataflow problems among others.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
776
111
kono
parents: 67
diff changeset
777 Optionally if START_POINTS is specified, start from exit block and all
kono
parents: 67
diff changeset
778 basic blocks in START_POINTS. This is used by CD-DCE.
kono
parents: 67
diff changeset
779
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
780 This function assumes that all blocks in the CFG are reachable
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
781 from the ENTRY (but not necessarily from EXIT).
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
782
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
783 If there's an infinite loop,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
784 a simple inverted traversal starting from the blocks
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
785 with no successors can't visit all blocks.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
786 To solve this problem, we first do inverted traversal
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
787 starting from the blocks with no successor.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
788 And if there's any block left that's not visited by the regular
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
789 inverted traversal from EXIT,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
790 those blocks are in such problematic region.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
791 Among those, we find one block that has
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
792 any visited predecessor (which is an entry into such a region),
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
793 and start looking for a "dead end" from that block
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
794 and do another inverted traversal from that block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
795
111
kono
parents: 67
diff changeset
796 void
kono
parents: 67
diff changeset
797 inverted_post_order_compute (vec<int> *post_order,
kono
parents: 67
diff changeset
798 sbitmap *start_points)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
799 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
800 basic_block bb;
111
kono
parents: 67
diff changeset
801 post_order->reserve_exact (n_basic_blocks_for_fn (cfun));
kono
parents: 67
diff changeset
802
kono
parents: 67
diff changeset
803 if (flag_checking)
kono
parents: 67
diff changeset
804 verify_no_unreachable_blocks ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
805
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
806 /* Allocate stack for back-tracking up CFG. */
111
kono
parents: 67
diff changeset
807 auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (cfun) + 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
808
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
809 /* Allocate bitmap to track nodes that have been visited. */
111
kono
parents: 67
diff changeset
810 auto_sbitmap visited (last_basic_block_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
811
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
812 /* None of the nodes in the CFG have been visited yet. */
111
kono
parents: 67
diff changeset
813 bitmap_clear (visited);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
814
111
kono
parents: 67
diff changeset
815 if (start_points)
kono
parents: 67
diff changeset
816 {
kono
parents: 67
diff changeset
817 FOR_ALL_BB_FN (bb, cfun)
kono
parents: 67
diff changeset
818 if (bitmap_bit_p (*start_points, bb->index)
kono
parents: 67
diff changeset
819 && EDGE_COUNT (bb->preds) > 0)
kono
parents: 67
diff changeset
820 {
kono
parents: 67
diff changeset
821 stack.quick_push (ei_start (bb->preds));
kono
parents: 67
diff changeset
822 bitmap_set_bit (visited, bb->index);
kono
parents: 67
diff changeset
823 }
kono
parents: 67
diff changeset
824 if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds))
kono
parents: 67
diff changeset
825 {
kono
parents: 67
diff changeset
826 stack.quick_push (ei_start (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds));
kono
parents: 67
diff changeset
827 bitmap_set_bit (visited, EXIT_BLOCK_PTR_FOR_FN (cfun)->index);
kono
parents: 67
diff changeset
828 }
kono
parents: 67
diff changeset
829 }
kono
parents: 67
diff changeset
830 else
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
831 /* Put all blocks that have no successor into the initial work list. */
111
kono
parents: 67
diff changeset
832 FOR_ALL_BB_FN (bb, cfun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
833 if (EDGE_COUNT (bb->succs) == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
834 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
835 /* Push the initial edge on to the stack. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
836 if (EDGE_COUNT (bb->preds) > 0)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
837 {
111
kono
parents: 67
diff changeset
838 stack.quick_push (ei_start (bb->preds));
kono
parents: 67
diff changeset
839 bitmap_set_bit (visited, bb->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
840 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
841 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
842
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
843 do
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
844 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
845 bool has_unvisited_bb = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
846
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
847 /* The inverted traversal loop. */
111
kono
parents: 67
diff changeset
848 while (!stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
849 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
850 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
851 basic_block pred;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
852
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
853 /* Look at the edge on the top of the stack. */
111
kono
parents: 67
diff changeset
854 ei = stack.last ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
855 bb = ei_edge (ei)->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
856 pred = ei_edge (ei)->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
857
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
858 /* Check if the predecessor has been visited yet. */
111
kono
parents: 67
diff changeset
859 if (! bitmap_bit_p (visited, pred->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
860 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
861 /* Mark that we have visited the destination. */
111
kono
parents: 67
diff changeset
862 bitmap_set_bit (visited, pred->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
863
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
864 if (EDGE_COUNT (pred->preds) > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
865 /* Since the predecessor node has been visited for the first
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
866 time, check its predecessors. */
111
kono
parents: 67
diff changeset
867 stack.quick_push (ei_start (pred->preds));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
868 else
111
kono
parents: 67
diff changeset
869 post_order->quick_push (pred->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
870 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
871 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
872 {
111
kono
parents: 67
diff changeset
873 if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
kono
parents: 67
diff changeset
874 && ei_one_before_end_p (ei))
kono
parents: 67
diff changeset
875 post_order->quick_push (bb->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
876
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
877 if (!ei_one_before_end_p (ei))
111
kono
parents: 67
diff changeset
878 ei_next (&stack.last ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
879 else
111
kono
parents: 67
diff changeset
880 stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
881 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
882 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
883
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
884 /* Detect any infinite loop and activate the kludge.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
885 Note that this doesn't check EXIT_BLOCK itself
111
kono
parents: 67
diff changeset
886 since EXIT_BLOCK is always added after the outer do-while loop. */
kono
parents: 67
diff changeset
887 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
kono
parents: 67
diff changeset
888 EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
kono
parents: 67
diff changeset
889 if (!bitmap_bit_p (visited, bb->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
890 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
891 has_unvisited_bb = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
892
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
893 if (EDGE_COUNT (bb->preds) > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
894 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
895 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
896 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
897 basic_block visited_pred = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
898
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
899 /* Find an already visited predecessor. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
900 FOR_EACH_EDGE (e, ei, bb->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
901 {
111
kono
parents: 67
diff changeset
902 if (bitmap_bit_p (visited, e->src->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
903 visited_pred = e->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
904 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
905
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
906 if (visited_pred)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
907 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
908 basic_block be = dfs_find_deadend (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
909 gcc_assert (be != NULL);
111
kono
parents: 67
diff changeset
910 bitmap_set_bit (visited, be->index);
kono
parents: 67
diff changeset
911 stack.quick_push (ei_start (be->preds));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
912 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
913 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
914 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
915 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
916
111
kono
parents: 67
diff changeset
917 if (has_unvisited_bb && stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
918 {
111
kono
parents: 67
diff changeset
919 /* No blocks are reachable from EXIT at all.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
920 Find a dead-end from the ENTRY, and restart the iteration. */
111
kono
parents: 67
diff changeset
921 basic_block be = dfs_find_deadend (ENTRY_BLOCK_PTR_FOR_FN (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
922 gcc_assert (be != NULL);
111
kono
parents: 67
diff changeset
923 bitmap_set_bit (visited, be->index);
kono
parents: 67
diff changeset
924 stack.quick_push (ei_start (be->preds));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
925 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
926
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
927 /* The only case the below while fires is
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
928 when there's an infinite loop. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
929 }
111
kono
parents: 67
diff changeset
930 while (!stack.is_empty ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
931
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
932 /* EXIT_BLOCK is always included. */
111
kono
parents: 67
diff changeset
933 post_order->quick_push (EXIT_BLOCK);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
934 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
935
111
kono
parents: 67
diff changeset
936 /* Compute the depth first search order of FN and store in the array
kono
parents: 67
diff changeset
937 PRE_ORDER if nonzero. If REV_POST_ORDER is nonzero, return the
kono
parents: 67
diff changeset
938 reverse completion number for each node. Returns the number of nodes
kono
parents: 67
diff changeset
939 visited. A depth first search tries to get as far away from the starting
kono
parents: 67
diff changeset
940 point as quickly as possible.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
941
111
kono
parents: 67
diff changeset
942 In case the function has unreachable blocks the number of nodes
kono
parents: 67
diff changeset
943 visited does not include them.
kono
parents: 67
diff changeset
944
kono
parents: 67
diff changeset
945 pre_order is a really a preorder numbering of the graph.
kono
parents: 67
diff changeset
946 rev_post_order is really a reverse postorder numbering of the graph. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948 int
111
kono
parents: 67
diff changeset
949 pre_and_rev_post_order_compute_fn (struct function *fn,
kono
parents: 67
diff changeset
950 int *pre_order, int *rev_post_order,
kono
parents: 67
diff changeset
951 bool include_entry_exit)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
952 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
953 int pre_order_num = 0;
111
kono
parents: 67
diff changeset
954 int rev_post_order_num = n_basic_blocks_for_fn (cfun) - 1;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
955
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
956 /* Allocate stack for back-tracking up CFG. */
111
kono
parents: 67
diff changeset
957 auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (cfun) + 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
958
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
959 if (include_entry_exit)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
960 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
961 if (pre_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
962 pre_order[pre_order_num] = ENTRY_BLOCK;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
963 pre_order_num++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
964 if (rev_post_order)
111
kono
parents: 67
diff changeset
965 rev_post_order[rev_post_order_num--] = EXIT_BLOCK;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
966 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
967 else
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
968 rev_post_order_num -= NUM_FIXED_BLOCKS;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
969
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
970 /* Allocate bitmap to track nodes that have been visited. */
111
kono
parents: 67
diff changeset
971 auto_sbitmap visited (last_basic_block_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
972
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
973 /* None of the nodes in the CFG have been visited yet. */
111
kono
parents: 67
diff changeset
974 bitmap_clear (visited);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
975
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
976 /* Push the first edge on to the stack. */
111
kono
parents: 67
diff changeset
977 stack.quick_push (ei_start (ENTRY_BLOCK_PTR_FOR_FN (fn)->succs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
978
111
kono
parents: 67
diff changeset
979 while (!stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
980 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
981 basic_block src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
982 basic_block dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
983
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
984 /* Look at the edge on the top of the stack. */
111
kono
parents: 67
diff changeset
985 edge_iterator ei = stack.last ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
986 src = ei_edge (ei)->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
987 dest = ei_edge (ei)->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
988
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
989 /* Check if the edge destination has been visited yet. */
111
kono
parents: 67
diff changeset
990 if (dest != EXIT_BLOCK_PTR_FOR_FN (fn)
kono
parents: 67
diff changeset
991 && ! bitmap_bit_p (visited, dest->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
992 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
993 /* Mark that we have visited the destination. */
111
kono
parents: 67
diff changeset
994 bitmap_set_bit (visited, dest->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
995
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
996 if (pre_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
997 pre_order[pre_order_num] = dest->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
998
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
999 pre_order_num++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1000
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1001 if (EDGE_COUNT (dest->succs) > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1002 /* Since the DEST node has been visited for the first
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1003 time, check its successors. */
111
kono
parents: 67
diff changeset
1004 stack.quick_push (ei_start (dest->succs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1005 else if (rev_post_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1006 /* There are no successors for the DEST node so assign
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1007 its reverse completion number. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1008 rev_post_order[rev_post_order_num--] = dest->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1009 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1010 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1011 {
111
kono
parents: 67
diff changeset
1012 if (ei_one_before_end_p (ei)
kono
parents: 67
diff changeset
1013 && src != ENTRY_BLOCK_PTR_FOR_FN (fn)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1014 && rev_post_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1015 /* There are no more successors for the SRC node
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1016 so assign its reverse completion number. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1017 rev_post_order[rev_post_order_num--] = src->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1018
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1019 if (!ei_one_before_end_p (ei))
111
kono
parents: 67
diff changeset
1020 ei_next (&stack.last ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1021 else
111
kono
parents: 67
diff changeset
1022 stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1023 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1024 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1025
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1026 if (include_entry_exit)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1027 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1028 if (pre_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1029 pre_order[pre_order_num] = EXIT_BLOCK;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1030 pre_order_num++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1031 if (rev_post_order)
111
kono
parents: 67
diff changeset
1032 rev_post_order[rev_post_order_num--] = ENTRY_BLOCK;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1033 }
111
kono
parents: 67
diff changeset
1034
kono
parents: 67
diff changeset
1035 return pre_order_num;
kono
parents: 67
diff changeset
1036 }
kono
parents: 67
diff changeset
1037
kono
parents: 67
diff changeset
1038 /* Like pre_and_rev_post_order_compute_fn but operating on the
kono
parents: 67
diff changeset
1039 current function and asserting that all nodes were visited. */
kono
parents: 67
diff changeset
1040
kono
parents: 67
diff changeset
1041 int
kono
parents: 67
diff changeset
1042 pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
kono
parents: 67
diff changeset
1043 bool include_entry_exit)
kono
parents: 67
diff changeset
1044 {
kono
parents: 67
diff changeset
1045 int pre_order_num
kono
parents: 67
diff changeset
1046 = pre_and_rev_post_order_compute_fn (cfun, pre_order, rev_post_order,
kono
parents: 67
diff changeset
1047 include_entry_exit);
kono
parents: 67
diff changeset
1048 if (include_entry_exit)
kono
parents: 67
diff changeset
1049 /* The number of nodes visited should be the number of blocks. */
kono
parents: 67
diff changeset
1050 gcc_assert (pre_order_num == n_basic_blocks_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1051 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1052 /* The number of nodes visited should be the number of blocks minus
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1053 the entry and exit blocks which are not visited here. */
111
kono
parents: 67
diff changeset
1054 gcc_assert (pre_order_num
kono
parents: 67
diff changeset
1055 == (n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1056
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1057 return pre_order_num;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1058 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1059
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1060 /* Unlike pre_and_rev_post_order_compute we fill rev_post_order backwards
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1061 so iterating in RPO order needs to start with rev_post_order[n - 1]
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1062 going to rev_post_order[0]. If FOR_ITERATION is true then try to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1063 make CFG cycles fit into small contiguous regions of the RPO order.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1064 When FOR_ITERATION is true this requires up-to-date loop structures. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1065
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1066 int
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1067 rev_post_order_and_mark_dfs_back_seme (struct function *fn, edge entry,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1068 bitmap exit_bbs, bool for_iteration,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1069 int *rev_post_order)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1070 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1071 int pre_order_num = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1072 int rev_post_order_num = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1073
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1074 /* Allocate stack for back-tracking up CFG. Worst case we need
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1075 O(n^2) edges but the following should suffice in practice without
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1076 a need to re-allocate. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1077 auto_vec<edge, 20> stack (2 * n_basic_blocks_for_fn (fn));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1078
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1079 int *pre = XNEWVEC (int, 2 * last_basic_block_for_fn (fn));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1080 int *post = pre + last_basic_block_for_fn (fn);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1081
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1082 /* BB flag to track nodes that have been visited. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1083 auto_bb_flag visited (fn);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1084 /* BB flag to track which nodes have post[] assigned to avoid
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1085 zeroing post. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1086 auto_bb_flag post_assigned (fn);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1087
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1088 /* Push the first edge on to the stack. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1089 stack.quick_push (entry);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1090
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1091 while (!stack.is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1092 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1093 basic_block src;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1094 basic_block dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1095
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1096 /* Look at the edge on the top of the stack. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1097 int idx = stack.length () - 1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1098 edge e = stack[idx];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1099 src = e->src;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1100 dest = e->dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1101 e->flags &= ~EDGE_DFS_BACK;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1102
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1103 /* Check if the edge destination has been visited yet. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1104 if (! bitmap_bit_p (exit_bbs, dest->index)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1105 && ! (dest->flags & visited))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1106 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1107 /* Mark that we have visited the destination. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1108 dest->flags |= visited;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1109
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1110 pre[dest->index] = pre_order_num++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1111
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1112 if (EDGE_COUNT (dest->succs) > 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1113 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1114 /* Since the DEST node has been visited for the first
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1115 time, check its successors. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1116 /* Push the edge vector in reverse to match previous behavior. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1117 stack.reserve (EDGE_COUNT (dest->succs));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1118 for (int i = EDGE_COUNT (dest->succs) - 1; i >= 0; --i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1119 stack.quick_push (EDGE_SUCC (dest, i));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1120 /* Generalize to handle more successors? */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1121 if (for_iteration
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1122 && EDGE_COUNT (dest->succs) == 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1123 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1124 edge &e1 = stack[stack.length () - 2];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1125 if (loop_exit_edge_p (e1->src->loop_father, e1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1126 std::swap (e1, stack.last ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1127 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1128 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1129 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1130 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1131 /* There are no successors for the DEST node so assign
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1132 its reverse completion number. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1133 post[dest->index] = rev_post_order_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1134 dest->flags |= post_assigned;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1135 rev_post_order[rev_post_order_num] = dest->index;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1136 rev_post_order_num++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1137 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1138 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1139 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1140 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1141 if (dest->flags & visited
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1142 && src != entry->src
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1143 && pre[src->index] >= pre[dest->index]
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1144 && !(dest->flags & post_assigned))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1145 e->flags |= EDGE_DFS_BACK;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1146
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1147 if (idx != 0 && stack[idx - 1]->src != src)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1148 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1149 /* There are no more successors for the SRC node
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1150 so assign its reverse completion number. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1151 post[src->index] = rev_post_order_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1152 src->flags |= post_assigned;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1153 rev_post_order[rev_post_order_num] = src->index;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1154 rev_post_order_num++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1155 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1156
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1157 stack.pop ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1158 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1159 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1160
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1161 XDELETEVEC (pre);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1162
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1163 /* Clear the temporarily allocated flags. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1164 for (int i = 0; i < rev_post_order_num; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1165 BASIC_BLOCK_FOR_FN (fn, rev_post_order[i])->flags
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1166 &= ~(post_assigned|visited);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1167
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1168 return rev_post_order_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1169 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1170
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1171
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1172
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1173 /* Compute the depth first search order on the _reverse_ graph and
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1174 store it in the array DFS_ORDER, marking the nodes visited in VISITED.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1175 Returns the number of nodes visited.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1176
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1177 The computation is split into three pieces:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1178
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1179 flow_dfs_compute_reverse_init () creates the necessary data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1180 structures.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1181
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1182 flow_dfs_compute_reverse_add_bb () adds a basic block to the data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1183 structures. The block will start the search.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1184
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1185 flow_dfs_compute_reverse_execute () continues (or starts) the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1186 search using the block on the top of the stack, stopping when the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1187 stack is empty.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1188
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1189 flow_dfs_compute_reverse_finish () destroys the necessary data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1190 structures.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1191
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1192 Thus, the user will probably call ..._init(), call ..._add_bb() to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1193 add a beginning basic block to the stack, call ..._execute(),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1194 possibly add another bb to the stack and again call ..._execute(),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1195 ..., and finally call _finish(). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1196
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1197 /* Initialize the data structures used for depth-first search on the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1198 reverse graph. If INITIALIZE_STACK is nonzero, the exit block is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1199 added to the basic block stack. DATA is the current depth-first
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1200 search context. If INITIALIZE_STACK is nonzero, there is an
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1201 element on the stack. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1202
111
kono
parents: 67
diff changeset
1203 depth_first_search::depth_first_search () :
kono
parents: 67
diff changeset
1204 m_stack (n_basic_blocks_for_fn (cfun)),
kono
parents: 67
diff changeset
1205 m_visited_blocks (last_basic_block_for_fn (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1206 {
111
kono
parents: 67
diff changeset
1207 bitmap_clear (m_visited_blocks);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1208 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1209
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1210 /* Add the specified basic block to the top of the dfs data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1211 structures. When the search continues, it will start at the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1212 block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1213
111
kono
parents: 67
diff changeset
1214 void
kono
parents: 67
diff changeset
1215 depth_first_search::add_bb (basic_block bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1216 {
111
kono
parents: 67
diff changeset
1217 m_stack.quick_push (bb);
kono
parents: 67
diff changeset
1218 bitmap_set_bit (m_visited_blocks, bb->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1219 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1220
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1221 /* Continue the depth-first search through the reverse graph starting with the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1222 block at the stack's top and ending when the stack is empty. Visited nodes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1223 are marked. Returns an unvisited basic block, or NULL if there is none
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1224 available. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1225
111
kono
parents: 67
diff changeset
1226 basic_block
kono
parents: 67
diff changeset
1227 depth_first_search::execute (basic_block last_unvisited)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1228 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1229 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1230 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1231 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1232
111
kono
parents: 67
diff changeset
1233 while (!m_stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1234 {
111
kono
parents: 67
diff changeset
1235 bb = m_stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1236
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1237 /* Perform depth-first search on adjacent vertices. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1238 FOR_EACH_EDGE (e, ei, bb->preds)
111
kono
parents: 67
diff changeset
1239 if (!bitmap_bit_p (m_visited_blocks, e->src->index))
kono
parents: 67
diff changeset
1240 add_bb (e->src);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1241 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1242
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1243 /* Determine if there are unvisited basic blocks. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1244 FOR_BB_BETWEEN (bb, last_unvisited, NULL, prev_bb)
111
kono
parents: 67
diff changeset
1245 if (!bitmap_bit_p (m_visited_blocks, bb->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1246 return bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1247
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1248 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1249 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1250
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1251 /* Performs dfs search from BB over vertices satisfying PREDICATE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1252 if REVERSE, go against direction of edges. Returns number of blocks
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1253 found and their list in RSLT. RSLT can contain at most RSLT_MAX items. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1254 int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1255 dfs_enumerate_from (basic_block bb, int reverse,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1256 bool (*predicate) (const_basic_block, const void *),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1257 basic_block *rslt, int rslt_max, const void *data)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1258 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1259 basic_block *st, lbb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1260 int sp = 0, tv = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1261
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1262 auto_bb_flag visited (cfun);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1263
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1264 #define MARK_VISITED(BB) ((BB)->flags |= visited)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1265 #define UNMARK_VISITED(BB) ((BB)->flags &= ~visited)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1266 #define VISITED_P(BB) (((BB)->flags & visited) != 0)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1267
111
kono
parents: 67
diff changeset
1268 st = XNEWVEC (basic_block, rslt_max);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1269 rslt[tv++] = st[sp++] = bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1270 MARK_VISITED (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1271 while (sp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1272 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1273 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1274 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1275 lbb = st[--sp];
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1276 if (reverse)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1277 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1278 FOR_EACH_EDGE (e, ei, lbb->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1279 if (!VISITED_P (e->src) && predicate (e->src, data))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1280 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1281 gcc_assert (tv != rslt_max);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1282 rslt[tv++] = st[sp++] = e->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1283 MARK_VISITED (e->src);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1284 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1285 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1286 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1287 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1288 FOR_EACH_EDGE (e, ei, lbb->succs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1289 if (!VISITED_P (e->dest) && predicate (e->dest, data))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1290 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1291 gcc_assert (tv != rslt_max);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1292 rslt[tv++] = st[sp++] = e->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1293 MARK_VISITED (e->dest);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1294 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1295 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1296 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1297 free (st);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1298 for (sp = 0; sp < tv; sp++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1299 UNMARK_VISITED (rslt[sp]);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1300 return tv;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1301 #undef MARK_VISITED
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1302 #undef UNMARK_VISITED
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1303 #undef VISITED_P
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1304 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1305
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1306
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1307 /* Compute dominance frontiers, ala Harvey, Ferrante, et al.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1308
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1309 This algorithm can be found in Timothy Harvey's PhD thesis, at
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1310 http://www.cs.rice.edu/~harv/dissertation.pdf in the section on iterative
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1311 dominance algorithms.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1312
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1313 First, we identify each join point, j (any node with more than one
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1314 incoming edge is a join point).
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1315
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1316 We then examine each predecessor, p, of j and walk up the dominator tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1317 starting at p.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1318
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1319 We stop the walk when we reach j's immediate dominator - j is in the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1320 dominance frontier of each of the nodes in the walk, except for j's
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1321 immediate dominator. Intuitively, all of the rest of j's dominators are
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1322 shared by j's predecessors as well.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1323 Since they dominate j, they will not have j in their dominance frontiers.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1324
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1325 The number of nodes touched by this algorithm is equal to the size
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1326 of the dominance frontiers, no more, no less.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1327 */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1328
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1329
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1330 static void
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1331 compute_dominance_frontiers_1 (bitmap_head *frontiers)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1332 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1333 edge p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1334 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1335 basic_block b;
111
kono
parents: 67
diff changeset
1336 FOR_EACH_BB_FN (b, cfun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1337 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1338 if (EDGE_COUNT (b->preds) >= 2)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1339 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1340 FOR_EACH_EDGE (p, ei, b->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1341 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1342 basic_block runner = p->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1343 basic_block domsb;
111
kono
parents: 67
diff changeset
1344 if (runner == ENTRY_BLOCK_PTR_FOR_FN (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1345 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1346
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1347 domsb = get_immediate_dominator (CDI_DOMINATORS, b);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1348 while (runner != domsb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1349 {
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1350 if (!bitmap_set_bit (&frontiers[runner->index],
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1351 b->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1352 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1353 runner = get_immediate_dominator (CDI_DOMINATORS,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1354 runner);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1355 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1356 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1357 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1358 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1359 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1360
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1361
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1362 void
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1363 compute_dominance_frontiers (bitmap_head *frontiers)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1364 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1365 timevar_push (TV_DOM_FRONTIERS);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1366
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1367 compute_dominance_frontiers_1 (frontiers);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1368
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1369 timevar_pop (TV_DOM_FRONTIERS);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1370 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1371
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1372 /* Given a set of blocks with variable definitions (DEF_BLOCKS),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1373 return a bitmap with all the blocks in the iterated dominance
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1374 frontier of the blocks in DEF_BLOCKS. DFS contains dominance
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1375 frontier information as returned by compute_dominance_frontiers.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1376
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1377 The resulting set of blocks are the potential sites where PHI nodes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1378 are needed. The caller is responsible for freeing the memory
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1379 allocated for the return value. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1380
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1381 bitmap
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1382 compute_idf (bitmap def_blocks, bitmap_head *dfs)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1383 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1384 bitmap_iterator bi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1385 unsigned bb_index, i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1386 bitmap phi_insertion_points;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1387
111
kono
parents: 67
diff changeset
1388 /* Each block can appear at most twice on the work-stack. */
kono
parents: 67
diff changeset
1389 auto_vec<int> work_stack (2 * n_basic_blocks_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1390 phi_insertion_points = BITMAP_ALLOC (NULL);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1391
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1392 /* Seed the work list with all the blocks in DEF_BLOCKS. We use
111
kono
parents: 67
diff changeset
1393 vec::quick_push here for speed. This is safe because we know that
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1394 the number of definition blocks is no greater than the number of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1395 basic blocks, which is the initial capacity of WORK_STACK. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1396 EXECUTE_IF_SET_IN_BITMAP (def_blocks, 0, bb_index, bi)
111
kono
parents: 67
diff changeset
1397 work_stack.quick_push (bb_index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1398
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1399 /* Pop a block off the worklist, add every block that appears in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1400 the original block's DF that we have not already processed to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1401 the worklist. Iterate until the worklist is empty. Blocks
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1402 which are added to the worklist are potential sites for
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1403 PHI nodes. */
111
kono
parents: 67
diff changeset
1404 while (work_stack.length () > 0)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1405 {
111
kono
parents: 67
diff changeset
1406 bb_index = work_stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1407
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1408 /* Since the registration of NEW -> OLD name mappings is done
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1409 separately from the call to update_ssa, when updating the SSA
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1410 form, the basic blocks where new and/or old names are defined
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1411 may have disappeared by CFG cleanup calls. In this case,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1412 we may pull a non-existing block from the work stack. */
111
kono
parents: 67
diff changeset
1413 gcc_checking_assert (bb_index
kono
parents: 67
diff changeset
1414 < (unsigned) last_basic_block_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1415
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1416 EXECUTE_IF_AND_COMPL_IN_BITMAP (&dfs[bb_index], phi_insertion_points,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1417 0, i, bi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1418 {
111
kono
parents: 67
diff changeset
1419 work_stack.quick_push (i);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1420 bitmap_set_bit (phi_insertion_points, i);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1421 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1422 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1423
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1424 return phi_insertion_points;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1425 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1426
111
kono
parents: 67
diff changeset
1427 /* Intersection and union of preds/succs for sbitmap based data flow
kono
parents: 67
diff changeset
1428 solvers. All four functions defined below take the same arguments:
kono
parents: 67
diff changeset
1429 B is the basic block to perform the operation for. DST is the
kono
parents: 67
diff changeset
1430 target sbitmap, i.e. the result. SRC is an sbitmap vector of size
kono
parents: 67
diff changeset
1431 last_basic_block so that it can be indexed with basic block indices.
kono
parents: 67
diff changeset
1432 DST may be (but does not have to be) SRC[B->index]. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1433
111
kono
parents: 67
diff changeset
1434 /* Set the bitmap DST to the intersection of SRC of successors of
kono
parents: 67
diff changeset
1435 basic block B. */
kono
parents: 67
diff changeset
1436
kono
parents: 67
diff changeset
1437 void
kono
parents: 67
diff changeset
1438 bitmap_intersection_of_succs (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1439 {
kono
parents: 67
diff changeset
1440 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1441 edge e;
kono
parents: 67
diff changeset
1442 unsigned ix;
kono
parents: 67
diff changeset
1443
kono
parents: 67
diff changeset
1444 for (e = NULL, ix = 0; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1445 {
kono
parents: 67
diff changeset
1446 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1447 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1448 continue;
kono
parents: 67
diff changeset
1449
kono
parents: 67
diff changeset
1450 bitmap_copy (dst, src[e->dest->index]);
kono
parents: 67
diff changeset
1451 break;
kono
parents: 67
diff changeset
1452 }
kono
parents: 67
diff changeset
1453
kono
parents: 67
diff changeset
1454 if (e == 0)
kono
parents: 67
diff changeset
1455 bitmap_ones (dst);
kono
parents: 67
diff changeset
1456 else
kono
parents: 67
diff changeset
1457 for (++ix; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1458 {
kono
parents: 67
diff changeset
1459 unsigned int i;
kono
parents: 67
diff changeset
1460 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1461
kono
parents: 67
diff changeset
1462 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1463 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1464 continue;
kono
parents: 67
diff changeset
1465
kono
parents: 67
diff changeset
1466 p = src[e->dest->index]->elms;
kono
parents: 67
diff changeset
1467 r = dst->elms;
kono
parents: 67
diff changeset
1468 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1469 *r++ &= *p++;
kono
parents: 67
diff changeset
1470 }
kono
parents: 67
diff changeset
1471 }
kono
parents: 67
diff changeset
1472
kono
parents: 67
diff changeset
1473 /* Set the bitmap DST to the intersection of SRC of predecessors of
kono
parents: 67
diff changeset
1474 basic block B. */
kono
parents: 67
diff changeset
1475
kono
parents: 67
diff changeset
1476 void
kono
parents: 67
diff changeset
1477 bitmap_intersection_of_preds (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1478 {
kono
parents: 67
diff changeset
1479 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1480 edge e;
kono
parents: 67
diff changeset
1481 unsigned ix;
kono
parents: 67
diff changeset
1482
kono
parents: 67
diff changeset
1483 for (e = NULL, ix = 0; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1484 {
kono
parents: 67
diff changeset
1485 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1486 if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1487 continue;
kono
parents: 67
diff changeset
1488
kono
parents: 67
diff changeset
1489 bitmap_copy (dst, src[e->src->index]);
kono
parents: 67
diff changeset
1490 break;
kono
parents: 67
diff changeset
1491 }
kono
parents: 67
diff changeset
1492
kono
parents: 67
diff changeset
1493 if (e == 0)
kono
parents: 67
diff changeset
1494 bitmap_ones (dst);
kono
parents: 67
diff changeset
1495 else
kono
parents: 67
diff changeset
1496 for (++ix; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1497 {
kono
parents: 67
diff changeset
1498 unsigned int i;
kono
parents: 67
diff changeset
1499 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1500
kono
parents: 67
diff changeset
1501 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1502 if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1503 continue;
kono
parents: 67
diff changeset
1504
kono
parents: 67
diff changeset
1505 p = src[e->src->index]->elms;
kono
parents: 67
diff changeset
1506 r = dst->elms;
kono
parents: 67
diff changeset
1507 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1508 *r++ &= *p++;
kono
parents: 67
diff changeset
1509 }
kono
parents: 67
diff changeset
1510 }
kono
parents: 67
diff changeset
1511
kono
parents: 67
diff changeset
1512 /* Set the bitmap DST to the union of SRC of successors of
kono
parents: 67
diff changeset
1513 basic block B. */
kono
parents: 67
diff changeset
1514
kono
parents: 67
diff changeset
1515 void
kono
parents: 67
diff changeset
1516 bitmap_union_of_succs (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1517 {
kono
parents: 67
diff changeset
1518 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1519 edge e;
kono
parents: 67
diff changeset
1520 unsigned ix;
kono
parents: 67
diff changeset
1521
kono
parents: 67
diff changeset
1522 for (ix = 0; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1523 {
kono
parents: 67
diff changeset
1524 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1525 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1526 continue;
kono
parents: 67
diff changeset
1527
kono
parents: 67
diff changeset
1528 bitmap_copy (dst, src[e->dest->index]);
kono
parents: 67
diff changeset
1529 break;
kono
parents: 67
diff changeset
1530 }
kono
parents: 67
diff changeset
1531
kono
parents: 67
diff changeset
1532 if (ix == EDGE_COUNT (b->succs))
kono
parents: 67
diff changeset
1533 bitmap_clear (dst);
kono
parents: 67
diff changeset
1534 else
kono
parents: 67
diff changeset
1535 for (ix++; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1536 {
kono
parents: 67
diff changeset
1537 unsigned int i;
kono
parents: 67
diff changeset
1538 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1539
kono
parents: 67
diff changeset
1540 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1541 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1542 continue;
kono
parents: 67
diff changeset
1543
kono
parents: 67
diff changeset
1544 p = src[e->dest->index]->elms;
kono
parents: 67
diff changeset
1545 r = dst->elms;
kono
parents: 67
diff changeset
1546 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1547 *r++ |= *p++;
kono
parents: 67
diff changeset
1548 }
kono
parents: 67
diff changeset
1549 }
kono
parents: 67
diff changeset
1550
kono
parents: 67
diff changeset
1551 /* Set the bitmap DST to the union of SRC of predecessors of
kono
parents: 67
diff changeset
1552 basic block B. */
kono
parents: 67
diff changeset
1553
kono
parents: 67
diff changeset
1554 void
kono
parents: 67
diff changeset
1555 bitmap_union_of_preds (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1556 {
kono
parents: 67
diff changeset
1557 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1558 edge e;
kono
parents: 67
diff changeset
1559 unsigned ix;
kono
parents: 67
diff changeset
1560
kono
parents: 67
diff changeset
1561 for (ix = 0; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1562 {
kono
parents: 67
diff changeset
1563 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1564 if (e->src== ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1565 continue;
kono
parents: 67
diff changeset
1566
kono
parents: 67
diff changeset
1567 bitmap_copy (dst, src[e->src->index]);
kono
parents: 67
diff changeset
1568 break;
kono
parents: 67
diff changeset
1569 }
kono
parents: 67
diff changeset
1570
kono
parents: 67
diff changeset
1571 if (ix == EDGE_COUNT (b->preds))
kono
parents: 67
diff changeset
1572 bitmap_clear (dst);
kono
parents: 67
diff changeset
1573 else
kono
parents: 67
diff changeset
1574 for (ix++; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1575 {
kono
parents: 67
diff changeset
1576 unsigned int i;
kono
parents: 67
diff changeset
1577 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1578
kono
parents: 67
diff changeset
1579 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1580 if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1581 continue;
kono
parents: 67
diff changeset
1582
kono
parents: 67
diff changeset
1583 p = src[e->src->index]->elms;
kono
parents: 67
diff changeset
1584 r = dst->elms;
kono
parents: 67
diff changeset
1585 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1586 *r++ |= *p++;
kono
parents: 67
diff changeset
1587 }
kono
parents: 67
diff changeset
1588 }
kono
parents: 67
diff changeset
1589
kono
parents: 67
diff changeset
1590 /* Returns the list of basic blocks in the function in an order that guarantees
kono
parents: 67
diff changeset
1591 that if a block X has just a single predecessor Y, then Y is after X in the
kono
parents: 67
diff changeset
1592 ordering. */
kono
parents: 67
diff changeset
1593
kono
parents: 67
diff changeset
1594 basic_block *
kono
parents: 67
diff changeset
1595 single_pred_before_succ_order (void)
kono
parents: 67
diff changeset
1596 {
kono
parents: 67
diff changeset
1597 basic_block x, y;
kono
parents: 67
diff changeset
1598 basic_block *order = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
kono
parents: 67
diff changeset
1599 unsigned n = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
kono
parents: 67
diff changeset
1600 unsigned np, i;
kono
parents: 67
diff changeset
1601 auto_sbitmap visited (last_basic_block_for_fn (cfun));
kono
parents: 67
diff changeset
1602
kono
parents: 67
diff changeset
1603 #define MARK_VISITED(BB) (bitmap_set_bit (visited, (BB)->index))
kono
parents: 67
diff changeset
1604 #define VISITED_P(BB) (bitmap_bit_p (visited, (BB)->index))
kono
parents: 67
diff changeset
1605
kono
parents: 67
diff changeset
1606 bitmap_clear (visited);
kono
parents: 67
diff changeset
1607
kono
parents: 67
diff changeset
1608 MARK_VISITED (ENTRY_BLOCK_PTR_FOR_FN (cfun));
kono
parents: 67
diff changeset
1609 FOR_EACH_BB_FN (x, cfun)
kono
parents: 67
diff changeset
1610 {
kono
parents: 67
diff changeset
1611 if (VISITED_P (x))
kono
parents: 67
diff changeset
1612 continue;
kono
parents: 67
diff changeset
1613
kono
parents: 67
diff changeset
1614 /* Walk the predecessors of x as long as they have precisely one
kono
parents: 67
diff changeset
1615 predecessor and add them to the list, so that they get stored
kono
parents: 67
diff changeset
1616 after x. */
kono
parents: 67
diff changeset
1617 for (y = x, np = 1;
kono
parents: 67
diff changeset
1618 single_pred_p (y) && !VISITED_P (single_pred (y));
kono
parents: 67
diff changeset
1619 y = single_pred (y))
kono
parents: 67
diff changeset
1620 np++;
kono
parents: 67
diff changeset
1621 for (y = x, i = n - np;
kono
parents: 67
diff changeset
1622 single_pred_p (y) && !VISITED_P (single_pred (y));
kono
parents: 67
diff changeset
1623 y = single_pred (y), i++)
kono
parents: 67
diff changeset
1624 {
kono
parents: 67
diff changeset
1625 order[i] = y;
kono
parents: 67
diff changeset
1626 MARK_VISITED (y);
kono
parents: 67
diff changeset
1627 }
kono
parents: 67
diff changeset
1628 order[i] = y;
kono
parents: 67
diff changeset
1629 MARK_VISITED (y);
kono
parents: 67
diff changeset
1630
kono
parents: 67
diff changeset
1631 gcc_assert (i == n - 1);
kono
parents: 67
diff changeset
1632 n -= np;
kono
parents: 67
diff changeset
1633 }
kono
parents: 67
diff changeset
1634
kono
parents: 67
diff changeset
1635 gcc_assert (n == 0);
kono
parents: 67
diff changeset
1636 return order;
kono
parents: 67
diff changeset
1637
kono
parents: 67
diff changeset
1638 #undef MARK_VISITED
kono
parents: 67
diff changeset
1639 #undef VISITED_P
kono
parents: 67
diff changeset
1640 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1641
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1642 /* Ignoring loop backedges, if BB has precisely one incoming edge then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1643 return that edge. Otherwise return NULL.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1644
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1645 When IGNORE_NOT_EXECUTABLE is true, also ignore edges that are not marked
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1646 as executable. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1647
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1648 edge
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1649 single_pred_edge_ignoring_loop_edges (basic_block bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1650 bool ignore_not_executable)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1651 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1652 edge retval = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1653 edge e;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1654 edge_iterator ei;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1655
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1656 FOR_EACH_EDGE (e, ei, bb->preds)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1657 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1658 /* A loop back edge can be identified by the destination of
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1659 the edge dominating the source of the edge. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1660 if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1661 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1662
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1663 /* We can safely ignore edges that are not executable. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1664 if (ignore_not_executable
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1665 && (e->flags & EDGE_EXECUTABLE) == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1666 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1667
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1668 /* If we have already seen a non-loop edge, then we must have
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1669 multiple incoming non-loop edges and thus we return NULL. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1670 if (retval)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1671 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1672
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1673 /* This is the first non-loop incoming edge we have found. Record
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1674 it. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1675 retval = e;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1676 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1677
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1678 return retval;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1679 }