annotate gcc/cfganal.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
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.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 1987-2020 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;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
954 int rev_post_order_num = n_basic_blocks_for_fn (fn) - 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. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
957 auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (fn) + 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
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
970 /* BB flag to track nodes that have been visited. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
971 auto_bb_flag visited (fn);
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 /* Push the first edge on to the stack. */
111
kono
parents: 67
diff changeset
974 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
975
111
kono
parents: 67
diff changeset
976 while (!stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
977 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
978 basic_block src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
979 basic_block dest;
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 /* Look at the edge on the top of the stack. */
111
kono
parents: 67
diff changeset
982 edge_iterator ei = stack.last ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
983 src = ei_edge (ei)->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
984 dest = ei_edge (ei)->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
985
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
986 /* Check if the edge destination has been visited yet. */
111
kono
parents: 67
diff changeset
987 if (dest != EXIT_BLOCK_PTR_FOR_FN (fn)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
988 && ! (dest->flags & visited))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
989 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
990 /* Mark that we have visited the destination. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
991 dest->flags |= visited;
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 if (pre_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
994 pre_order[pre_order_num] = dest->index;
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 pre_order_num++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
997
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
998 if (EDGE_COUNT (dest->succs) > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
999 /* Since the DEST node has been visited for the first
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1000 time, check its successors. */
111
kono
parents: 67
diff changeset
1001 stack.quick_push (ei_start (dest->succs));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1002 else if (rev_post_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1003 /* There are no successors for the DEST node so assign
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1004 its reverse completion number. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1005 rev_post_order[rev_post_order_num--] = dest->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1006 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1007 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1008 {
111
kono
parents: 67
diff changeset
1009 if (ei_one_before_end_p (ei)
kono
parents: 67
diff changeset
1010 && src != ENTRY_BLOCK_PTR_FOR_FN (fn)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1011 && rev_post_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1012 /* There are no more successors for the SRC node
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1013 so assign its reverse completion number. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1014 rev_post_order[rev_post_order_num--] = src->index;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1015
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1016 if (!ei_one_before_end_p (ei))
111
kono
parents: 67
diff changeset
1017 ei_next (&stack.last ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1018 else
111
kono
parents: 67
diff changeset
1019 stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1020 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1021 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1022
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1023 if (include_entry_exit)
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 if (pre_order)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1026 pre_order[pre_order_num] = EXIT_BLOCK;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1027 pre_order_num++;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1028 if (rev_post_order)
111
kono
parents: 67
diff changeset
1029 rev_post_order[rev_post_order_num--] = ENTRY_BLOCK;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1030 }
111
kono
parents: 67
diff changeset
1031
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1032 /* Clear the temporarily allocated flag. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1033 if (!rev_post_order)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1034 rev_post_order = pre_order;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1035 for (int i = 0; i < pre_order_num; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1036 BASIC_BLOCK_FOR_FN (fn, rev_post_order[i])->flags &= ~visited;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1037
111
kono
parents: 67
diff changeset
1038 return pre_order_num;
kono
parents: 67
diff changeset
1039 }
kono
parents: 67
diff changeset
1040
kono
parents: 67
diff changeset
1041 /* Like pre_and_rev_post_order_compute_fn but operating on the
kono
parents: 67
diff changeset
1042 current function and asserting that all nodes were visited. */
kono
parents: 67
diff changeset
1043
kono
parents: 67
diff changeset
1044 int
kono
parents: 67
diff changeset
1045 pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
kono
parents: 67
diff changeset
1046 bool include_entry_exit)
kono
parents: 67
diff changeset
1047 {
kono
parents: 67
diff changeset
1048 int pre_order_num
kono
parents: 67
diff changeset
1049 = pre_and_rev_post_order_compute_fn (cfun, pre_order, rev_post_order,
kono
parents: 67
diff changeset
1050 include_entry_exit);
kono
parents: 67
diff changeset
1051 if (include_entry_exit)
kono
parents: 67
diff changeset
1052 /* The number of nodes visited should be the number of blocks. */
kono
parents: 67
diff changeset
1053 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
1054 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1055 /* 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
1056 the entry and exit blocks which are not visited here. */
111
kono
parents: 67
diff changeset
1057 gcc_assert (pre_order_num
kono
parents: 67
diff changeset
1058 == (n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1059
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1060 return pre_order_num;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1061 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1062
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1063 /* Unlike pre_and_rev_post_order_compute we fill rev_post_order backwards
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1064 so iterating in RPO order needs to start with rev_post_order[n - 1]
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1065 going to rev_post_order[0]. If FOR_ITERATION is true then try to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1066 make CFG cycles fit into small contiguous regions of the RPO order.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1067 When FOR_ITERATION is true this requires up-to-date loop structures. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1068
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1069 int
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1070 rev_post_order_and_mark_dfs_back_seme (struct function *fn, edge entry,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1071 bitmap exit_bbs, bool for_iteration,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1072 int *rev_post_order)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1073 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1074 int pre_order_num = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1075 int rev_post_order_num = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1076
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1077 /* Allocate stack for back-tracking up CFG. Worst case we need
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1078 O(n^2) edges but the following should suffice in practice without
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1079 a need to re-allocate. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1080 auto_vec<edge, 20> stack (2 * n_basic_blocks_for_fn (fn));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1081
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1082 int *pre = XNEWVEC (int, 2 * last_basic_block_for_fn (fn));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1083 int *post = pre + last_basic_block_for_fn (fn);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1084
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1085 /* BB flag to track nodes that have been visited. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1086 auto_bb_flag visited (fn);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1087 /* BB flag to track which nodes have post[] assigned to avoid
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1088 zeroing post. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1089 auto_bb_flag post_assigned (fn);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1090
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1091 /* Push the first edge on to the stack. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1092 stack.quick_push (entry);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1093
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1094 while (!stack.is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1095 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1096 basic_block src;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1097 basic_block dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1098
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1099 /* Look at the edge on the top of the stack. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1100 int idx = stack.length () - 1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1101 edge e = stack[idx];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1102 src = e->src;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1103 dest = e->dest;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1104 e->flags &= ~EDGE_DFS_BACK;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1105
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1106 /* Check if the edge destination has been visited yet. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1107 if (! bitmap_bit_p (exit_bbs, dest->index)
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 /* Mark that we have visited the destination. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1111 dest->flags |= visited;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1112
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1113 pre[dest->index] = pre_order_num++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1114
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1115 if (EDGE_COUNT (dest->succs) > 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1116 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1117 /* Since the DEST node has been visited for the first
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1118 time, check its successors. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1119 /* Push the edge vector in reverse to match previous behavior. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1120 stack.reserve (EDGE_COUNT (dest->succs));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1121 for (int i = EDGE_COUNT (dest->succs) - 1; i >= 0; --i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1122 stack.quick_push (EDGE_SUCC (dest, i));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1123 /* Generalize to handle more successors? */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1124 if (for_iteration
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1125 && EDGE_COUNT (dest->succs) == 2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1126 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1127 edge &e1 = stack[stack.length () - 2];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1128 if (loop_exit_edge_p (e1->src->loop_father, e1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1129 std::swap (e1, stack.last ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1130 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1131 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1132 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1133 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1134 /* There are no successors for the DEST node so assign
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1135 its reverse completion number. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1136 post[dest->index] = rev_post_order_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1137 dest->flags |= post_assigned;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1138 rev_post_order[rev_post_order_num] = dest->index;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1139 rev_post_order_num++;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1140 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1141 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1142 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1143 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1144 if (dest->flags & visited
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1145 && src != entry->src
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1146 && pre[src->index] >= pre[dest->index]
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1147 && !(dest->flags & post_assigned))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1148 e->flags |= EDGE_DFS_BACK;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1149
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1150 if (idx != 0 && stack[idx - 1]->src != src)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1151 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1152 /* There are no more successors for the SRC node
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1153 so assign its reverse completion number. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1154 post[src->index] = rev_post_order_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1155 src->flags |= post_assigned;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1156 rev_post_order[rev_post_order_num] = src->index;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1157 rev_post_order_num++;
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 stack.pop ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1161 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1162 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1163
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1164 XDELETEVEC (pre);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1165
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1166 /* Clear the temporarily allocated flags. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1167 for (int i = 0; i < rev_post_order_num; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1168 BASIC_BLOCK_FOR_FN (fn, rev_post_order[i])->flags
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1169 &= ~(post_assigned|visited);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1170
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1171 return rev_post_order_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1172 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1173
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1174
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1175
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1176 /* Compute the depth first search order on the _reverse_ graph and
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1177 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
1178 Returns the number of nodes visited.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1179
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1180 The computation is split into three pieces:
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_init () creates the necessary data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1183 structures.
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_add_bb () adds a basic block to the data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1186 structures. The block will start the search.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1187
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1188 flow_dfs_compute_reverse_execute () continues (or starts) the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1189 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
1190 stack is empty.
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 flow_dfs_compute_reverse_finish () destroys the necessary data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1193 structures.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1194
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1195 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
1196 add a beginning basic block to the stack, call ..._execute(),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1197 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
1198 ..., and finally call _finish(). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1199
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1200 /* 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
1201 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
1202 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
1203 search context. If INITIALIZE_STACK is nonzero, there is an
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1204 element on the stack. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1205
111
kono
parents: 67
diff changeset
1206 depth_first_search::depth_first_search () :
kono
parents: 67
diff changeset
1207 m_stack (n_basic_blocks_for_fn (cfun)),
kono
parents: 67
diff changeset
1208 m_visited_blocks (last_basic_block_for_fn (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1209 {
111
kono
parents: 67
diff changeset
1210 bitmap_clear (m_visited_blocks);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1211 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1212
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1213 /* 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
1214 structures. When the search continues, it will start at the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1215 block. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1216
111
kono
parents: 67
diff changeset
1217 void
kono
parents: 67
diff changeset
1218 depth_first_search::add_bb (basic_block bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1219 {
111
kono
parents: 67
diff changeset
1220 m_stack.quick_push (bb);
kono
parents: 67
diff changeset
1221 bitmap_set_bit (m_visited_blocks, bb->index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1222 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1223
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1224 /* 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
1225 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
1226 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
1227 available. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1228
111
kono
parents: 67
diff changeset
1229 basic_block
kono
parents: 67
diff changeset
1230 depth_first_search::execute (basic_block last_unvisited)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1231 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1232 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1233 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1234 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1235
111
kono
parents: 67
diff changeset
1236 while (!m_stack.is_empty ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1237 {
111
kono
parents: 67
diff changeset
1238 bb = m_stack.pop ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1239
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1240 /* Perform depth-first search on adjacent vertices. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1241 FOR_EACH_EDGE (e, ei, bb->preds)
111
kono
parents: 67
diff changeset
1242 if (!bitmap_bit_p (m_visited_blocks, e->src->index))
kono
parents: 67
diff changeset
1243 add_bb (e->src);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1244 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1245
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1246 /* Determine if there are unvisited basic blocks. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1247 FOR_BB_BETWEEN (bb, last_unvisited, NULL, prev_bb)
111
kono
parents: 67
diff changeset
1248 if (!bitmap_bit_p (m_visited_blocks, bb->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1249 return bb;
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 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1252 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1253
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1254 /* Performs dfs search from BB over vertices satisfying PREDICATE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1255 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
1256 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
1257 int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1258 dfs_enumerate_from (basic_block bb, int reverse,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1259 bool (*predicate) (const_basic_block, const void *),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1260 basic_block *rslt, int rslt_max, const void *data)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1261 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1262 basic_block *st, lbb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1263 int sp = 0, tv = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1264
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1265 auto_bb_flag visited (cfun);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1266
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1267 #define MARK_VISITED(BB) ((BB)->flags |= visited)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1268 #define UNMARK_VISITED(BB) ((BB)->flags &= ~visited)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1269 #define VISITED_P(BB) (((BB)->flags & visited) != 0)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1270
111
kono
parents: 67
diff changeset
1271 st = XNEWVEC (basic_block, rslt_max);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1272 rslt[tv++] = st[sp++] = bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1273 MARK_VISITED (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1274 while (sp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1275 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1276 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1277 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1278 lbb = st[--sp];
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1279 if (reverse)
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 FOR_EACH_EDGE (e, ei, lbb->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1282 if (!VISITED_P (e->src) && predicate (e->src, data))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1283 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1284 gcc_assert (tv != rslt_max);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1285 rslt[tv++] = st[sp++] = e->src;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1286 MARK_VISITED (e->src);
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 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1289 else
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 FOR_EACH_EDGE (e, ei, lbb->succs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1292 if (!VISITED_P (e->dest) && predicate (e->dest, data))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1293 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1294 gcc_assert (tv != rslt_max);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1295 rslt[tv++] = st[sp++] = e->dest;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1296 MARK_VISITED (e->dest);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1297 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1298 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1299 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1300 free (st);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1301 for (sp = 0; sp < tv; sp++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1302 UNMARK_VISITED (rslt[sp]);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1303 return tv;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1304 #undef MARK_VISITED
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1305 #undef UNMARK_VISITED
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1306 #undef VISITED_P
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1307 }
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
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1310 /* Compute dominance frontiers, ala Harvey, Ferrante, et al.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1311
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1312 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
1313 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
1314 dominance algorithms.
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 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
1317 incoming edge is a join point).
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 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
1320 starting at p.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1321
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1322 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
1323 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
1324 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
1325 shared by j's predecessors as well.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1326 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
1327
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1328 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
1329 of the dominance frontiers, no more, no less.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1330 */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1331
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1332 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1333 compute_dominance_frontiers (bitmap_head *frontiers)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1334 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1335 timevar_push (TV_DOM_FRONTIERS);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1336
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1337 edge p;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1338 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1339 basic_block b;
111
kono
parents: 67
diff changeset
1340 FOR_EACH_BB_FN (b, cfun)
0
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 if (EDGE_COUNT (b->preds) >= 2)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1343 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1344 basic_block domsb = get_immediate_dominator (CDI_DOMINATORS, b);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1345 FOR_EACH_EDGE (p, ei, b->preds)
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 basic_block runner = p->src;
111
kono
parents: 67
diff changeset
1348 if (runner == ENTRY_BLOCK_PTR_FOR_FN (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1349 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1350
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1351 while (runner != domsb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1352 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1353 if (!bitmap_set_bit (&frontiers[runner->index], b->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1354 break;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1355 runner = get_immediate_dominator (CDI_DOMINATORS, runner);
0
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 timevar_pop (TV_DOM_FRONTIERS);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1362 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1363
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1364 /* Given a set of blocks with variable definitions (DEF_BLOCKS),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1365 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
1366 frontier of the blocks in DEF_BLOCKS. DFS contains dominance
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1367 frontier information as returned by compute_dominance_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 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
1370 are needed. The caller is responsible for freeing the memory
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1371 allocated for the return value. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1372
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1373 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
1374 compute_idf (bitmap def_blocks, bitmap_head *dfs)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1375 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1376 bitmap_iterator bi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1377 unsigned bb_index, i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1378 bitmap phi_insertion_points;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1379
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1380 phi_insertion_points = BITMAP_ALLOC (NULL);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1381
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1382 /* Seed the work set with all the blocks in DEF_BLOCKS. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1383 auto_bitmap work_set;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1384 bitmap_copy (work_set, def_blocks);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1385 bitmap_tree_view (work_set);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1386
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1387 /* Pop a block off the workset, add every block that appears in
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1388 the original block's DF that we have not already processed to
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1389 the workset. Iterate until the workset is empty. Blocks
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1390 which are added to the workset are potential sites for
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1391 PHI nodes. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1392 while (!bitmap_empty_p (work_set))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1393 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1394 /* The dominance frontier of a block is blocks after it so iterating
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1395 on earlier blocks first is better.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1396 ??? Basic blocks are by no means guaranteed to be ordered in
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1397 optimal order for this iteration. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1398 bb_index = bitmap_first_set_bit (work_set);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1399 bitmap_clear_bit (work_set, bb_index);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1400
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1401 /* Since the registration of NEW -> OLD name mappings is done
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1402 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
1403 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
1404 may have disappeared by CFG cleanup calls. In this case,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1405 we may pull a non-existing block from the work stack. */
111
kono
parents: 67
diff changeset
1406 gcc_checking_assert (bb_index
kono
parents: 67
diff changeset
1407 < (unsigned) last_basic_block_for_fn (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1408
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
1409 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
1410 0, i, bi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1411 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1412 bitmap_set_bit (work_set, i);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1413 bitmap_set_bit (phi_insertion_points, i);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1414 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1415 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1416
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1417 return phi_insertion_points;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1418 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1419
111
kono
parents: 67
diff changeset
1420 /* Intersection and union of preds/succs for sbitmap based data flow
kono
parents: 67
diff changeset
1421 solvers. All four functions defined below take the same arguments:
kono
parents: 67
diff changeset
1422 B is the basic block to perform the operation for. DST is the
kono
parents: 67
diff changeset
1423 target sbitmap, i.e. the result. SRC is an sbitmap vector of size
kono
parents: 67
diff changeset
1424 last_basic_block so that it can be indexed with basic block indices.
kono
parents: 67
diff changeset
1425 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
1426
111
kono
parents: 67
diff changeset
1427 /* Set the bitmap DST to the intersection of SRC of successors of
kono
parents: 67
diff changeset
1428 basic block B. */
kono
parents: 67
diff changeset
1429
kono
parents: 67
diff changeset
1430 void
kono
parents: 67
diff changeset
1431 bitmap_intersection_of_succs (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1432 {
kono
parents: 67
diff changeset
1433 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1434 edge e;
kono
parents: 67
diff changeset
1435 unsigned ix;
kono
parents: 67
diff changeset
1436
kono
parents: 67
diff changeset
1437 for (e = NULL, ix = 0; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1438 {
kono
parents: 67
diff changeset
1439 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1440 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1441 continue;
kono
parents: 67
diff changeset
1442
kono
parents: 67
diff changeset
1443 bitmap_copy (dst, src[e->dest->index]);
kono
parents: 67
diff changeset
1444 break;
kono
parents: 67
diff changeset
1445 }
kono
parents: 67
diff changeset
1446
kono
parents: 67
diff changeset
1447 if (e == 0)
kono
parents: 67
diff changeset
1448 bitmap_ones (dst);
kono
parents: 67
diff changeset
1449 else
kono
parents: 67
diff changeset
1450 for (++ix; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1451 {
kono
parents: 67
diff changeset
1452 unsigned int i;
kono
parents: 67
diff changeset
1453 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1454
kono
parents: 67
diff changeset
1455 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1456 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1457 continue;
kono
parents: 67
diff changeset
1458
kono
parents: 67
diff changeset
1459 p = src[e->dest->index]->elms;
kono
parents: 67
diff changeset
1460 r = dst->elms;
kono
parents: 67
diff changeset
1461 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1462 *r++ &= *p++;
kono
parents: 67
diff changeset
1463 }
kono
parents: 67
diff changeset
1464 }
kono
parents: 67
diff changeset
1465
kono
parents: 67
diff changeset
1466 /* Set the bitmap DST to the intersection of SRC of predecessors of
kono
parents: 67
diff changeset
1467 basic block B. */
kono
parents: 67
diff changeset
1468
kono
parents: 67
diff changeset
1469 void
kono
parents: 67
diff changeset
1470 bitmap_intersection_of_preds (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1471 {
kono
parents: 67
diff changeset
1472 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1473 edge e;
kono
parents: 67
diff changeset
1474 unsigned ix;
kono
parents: 67
diff changeset
1475
kono
parents: 67
diff changeset
1476 for (e = NULL, ix = 0; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1477 {
kono
parents: 67
diff changeset
1478 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1479 if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1480 continue;
kono
parents: 67
diff changeset
1481
kono
parents: 67
diff changeset
1482 bitmap_copy (dst, src[e->src->index]);
kono
parents: 67
diff changeset
1483 break;
kono
parents: 67
diff changeset
1484 }
kono
parents: 67
diff changeset
1485
kono
parents: 67
diff changeset
1486 if (e == 0)
kono
parents: 67
diff changeset
1487 bitmap_ones (dst);
kono
parents: 67
diff changeset
1488 else
kono
parents: 67
diff changeset
1489 for (++ix; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1490 {
kono
parents: 67
diff changeset
1491 unsigned int i;
kono
parents: 67
diff changeset
1492 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1493
kono
parents: 67
diff changeset
1494 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1495 if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1496 continue;
kono
parents: 67
diff changeset
1497
kono
parents: 67
diff changeset
1498 p = src[e->src->index]->elms;
kono
parents: 67
diff changeset
1499 r = dst->elms;
kono
parents: 67
diff changeset
1500 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1501 *r++ &= *p++;
kono
parents: 67
diff changeset
1502 }
kono
parents: 67
diff changeset
1503 }
kono
parents: 67
diff changeset
1504
kono
parents: 67
diff changeset
1505 /* Set the bitmap DST to the union of SRC of successors of
kono
parents: 67
diff changeset
1506 basic block B. */
kono
parents: 67
diff changeset
1507
kono
parents: 67
diff changeset
1508 void
kono
parents: 67
diff changeset
1509 bitmap_union_of_succs (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1510 {
kono
parents: 67
diff changeset
1511 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1512 edge e;
kono
parents: 67
diff changeset
1513 unsigned ix;
kono
parents: 67
diff changeset
1514
kono
parents: 67
diff changeset
1515 for (ix = 0; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1516 {
kono
parents: 67
diff changeset
1517 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1518 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1519 continue;
kono
parents: 67
diff changeset
1520
kono
parents: 67
diff changeset
1521 bitmap_copy (dst, src[e->dest->index]);
kono
parents: 67
diff changeset
1522 break;
kono
parents: 67
diff changeset
1523 }
kono
parents: 67
diff changeset
1524
kono
parents: 67
diff changeset
1525 if (ix == EDGE_COUNT (b->succs))
kono
parents: 67
diff changeset
1526 bitmap_clear (dst);
kono
parents: 67
diff changeset
1527 else
kono
parents: 67
diff changeset
1528 for (ix++; ix < EDGE_COUNT (b->succs); ix++)
kono
parents: 67
diff changeset
1529 {
kono
parents: 67
diff changeset
1530 unsigned int i;
kono
parents: 67
diff changeset
1531 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1532
kono
parents: 67
diff changeset
1533 e = EDGE_SUCC (b, ix);
kono
parents: 67
diff changeset
1534 if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1535 continue;
kono
parents: 67
diff changeset
1536
kono
parents: 67
diff changeset
1537 p = src[e->dest->index]->elms;
kono
parents: 67
diff changeset
1538 r = dst->elms;
kono
parents: 67
diff changeset
1539 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1540 *r++ |= *p++;
kono
parents: 67
diff changeset
1541 }
kono
parents: 67
diff changeset
1542 }
kono
parents: 67
diff changeset
1543
kono
parents: 67
diff changeset
1544 /* Set the bitmap DST to the union of SRC of predecessors of
kono
parents: 67
diff changeset
1545 basic block B. */
kono
parents: 67
diff changeset
1546
kono
parents: 67
diff changeset
1547 void
kono
parents: 67
diff changeset
1548 bitmap_union_of_preds (sbitmap dst, sbitmap *src, basic_block b)
kono
parents: 67
diff changeset
1549 {
kono
parents: 67
diff changeset
1550 unsigned int set_size = dst->size;
kono
parents: 67
diff changeset
1551 edge e;
kono
parents: 67
diff changeset
1552 unsigned ix;
kono
parents: 67
diff changeset
1553
kono
parents: 67
diff changeset
1554 for (ix = 0; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1555 {
kono
parents: 67
diff changeset
1556 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1557 if (e->src== ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1558 continue;
kono
parents: 67
diff changeset
1559
kono
parents: 67
diff changeset
1560 bitmap_copy (dst, src[e->src->index]);
kono
parents: 67
diff changeset
1561 break;
kono
parents: 67
diff changeset
1562 }
kono
parents: 67
diff changeset
1563
kono
parents: 67
diff changeset
1564 if (ix == EDGE_COUNT (b->preds))
kono
parents: 67
diff changeset
1565 bitmap_clear (dst);
kono
parents: 67
diff changeset
1566 else
kono
parents: 67
diff changeset
1567 for (ix++; ix < EDGE_COUNT (b->preds); ix++)
kono
parents: 67
diff changeset
1568 {
kono
parents: 67
diff changeset
1569 unsigned int i;
kono
parents: 67
diff changeset
1570 SBITMAP_ELT_TYPE *p, *r;
kono
parents: 67
diff changeset
1571
kono
parents: 67
diff changeset
1572 e = EDGE_PRED (b, ix);
kono
parents: 67
diff changeset
1573 if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
kono
parents: 67
diff changeset
1574 continue;
kono
parents: 67
diff changeset
1575
kono
parents: 67
diff changeset
1576 p = src[e->src->index]->elms;
kono
parents: 67
diff changeset
1577 r = dst->elms;
kono
parents: 67
diff changeset
1578 for (i = 0; i < set_size; i++)
kono
parents: 67
diff changeset
1579 *r++ |= *p++;
kono
parents: 67
diff changeset
1580 }
kono
parents: 67
diff changeset
1581 }
kono
parents: 67
diff changeset
1582
kono
parents: 67
diff changeset
1583 /* Returns the list of basic blocks in the function in an order that guarantees
kono
parents: 67
diff changeset
1584 that if a block X has just a single predecessor Y, then Y is after X in the
kono
parents: 67
diff changeset
1585 ordering. */
kono
parents: 67
diff changeset
1586
kono
parents: 67
diff changeset
1587 basic_block *
kono
parents: 67
diff changeset
1588 single_pred_before_succ_order (void)
kono
parents: 67
diff changeset
1589 {
kono
parents: 67
diff changeset
1590 basic_block x, y;
kono
parents: 67
diff changeset
1591 basic_block *order = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
kono
parents: 67
diff changeset
1592 unsigned n = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
kono
parents: 67
diff changeset
1593 unsigned np, i;
kono
parents: 67
diff changeset
1594 auto_sbitmap visited (last_basic_block_for_fn (cfun));
kono
parents: 67
diff changeset
1595
kono
parents: 67
diff changeset
1596 #define MARK_VISITED(BB) (bitmap_set_bit (visited, (BB)->index))
kono
parents: 67
diff changeset
1597 #define VISITED_P(BB) (bitmap_bit_p (visited, (BB)->index))
kono
parents: 67
diff changeset
1598
kono
parents: 67
diff changeset
1599 bitmap_clear (visited);
kono
parents: 67
diff changeset
1600
kono
parents: 67
diff changeset
1601 MARK_VISITED (ENTRY_BLOCK_PTR_FOR_FN (cfun));
kono
parents: 67
diff changeset
1602 FOR_EACH_BB_FN (x, cfun)
kono
parents: 67
diff changeset
1603 {
kono
parents: 67
diff changeset
1604 if (VISITED_P (x))
kono
parents: 67
diff changeset
1605 continue;
kono
parents: 67
diff changeset
1606
kono
parents: 67
diff changeset
1607 /* Walk the predecessors of x as long as they have precisely one
kono
parents: 67
diff changeset
1608 predecessor and add them to the list, so that they get stored
kono
parents: 67
diff changeset
1609 after x. */
kono
parents: 67
diff changeset
1610 for (y = x, np = 1;
kono
parents: 67
diff changeset
1611 single_pred_p (y) && !VISITED_P (single_pred (y));
kono
parents: 67
diff changeset
1612 y = single_pred (y))
kono
parents: 67
diff changeset
1613 np++;
kono
parents: 67
diff changeset
1614 for (y = x, i = n - np;
kono
parents: 67
diff changeset
1615 single_pred_p (y) && !VISITED_P (single_pred (y));
kono
parents: 67
diff changeset
1616 y = single_pred (y), i++)
kono
parents: 67
diff changeset
1617 {
kono
parents: 67
diff changeset
1618 order[i] = y;
kono
parents: 67
diff changeset
1619 MARK_VISITED (y);
kono
parents: 67
diff changeset
1620 }
kono
parents: 67
diff changeset
1621 order[i] = y;
kono
parents: 67
diff changeset
1622 MARK_VISITED (y);
kono
parents: 67
diff changeset
1623
kono
parents: 67
diff changeset
1624 gcc_assert (i == n - 1);
kono
parents: 67
diff changeset
1625 n -= np;
kono
parents: 67
diff changeset
1626 }
kono
parents: 67
diff changeset
1627
kono
parents: 67
diff changeset
1628 gcc_assert (n == 0);
kono
parents: 67
diff changeset
1629 return order;
kono
parents: 67
diff changeset
1630
kono
parents: 67
diff changeset
1631 #undef MARK_VISITED
kono
parents: 67
diff changeset
1632 #undef VISITED_P
kono
parents: 67
diff changeset
1633 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1634
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1635 /* Ignoring loop backedges, if BB has precisely one incoming edge then
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1636 return that edge. Otherwise return NULL.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1637
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1638 When IGNORE_NOT_EXECUTABLE is true, also ignore edges that are not marked
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1639 as executable. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1640
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1641 edge
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1642 single_pred_edge_ignoring_loop_edges (basic_block bb,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1643 bool ignore_not_executable)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1644 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1645 edge retval = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1646 edge e;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1647 edge_iterator ei;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1648
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1649 FOR_EACH_EDGE (e, ei, bb->preds)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1650 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1651 /* A loop back edge can be identified by the destination of
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1652 the edge dominating the source of the edge. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1653 if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1654 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1655
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1656 /* We can safely ignore edges that are not executable. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1657 if (ignore_not_executable
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1658 && (e->flags & EDGE_EXECUTABLE) == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1659 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1660
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1661 /* If we have already seen a non-loop edge, then we must have
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1662 multiple incoming non-loop edges and thus we return NULL. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1663 if (retval)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1664 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1665
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1666 /* This is the first non-loop incoming edge we have found. Record
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1667 it. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1668 retval = e;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1669 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1670
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1671 return retval;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1672 }