annotate gcc/cfganal.c @ 120:f93fa5091070

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