1 |
684 |
jeremybenn |
/* Define control flow data structures for the CFG.
|
2 |
|
|
Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
3 |
|
|
2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
4 |
|
|
|
5 |
|
|
This file is part of GCC.
|
6 |
|
|
|
7 |
|
|
GCC is free software; you can redistribute it and/or modify it under
|
8 |
|
|
the terms of the GNU General Public License as published by the Free
|
9 |
|
|
Software Foundation; either version 3, or (at your option) any later
|
10 |
|
|
version.
|
11 |
|
|
|
12 |
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
13 |
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
14 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
15 |
|
|
for more details.
|
16 |
|
|
|
17 |
|
|
You should have received a copy of the GNU General Public License
|
18 |
|
|
along with GCC; see the file COPYING3. If not see
|
19 |
|
|
<http://www.gnu.org/licenses/>. */
|
20 |
|
|
|
21 |
|
|
#ifndef GCC_BASIC_BLOCK_H
|
22 |
|
|
#define GCC_BASIC_BLOCK_H
|
23 |
|
|
|
24 |
|
|
#include "predict.h"
|
25 |
|
|
#include "vec.h"
|
26 |
|
|
#include "function.h"
|
27 |
|
|
|
28 |
|
|
/* Type we use to hold basic block counters. Should be at least
|
29 |
|
|
64bit. Although a counter cannot be negative, we use a signed
|
30 |
|
|
type, because erroneous negative counts can be generated when the
|
31 |
|
|
flow graph is manipulated by various optimizations. A signed type
|
32 |
|
|
makes those easy to detect. */
|
33 |
|
|
typedef HOST_WIDEST_INT gcov_type;
|
34 |
|
|
|
35 |
|
|
/* Control flow edge information. */
|
36 |
|
|
struct GTY(()) edge_def {
|
37 |
|
|
/* The two blocks at the ends of the edge. */
|
38 |
|
|
struct basic_block_def *src;
|
39 |
|
|
struct basic_block_def *dest;
|
40 |
|
|
|
41 |
|
|
/* Instructions queued on the edge. */
|
42 |
|
|
union edge_def_insns {
|
43 |
|
|
gimple_seq GTY ((tag ("true"))) g;
|
44 |
|
|
rtx GTY ((tag ("false"))) r;
|
45 |
|
|
} GTY ((desc ("current_ir_type () == IR_GIMPLE"))) insns;
|
46 |
|
|
|
47 |
|
|
/* Auxiliary info specific to a pass. */
|
48 |
|
|
PTR GTY ((skip (""))) aux;
|
49 |
|
|
|
50 |
|
|
/* Location of any goto implicit in the edge and associated BLOCK. */
|
51 |
|
|
tree goto_block;
|
52 |
|
|
location_t goto_locus;
|
53 |
|
|
|
54 |
|
|
/* The index number corresponding to this edge in the edge vector
|
55 |
|
|
dest->preds. */
|
56 |
|
|
unsigned int dest_idx;
|
57 |
|
|
|
58 |
|
|
int flags; /* see EDGE_* below */
|
59 |
|
|
int probability; /* biased by REG_BR_PROB_BASE */
|
60 |
|
|
gcov_type count; /* Expected number of executions calculated
|
61 |
|
|
in profile.c */
|
62 |
|
|
};
|
63 |
|
|
|
64 |
|
|
DEF_VEC_P(edge);
|
65 |
|
|
DEF_VEC_ALLOC_P(edge,gc);
|
66 |
|
|
DEF_VEC_ALLOC_P(edge,heap);
|
67 |
|
|
|
68 |
|
|
/* Always update the table in cfg.c dump_edge_info. */
|
69 |
|
|
#define EDGE_FALLTHRU 0x0001 /* 'Straight line' flow */
|
70 |
|
|
#define EDGE_ABNORMAL 0x0002 /* Strange flow, like computed
|
71 |
|
|
label, or eh */
|
72 |
|
|
#define EDGE_ABNORMAL_CALL 0x0004 /* Call with abnormal exit
|
73 |
|
|
like an exception, or sibcall */
|
74 |
|
|
#define EDGE_EH 0x0008 /* Exception throw */
|
75 |
|
|
#define EDGE_FAKE 0x0010 /* Not a real edge (profile.c) */
|
76 |
|
|
#define EDGE_DFS_BACK 0x0020 /* A backwards edge */
|
77 |
|
|
#define EDGE_CAN_FALLTHRU 0x0040 /* Candidate for straight line
|
78 |
|
|
flow. */
|
79 |
|
|
#define EDGE_IRREDUCIBLE_LOOP 0x0080 /* Part of irreducible loop. */
|
80 |
|
|
#define EDGE_SIBCALL 0x0100 /* Edge from sibcall to exit. */
|
81 |
|
|
#define EDGE_LOOP_EXIT 0x0200 /* Exit of a loop. */
|
82 |
|
|
#define EDGE_TRUE_VALUE 0x0400 /* Edge taken when controlling
|
83 |
|
|
predicate is nonzero. */
|
84 |
|
|
#define EDGE_FALSE_VALUE 0x0800 /* Edge taken when controlling
|
85 |
|
|
predicate is zero. */
|
86 |
|
|
#define EDGE_EXECUTABLE 0x1000 /* Edge is executable. Only
|
87 |
|
|
valid during SSA-CCP. */
|
88 |
|
|
#define EDGE_CROSSING 0x2000 /* Edge crosses between hot
|
89 |
|
|
and cold sections, when we
|
90 |
|
|
do partitioning. */
|
91 |
|
|
#define EDGE_PRESERVE 0x4000 /* Never merge blocks via this edge. */
|
92 |
|
|
#define EDGE_ALL_FLAGS 0x7fff
|
93 |
|
|
|
94 |
|
|
#define EDGE_COMPLEX \
|
95 |
|
|
(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE)
|
96 |
|
|
|
97 |
|
|
/* Counter summary from the last set of coverage counts read by
|
98 |
|
|
profile.c. */
|
99 |
|
|
extern const struct gcov_ctr_summary *profile_info;
|
100 |
|
|
|
101 |
|
|
/* Declared in cfgloop.h. */
|
102 |
|
|
struct loop;
|
103 |
|
|
|
104 |
|
|
/* Declared in tree-flow.h. */
|
105 |
|
|
struct rtl_bb_info;
|
106 |
|
|
|
107 |
|
|
/* A basic block is a sequence of instructions with only entry and
|
108 |
|
|
only one exit. If any one of the instructions are executed, they
|
109 |
|
|
will all be executed, and in sequence from first to last.
|
110 |
|
|
|
111 |
|
|
There may be COND_EXEC instructions in the basic block. The
|
112 |
|
|
COND_EXEC *instructions* will be executed -- but if the condition
|
113 |
|
|
is false the conditionally executed *expressions* will of course
|
114 |
|
|
not be executed. We don't consider the conditionally executed
|
115 |
|
|
expression (which might have side-effects) to be in a separate
|
116 |
|
|
basic block because the program counter will always be at the same
|
117 |
|
|
location after the COND_EXEC instruction, regardless of whether the
|
118 |
|
|
condition is true or not.
|
119 |
|
|
|
120 |
|
|
Basic blocks need not start with a label nor end with a jump insn.
|
121 |
|
|
For example, a previous basic block may just "conditionally fall"
|
122 |
|
|
into the succeeding basic block, and the last basic block need not
|
123 |
|
|
end with a jump insn. Block 0 is a descendant of the entry block.
|
124 |
|
|
|
125 |
|
|
A basic block beginning with two labels cannot have notes between
|
126 |
|
|
the labels.
|
127 |
|
|
|
128 |
|
|
Data for jump tables are stored in jump_insns that occur in no
|
129 |
|
|
basic block even though these insns can follow or precede insns in
|
130 |
|
|
basic blocks. */
|
131 |
|
|
|
132 |
|
|
/* Basic block information indexed by block number. */
|
133 |
|
|
struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_def {
|
134 |
|
|
/* The edges into and out of the block. */
|
135 |
|
|
VEC(edge,gc) *preds;
|
136 |
|
|
VEC(edge,gc) *succs;
|
137 |
|
|
|
138 |
|
|
/* Auxiliary info specific to a pass. */
|
139 |
|
|
PTR GTY ((skip (""))) aux;
|
140 |
|
|
|
141 |
|
|
/* Innermost loop containing the block. */
|
142 |
|
|
struct loop *loop_father;
|
143 |
|
|
|
144 |
|
|
/* The dominance and postdominance information node. */
|
145 |
|
|
struct et_node * GTY ((skip (""))) dom[2];
|
146 |
|
|
|
147 |
|
|
/* Previous and next blocks in the chain. */
|
148 |
|
|
struct basic_block_def *prev_bb;
|
149 |
|
|
struct basic_block_def *next_bb;
|
150 |
|
|
|
151 |
|
|
union basic_block_il_dependent {
|
152 |
|
|
struct gimple_bb_info * GTY ((tag ("0"))) gimple;
|
153 |
|
|
struct rtl_bb_info * GTY ((tag ("1"))) rtl;
|
154 |
|
|
} GTY ((desc ("((%1.flags & BB_RTL) != 0)"))) il;
|
155 |
|
|
|
156 |
|
|
/* Expected number of executions: calculated in profile.c. */
|
157 |
|
|
gcov_type count;
|
158 |
|
|
|
159 |
|
|
/* The index of this block. */
|
160 |
|
|
int index;
|
161 |
|
|
|
162 |
|
|
/* The loop depth of this block. */
|
163 |
|
|
int loop_depth;
|
164 |
|
|
|
165 |
|
|
/* Expected frequency. Normalized to be in range 0 to BB_FREQ_MAX. */
|
166 |
|
|
int frequency;
|
167 |
|
|
|
168 |
|
|
/* The discriminator for this block. */
|
169 |
|
|
int discriminator;
|
170 |
|
|
|
171 |
|
|
/* Various flags. See BB_* below. */
|
172 |
|
|
int flags;
|
173 |
|
|
};
|
174 |
|
|
|
175 |
|
|
struct GTY(()) rtl_bb_info {
|
176 |
|
|
/* The first and last insns of the block. */
|
177 |
|
|
rtx head_;
|
178 |
|
|
rtx end_;
|
179 |
|
|
|
180 |
|
|
/* In CFGlayout mode points to insn notes/jumptables to be placed just before
|
181 |
|
|
and after the block. */
|
182 |
|
|
rtx header;
|
183 |
|
|
rtx footer;
|
184 |
|
|
|
185 |
|
|
/* This field is used by the bb-reorder and tracer passes. */
|
186 |
|
|
int visited;
|
187 |
|
|
};
|
188 |
|
|
|
189 |
|
|
struct GTY(()) gimple_bb_info {
|
190 |
|
|
/* Sequence of statements in this block. */
|
191 |
|
|
gimple_seq seq;
|
192 |
|
|
|
193 |
|
|
/* PHI nodes for this block. */
|
194 |
|
|
gimple_seq phi_nodes;
|
195 |
|
|
};
|
196 |
|
|
|
197 |
|
|
DEF_VEC_P(basic_block);
|
198 |
|
|
DEF_VEC_ALLOC_P(basic_block,gc);
|
199 |
|
|
DEF_VEC_ALLOC_P(basic_block,heap);
|
200 |
|
|
|
201 |
|
|
#define BB_FREQ_MAX 10000
|
202 |
|
|
|
203 |
|
|
/* Masks for basic_block.flags.
|
204 |
|
|
|
205 |
|
|
BB_HOT_PARTITION and BB_COLD_PARTITION should be preserved throughout
|
206 |
|
|
the compilation, so they are never cleared.
|
207 |
|
|
|
208 |
|
|
All other flags may be cleared by clear_bb_flags(). It is generally
|
209 |
|
|
a bad idea to rely on any flags being up-to-date.
|
210 |
|
|
|
211 |
|
|
Always update the table in cfg.c dump_bb_info. */
|
212 |
|
|
|
213 |
|
|
enum bb_flags
|
214 |
|
|
{
|
215 |
|
|
/* Only set on blocks that have just been created by create_bb. */
|
216 |
|
|
BB_NEW = 1 << 0,
|
217 |
|
|
|
218 |
|
|
/* Set by find_unreachable_blocks. Do not rely on this being set in any
|
219 |
|
|
pass. */
|
220 |
|
|
BB_REACHABLE = 1 << 1,
|
221 |
|
|
|
222 |
|
|
/* Set for blocks in an irreducible loop by loop analysis. */
|
223 |
|
|
BB_IRREDUCIBLE_LOOP = 1 << 2,
|
224 |
|
|
|
225 |
|
|
/* Set on blocks that may actually not be single-entry single-exit block. */
|
226 |
|
|
BB_SUPERBLOCK = 1 << 3,
|
227 |
|
|
|
228 |
|
|
/* Set on basic blocks that the scheduler should not touch. This is used
|
229 |
|
|
by SMS to prevent other schedulers from messing with the loop schedule. */
|
230 |
|
|
BB_DISABLE_SCHEDULE = 1 << 4,
|
231 |
|
|
|
232 |
|
|
/* Set on blocks that should be put in a hot section. */
|
233 |
|
|
BB_HOT_PARTITION = 1 << 5,
|
234 |
|
|
|
235 |
|
|
/* Set on blocks that should be put in a cold section. */
|
236 |
|
|
BB_COLD_PARTITION = 1 << 6,
|
237 |
|
|
|
238 |
|
|
/* Set on block that was duplicated. */
|
239 |
|
|
BB_DUPLICATED = 1 << 7,
|
240 |
|
|
|
241 |
|
|
/* Set if the label at the top of this block is the target of a non-local goto. */
|
242 |
|
|
BB_NON_LOCAL_GOTO_TARGET = 1 << 8,
|
243 |
|
|
|
244 |
|
|
/* Set on blocks that are in RTL format. */
|
245 |
|
|
BB_RTL = 1 << 9 ,
|
246 |
|
|
|
247 |
|
|
/* Set on blocks that are forwarder blocks.
|
248 |
|
|
Only used in cfgcleanup.c. */
|
249 |
|
|
BB_FORWARDER_BLOCK = 1 << 10,
|
250 |
|
|
|
251 |
|
|
/* Set on blocks that cannot be threaded through.
|
252 |
|
|
Only used in cfgcleanup.c. */
|
253 |
|
|
BB_NONTHREADABLE_BLOCK = 1 << 11,
|
254 |
|
|
|
255 |
|
|
/* Set on blocks that were modified in some way. This bit is set in
|
256 |
|
|
df_set_bb_dirty, but not cleared by df_analyze, so it can be used
|
257 |
|
|
to test whether a block has been modified prior to a df_analyze
|
258 |
|
|
call. */
|
259 |
|
|
BB_MODIFIED = 1 << 12
|
260 |
|
|
};
|
261 |
|
|
|
262 |
|
|
/* Dummy flag for convenience in the hot/cold partitioning code. */
|
263 |
|
|
#define BB_UNPARTITIONED 0
|
264 |
|
|
|
265 |
|
|
/* Partitions, to be used when partitioning hot and cold basic blocks into
|
266 |
|
|
separate sections. */
|
267 |
|
|
#define BB_PARTITION(bb) ((bb)->flags & (BB_HOT_PARTITION|BB_COLD_PARTITION))
|
268 |
|
|
#define BB_SET_PARTITION(bb, part) do { \
|
269 |
|
|
basic_block bb_ = (bb); \
|
270 |
|
|
bb_->flags = ((bb_->flags & ~(BB_HOT_PARTITION|BB_COLD_PARTITION)) \
|
271 |
|
|
| (part)); \
|
272 |
|
|
} while (0)
|
273 |
|
|
|
274 |
|
|
#define BB_COPY_PARTITION(dstbb, srcbb) \
|
275 |
|
|
BB_SET_PARTITION (dstbb, BB_PARTITION (srcbb))
|
276 |
|
|
|
277 |
|
|
/* State of dominance information. */
|
278 |
|
|
|
279 |
|
|
enum dom_state
|
280 |
|
|
{
|
281 |
|
|
DOM_NONE, /* Not computed at all. */
|
282 |
|
|
DOM_NO_FAST_QUERY, /* The data is OK, but the fast query data are not usable. */
|
283 |
|
|
DOM_OK /* Everything is ok. */
|
284 |
|
|
};
|
285 |
|
|
|
286 |
|
|
/* What sort of profiling information we have. */
|
287 |
|
|
enum profile_status_d
|
288 |
|
|
{
|
289 |
|
|
PROFILE_ABSENT,
|
290 |
|
|
PROFILE_GUESSED,
|
291 |
|
|
PROFILE_READ,
|
292 |
|
|
PROFILE_LAST /* Last value, used by profile streaming. */
|
293 |
|
|
};
|
294 |
|
|
|
295 |
|
|
/* A structure to group all the per-function control flow graph data.
|
296 |
|
|
The x_* prefixing is necessary because otherwise references to the
|
297 |
|
|
fields of this struct are interpreted as the defines for backward
|
298 |
|
|
source compatibility following the definition of this struct. */
|
299 |
|
|
struct GTY(()) control_flow_graph {
|
300 |
|
|
/* Block pointers for the exit and entry of a function.
|
301 |
|
|
These are always the head and tail of the basic block list. */
|
302 |
|
|
basic_block x_entry_block_ptr;
|
303 |
|
|
basic_block x_exit_block_ptr;
|
304 |
|
|
|
305 |
|
|
/* Index by basic block number, get basic block struct info. */
|
306 |
|
|
VEC(basic_block,gc) *x_basic_block_info;
|
307 |
|
|
|
308 |
|
|
/* Number of basic blocks in this flow graph. */
|
309 |
|
|
int x_n_basic_blocks;
|
310 |
|
|
|
311 |
|
|
/* Number of edges in this flow graph. */
|
312 |
|
|
int x_n_edges;
|
313 |
|
|
|
314 |
|
|
/* The first free basic block number. */
|
315 |
|
|
int x_last_basic_block;
|
316 |
|
|
|
317 |
|
|
/* UIDs for LABEL_DECLs. */
|
318 |
|
|
int last_label_uid;
|
319 |
|
|
|
320 |
|
|
/* Mapping of labels to their associated blocks. At present
|
321 |
|
|
only used for the gimple CFG. */
|
322 |
|
|
VEC(basic_block,gc) *x_label_to_block_map;
|
323 |
|
|
|
324 |
|
|
enum profile_status_d x_profile_status;
|
325 |
|
|
|
326 |
|
|
/* Whether the dominators and the postdominators are available. */
|
327 |
|
|
enum dom_state x_dom_computed[2];
|
328 |
|
|
|
329 |
|
|
/* Number of basic blocks in the dominance tree. */
|
330 |
|
|
unsigned x_n_bbs_in_dom_tree[2];
|
331 |
|
|
|
332 |
|
|
/* Maximal number of entities in the single jumptable. Used to estimate
|
333 |
|
|
final flowgraph size. */
|
334 |
|
|
int max_jumptable_ents;
|
335 |
|
|
};
|
336 |
|
|
|
337 |
|
|
/* Defines for accessing the fields of the CFG structure for function FN. */
|
338 |
|
|
#define ENTRY_BLOCK_PTR_FOR_FUNCTION(FN) ((FN)->cfg->x_entry_block_ptr)
|
339 |
|
|
#define EXIT_BLOCK_PTR_FOR_FUNCTION(FN) ((FN)->cfg->x_exit_block_ptr)
|
340 |
|
|
#define basic_block_info_for_function(FN) ((FN)->cfg->x_basic_block_info)
|
341 |
|
|
#define n_basic_blocks_for_function(FN) ((FN)->cfg->x_n_basic_blocks)
|
342 |
|
|
#define n_edges_for_function(FN) ((FN)->cfg->x_n_edges)
|
343 |
|
|
#define last_basic_block_for_function(FN) ((FN)->cfg->x_last_basic_block)
|
344 |
|
|
#define label_to_block_map_for_function(FN) ((FN)->cfg->x_label_to_block_map)
|
345 |
|
|
#define profile_status_for_function(FN) ((FN)->cfg->x_profile_status)
|
346 |
|
|
|
347 |
|
|
#define BASIC_BLOCK_FOR_FUNCTION(FN,N) \
|
348 |
|
|
(VEC_index (basic_block, basic_block_info_for_function(FN), (N)))
|
349 |
|
|
#define SET_BASIC_BLOCK_FOR_FUNCTION(FN,N,BB) \
|
350 |
|
|
(VEC_replace (basic_block, basic_block_info_for_function(FN), (N), (BB)))
|
351 |
|
|
|
352 |
|
|
/* Defines for textual backward source compatibility. */
|
353 |
|
|
#define ENTRY_BLOCK_PTR (cfun->cfg->x_entry_block_ptr)
|
354 |
|
|
#define EXIT_BLOCK_PTR (cfun->cfg->x_exit_block_ptr)
|
355 |
|
|
#define basic_block_info (cfun->cfg->x_basic_block_info)
|
356 |
|
|
#define n_basic_blocks (cfun->cfg->x_n_basic_blocks)
|
357 |
|
|
#define n_edges (cfun->cfg->x_n_edges)
|
358 |
|
|
#define last_basic_block (cfun->cfg->x_last_basic_block)
|
359 |
|
|
#define label_to_block_map (cfun->cfg->x_label_to_block_map)
|
360 |
|
|
#define profile_status (cfun->cfg->x_profile_status)
|
361 |
|
|
|
362 |
|
|
#define BASIC_BLOCK(N) (VEC_index (basic_block, basic_block_info, (N)))
|
363 |
|
|
#define SET_BASIC_BLOCK(N,BB) (VEC_replace (basic_block, basic_block_info, (N), (BB)))
|
364 |
|
|
|
365 |
|
|
/* For iterating over basic blocks. */
|
366 |
|
|
#define FOR_BB_BETWEEN(BB, FROM, TO, DIR) \
|
367 |
|
|
for (BB = FROM; BB != TO; BB = BB->DIR)
|
368 |
|
|
|
369 |
|
|
#define FOR_EACH_BB_FN(BB, FN) \
|
370 |
|
|
FOR_BB_BETWEEN (BB, (FN)->cfg->x_entry_block_ptr->next_bb, (FN)->cfg->x_exit_block_ptr, next_bb)
|
371 |
|
|
|
372 |
|
|
#define FOR_EACH_BB(BB) FOR_EACH_BB_FN (BB, cfun)
|
373 |
|
|
|
374 |
|
|
#define FOR_EACH_BB_REVERSE_FN(BB, FN) \
|
375 |
|
|
FOR_BB_BETWEEN (BB, (FN)->cfg->x_exit_block_ptr->prev_bb, (FN)->cfg->x_entry_block_ptr, prev_bb)
|
376 |
|
|
|
377 |
|
|
#define FOR_EACH_BB_REVERSE(BB) FOR_EACH_BB_REVERSE_FN(BB, cfun)
|
378 |
|
|
|
379 |
|
|
/* For iterating over insns in basic block. */
|
380 |
|
|
#define FOR_BB_INSNS(BB, INSN) \
|
381 |
|
|
for ((INSN) = BB_HEAD (BB); \
|
382 |
|
|
(INSN) && (INSN) != NEXT_INSN (BB_END (BB)); \
|
383 |
|
|
(INSN) = NEXT_INSN (INSN))
|
384 |
|
|
|
385 |
|
|
/* For iterating over insns in basic block when we might remove the
|
386 |
|
|
current insn. */
|
387 |
|
|
#define FOR_BB_INSNS_SAFE(BB, INSN, CURR) \
|
388 |
|
|
for ((INSN) = BB_HEAD (BB), (CURR) = (INSN) ? NEXT_INSN ((INSN)): NULL; \
|
389 |
|
|
(INSN) && (INSN) != NEXT_INSN (BB_END (BB)); \
|
390 |
|
|
(INSN) = (CURR), (CURR) = (INSN) ? NEXT_INSN ((INSN)) : NULL)
|
391 |
|
|
|
392 |
|
|
#define FOR_BB_INSNS_REVERSE(BB, INSN) \
|
393 |
|
|
for ((INSN) = BB_END (BB); \
|
394 |
|
|
(INSN) && (INSN) != PREV_INSN (BB_HEAD (BB)); \
|
395 |
|
|
(INSN) = PREV_INSN (INSN))
|
396 |
|
|
|
397 |
|
|
#define FOR_BB_INSNS_REVERSE_SAFE(BB, INSN, CURR) \
|
398 |
|
|
for ((INSN) = BB_END (BB),(CURR) = (INSN) ? PREV_INSN ((INSN)) : NULL; \
|
399 |
|
|
(INSN) && (INSN) != PREV_INSN (BB_HEAD (BB)); \
|
400 |
|
|
(INSN) = (CURR), (CURR) = (INSN) ? PREV_INSN ((INSN)) : NULL)
|
401 |
|
|
|
402 |
|
|
/* Cycles through _all_ basic blocks, even the fake ones (entry and
|
403 |
|
|
exit block). */
|
404 |
|
|
|
405 |
|
|
#define FOR_ALL_BB(BB) \
|
406 |
|
|
for (BB = ENTRY_BLOCK_PTR; BB; BB = BB->next_bb)
|
407 |
|
|
|
408 |
|
|
#define FOR_ALL_BB_FN(BB, FN) \
|
409 |
|
|
for (BB = ENTRY_BLOCK_PTR_FOR_FUNCTION (FN); BB; BB = BB->next_bb)
|
410 |
|
|
|
411 |
|
|
|
412 |
|
|
/* Stuff for recording basic block info. */
|
413 |
|
|
|
414 |
|
|
#define BB_HEAD(B) (B)->il.rtl->head_
|
415 |
|
|
#define BB_END(B) (B)->il.rtl->end_
|
416 |
|
|
|
417 |
|
|
/* Special block numbers [markers] for entry and exit.
|
418 |
|
|
Neither of them is supposed to hold actual statements. */
|
419 |
|
|
#define ENTRY_BLOCK (0)
|
420 |
|
|
#define EXIT_BLOCK (1)
|
421 |
|
|
|
422 |
|
|
/* The two blocks that are always in the cfg. */
|
423 |
|
|
#define NUM_FIXED_BLOCKS (2)
|
424 |
|
|
|
425 |
|
|
#define set_block_for_insn(INSN, BB) (BLOCK_FOR_INSN (INSN) = BB)
|
426 |
|
|
|
427 |
|
|
extern void compute_bb_for_insn (void);
|
428 |
|
|
extern unsigned int free_bb_for_insn (void);
|
429 |
|
|
extern void update_bb_for_insn (basic_block);
|
430 |
|
|
|
431 |
|
|
extern void insert_insn_on_edge (rtx, edge);
|
432 |
|
|
basic_block split_edge_and_insert (edge, rtx);
|
433 |
|
|
|
434 |
|
|
extern void commit_one_edge_insertion (edge e);
|
435 |
|
|
extern void commit_edge_insertions (void);
|
436 |
|
|
|
437 |
|
|
extern void remove_fake_edges (void);
|
438 |
|
|
extern void remove_fake_exit_edges (void);
|
439 |
|
|
extern void add_noreturn_fake_exit_edges (void);
|
440 |
|
|
extern void connect_infinite_loops_to_exit (void);
|
441 |
|
|
extern edge unchecked_make_edge (basic_block, basic_block, int);
|
442 |
|
|
extern edge cached_make_edge (sbitmap, basic_block, basic_block, int);
|
443 |
|
|
extern edge make_edge (basic_block, basic_block, int);
|
444 |
|
|
extern edge make_single_succ_edge (basic_block, basic_block, int);
|
445 |
|
|
extern void remove_edge_raw (edge);
|
446 |
|
|
extern void redirect_edge_succ (edge, basic_block);
|
447 |
|
|
extern edge redirect_edge_succ_nodup (edge, basic_block);
|
448 |
|
|
extern void redirect_edge_pred (edge, basic_block);
|
449 |
|
|
extern basic_block create_basic_block_structure (rtx, rtx, rtx, basic_block);
|
450 |
|
|
extern void clear_bb_flags (void);
|
451 |
|
|
extern int post_order_compute (int *, bool, bool);
|
452 |
|
|
extern int inverted_post_order_compute (int *);
|
453 |
|
|
extern int pre_and_rev_post_order_compute (int *, int *, bool);
|
454 |
|
|
extern int dfs_enumerate_from (basic_block, int,
|
455 |
|
|
bool (*)(const_basic_block, const void *),
|
456 |
|
|
basic_block *, int, const void *);
|
457 |
|
|
extern void compute_dominance_frontiers (struct bitmap_head_def *);
|
458 |
|
|
extern bitmap compute_idf (bitmap, struct bitmap_head_def *);
|
459 |
|
|
extern void dump_bb_info (basic_block, bool, bool, int, const char *, FILE *);
|
460 |
|
|
extern void dump_edge_info (FILE *, edge, int);
|
461 |
|
|
extern void brief_dump_cfg (FILE *);
|
462 |
|
|
extern void clear_edges (void);
|
463 |
|
|
extern void scale_bbs_frequencies_int (basic_block *, int, int, int);
|
464 |
|
|
extern void scale_bbs_frequencies_gcov_type (basic_block *, int, gcov_type,
|
465 |
|
|
gcov_type);
|
466 |
|
|
|
467 |
|
|
/* Structure to group all of the information to process IF-THEN and
|
468 |
|
|
IF-THEN-ELSE blocks for the conditional execution support. This
|
469 |
|
|
needs to be in a public file in case the IFCVT macros call
|
470 |
|
|
functions passing the ce_if_block data structure. */
|
471 |
|
|
|
472 |
|
|
typedef struct ce_if_block
|
473 |
|
|
{
|
474 |
|
|
basic_block test_bb; /* First test block. */
|
475 |
|
|
basic_block then_bb; /* THEN block. */
|
476 |
|
|
basic_block else_bb; /* ELSE block or NULL. */
|
477 |
|
|
basic_block join_bb; /* Join THEN/ELSE blocks. */
|
478 |
|
|
basic_block last_test_bb; /* Last bb to hold && or || tests. */
|
479 |
|
|
int num_multiple_test_blocks; /* # of && and || basic blocks. */
|
480 |
|
|
int num_and_and_blocks; /* # of && blocks. */
|
481 |
|
|
int num_or_or_blocks; /* # of || blocks. */
|
482 |
|
|
int num_multiple_test_insns; /* # of insns in && and || blocks. */
|
483 |
|
|
int and_and_p; /* Complex test is &&. */
|
484 |
|
|
int num_then_insns; /* # of insns in THEN block. */
|
485 |
|
|
int num_else_insns; /* # of insns in ELSE block. */
|
486 |
|
|
int pass; /* Pass number. */
|
487 |
|
|
|
488 |
|
|
#ifdef IFCVT_EXTRA_FIELDS
|
489 |
|
|
IFCVT_EXTRA_FIELDS /* Any machine dependent fields. */
|
490 |
|
|
#endif
|
491 |
|
|
|
492 |
|
|
} ce_if_block_t;
|
493 |
|
|
|
494 |
|
|
/* This structure maintains an edge list vector. */
|
495 |
|
|
struct edge_list
|
496 |
|
|
{
|
497 |
|
|
int num_blocks;
|
498 |
|
|
int num_edges;
|
499 |
|
|
edge *index_to_edge;
|
500 |
|
|
};
|
501 |
|
|
|
502 |
|
|
/* The base value for branch probability notes and edge probabilities. */
|
503 |
|
|
#define REG_BR_PROB_BASE 10000
|
504 |
|
|
|
505 |
|
|
/* This is the value which indicates no edge is present. */
|
506 |
|
|
#define EDGE_INDEX_NO_EDGE -1
|
507 |
|
|
|
508 |
|
|
/* EDGE_INDEX returns an integer index for an edge, or EDGE_INDEX_NO_EDGE
|
509 |
|
|
if there is no edge between the 2 basic blocks. */
|
510 |
|
|
#define EDGE_INDEX(el, pred, succ) (find_edge_index ((el), (pred), (succ)))
|
511 |
|
|
|
512 |
|
|
/* INDEX_EDGE_PRED_BB and INDEX_EDGE_SUCC_BB return a pointer to the basic
|
513 |
|
|
block which is either the pred or succ end of the indexed edge. */
|
514 |
|
|
#define INDEX_EDGE_PRED_BB(el, index) ((el)->index_to_edge[(index)]->src)
|
515 |
|
|
#define INDEX_EDGE_SUCC_BB(el, index) ((el)->index_to_edge[(index)]->dest)
|
516 |
|
|
|
517 |
|
|
/* INDEX_EDGE returns a pointer to the edge. */
|
518 |
|
|
#define INDEX_EDGE(el, index) ((el)->index_to_edge[(index)])
|
519 |
|
|
|
520 |
|
|
/* Number of edges in the compressed edge list. */
|
521 |
|
|
#define NUM_EDGES(el) ((el)->num_edges)
|
522 |
|
|
|
523 |
|
|
/* BB is assumed to contain conditional jump. Return the fallthru edge. */
|
524 |
|
|
#define FALLTHRU_EDGE(bb) (EDGE_SUCC ((bb), 0)->flags & EDGE_FALLTHRU \
|
525 |
|
|
? EDGE_SUCC ((bb), 0) : EDGE_SUCC ((bb), 1))
|
526 |
|
|
|
527 |
|
|
/* BB is assumed to contain conditional jump. Return the branch edge. */
|
528 |
|
|
#define BRANCH_EDGE(bb) (EDGE_SUCC ((bb), 0)->flags & EDGE_FALLTHRU \
|
529 |
|
|
? EDGE_SUCC ((bb), 1) : EDGE_SUCC ((bb), 0))
|
530 |
|
|
|
531 |
|
|
/* Return expected execution frequency of the edge E. */
|
532 |
|
|
#define EDGE_FREQUENCY(e) (((e)->src->frequency \
|
533 |
|
|
* (e)->probability \
|
534 |
|
|
+ REG_BR_PROB_BASE / 2) \
|
535 |
|
|
/ REG_BR_PROB_BASE)
|
536 |
|
|
|
537 |
|
|
/* Return nonzero if edge is critical. */
|
538 |
|
|
#define EDGE_CRITICAL_P(e) (EDGE_COUNT ((e)->src->succs) >= 2 \
|
539 |
|
|
&& EDGE_COUNT ((e)->dest->preds) >= 2)
|
540 |
|
|
|
541 |
|
|
#define EDGE_COUNT(ev) VEC_length (edge, (ev))
|
542 |
|
|
#define EDGE_I(ev,i) VEC_index (edge, (ev), (i))
|
543 |
|
|
#define EDGE_PRED(bb,i) VEC_index (edge, (bb)->preds, (i))
|
544 |
|
|
#define EDGE_SUCC(bb,i) VEC_index (edge, (bb)->succs, (i))
|
545 |
|
|
|
546 |
|
|
/* Returns true if BB has precisely one successor. */
|
547 |
|
|
|
548 |
|
|
static inline bool
|
549 |
|
|
single_succ_p (const_basic_block bb)
|
550 |
|
|
{
|
551 |
|
|
return EDGE_COUNT (bb->succs) == 1;
|
552 |
|
|
}
|
553 |
|
|
|
554 |
|
|
/* Returns true if BB has precisely one predecessor. */
|
555 |
|
|
|
556 |
|
|
static inline bool
|
557 |
|
|
single_pred_p (const_basic_block bb)
|
558 |
|
|
{
|
559 |
|
|
return EDGE_COUNT (bb->preds) == 1;
|
560 |
|
|
}
|
561 |
|
|
|
562 |
|
|
/* Returns the single successor edge of basic block BB. Aborts if
|
563 |
|
|
BB does not have exactly one successor. */
|
564 |
|
|
|
565 |
|
|
static inline edge
|
566 |
|
|
single_succ_edge (const_basic_block bb)
|
567 |
|
|
{
|
568 |
|
|
gcc_checking_assert (single_succ_p (bb));
|
569 |
|
|
return EDGE_SUCC (bb, 0);
|
570 |
|
|
}
|
571 |
|
|
|
572 |
|
|
/* Returns the single predecessor edge of basic block BB. Aborts
|
573 |
|
|
if BB does not have exactly one predecessor. */
|
574 |
|
|
|
575 |
|
|
static inline edge
|
576 |
|
|
single_pred_edge (const_basic_block bb)
|
577 |
|
|
{
|
578 |
|
|
gcc_checking_assert (single_pred_p (bb));
|
579 |
|
|
return EDGE_PRED (bb, 0);
|
580 |
|
|
}
|
581 |
|
|
|
582 |
|
|
/* Returns the single successor block of basic block BB. Aborts
|
583 |
|
|
if BB does not have exactly one successor. */
|
584 |
|
|
|
585 |
|
|
static inline basic_block
|
586 |
|
|
single_succ (const_basic_block bb)
|
587 |
|
|
{
|
588 |
|
|
return single_succ_edge (bb)->dest;
|
589 |
|
|
}
|
590 |
|
|
|
591 |
|
|
/* Returns the single predecessor block of basic block BB. Aborts
|
592 |
|
|
if BB does not have exactly one predecessor.*/
|
593 |
|
|
|
594 |
|
|
static inline basic_block
|
595 |
|
|
single_pred (const_basic_block bb)
|
596 |
|
|
{
|
597 |
|
|
return single_pred_edge (bb)->src;
|
598 |
|
|
}
|
599 |
|
|
|
600 |
|
|
/* Iterator object for edges. */
|
601 |
|
|
|
602 |
|
|
typedef struct {
|
603 |
|
|
unsigned index;
|
604 |
|
|
VEC(edge,gc) **container;
|
605 |
|
|
} edge_iterator;
|
606 |
|
|
|
607 |
|
|
static inline VEC(edge,gc) *
|
608 |
|
|
ei_container (edge_iterator i)
|
609 |
|
|
{
|
610 |
|
|
gcc_checking_assert (i.container);
|
611 |
|
|
return *i.container;
|
612 |
|
|
}
|
613 |
|
|
|
614 |
|
|
#define ei_start(iter) ei_start_1 (&(iter))
|
615 |
|
|
#define ei_last(iter) ei_last_1 (&(iter))
|
616 |
|
|
|
617 |
|
|
/* Return an iterator pointing to the start of an edge vector. */
|
618 |
|
|
static inline edge_iterator
|
619 |
|
|
ei_start_1 (VEC(edge,gc) **ev)
|
620 |
|
|
{
|
621 |
|
|
edge_iterator i;
|
622 |
|
|
|
623 |
|
|
i.index = 0;
|
624 |
|
|
i.container = ev;
|
625 |
|
|
|
626 |
|
|
return i;
|
627 |
|
|
}
|
628 |
|
|
|
629 |
|
|
/* Return an iterator pointing to the last element of an edge
|
630 |
|
|
vector. */
|
631 |
|
|
static inline edge_iterator
|
632 |
|
|
ei_last_1 (VEC(edge,gc) **ev)
|
633 |
|
|
{
|
634 |
|
|
edge_iterator i;
|
635 |
|
|
|
636 |
|
|
i.index = EDGE_COUNT (*ev) - 1;
|
637 |
|
|
i.container = ev;
|
638 |
|
|
|
639 |
|
|
return i;
|
640 |
|
|
}
|
641 |
|
|
|
642 |
|
|
/* Is the iterator `i' at the end of the sequence? */
|
643 |
|
|
static inline bool
|
644 |
|
|
ei_end_p (edge_iterator i)
|
645 |
|
|
{
|
646 |
|
|
return (i.index == EDGE_COUNT (ei_container (i)));
|
647 |
|
|
}
|
648 |
|
|
|
649 |
|
|
/* Is the iterator `i' at one position before the end of the
|
650 |
|
|
sequence? */
|
651 |
|
|
static inline bool
|
652 |
|
|
ei_one_before_end_p (edge_iterator i)
|
653 |
|
|
{
|
654 |
|
|
return (i.index + 1 == EDGE_COUNT (ei_container (i)));
|
655 |
|
|
}
|
656 |
|
|
|
657 |
|
|
/* Advance the iterator to the next element. */
|
658 |
|
|
static inline void
|
659 |
|
|
ei_next (edge_iterator *i)
|
660 |
|
|
{
|
661 |
|
|
gcc_checking_assert (i->index < EDGE_COUNT (ei_container (*i)));
|
662 |
|
|
i->index++;
|
663 |
|
|
}
|
664 |
|
|
|
665 |
|
|
/* Move the iterator to the previous element. */
|
666 |
|
|
static inline void
|
667 |
|
|
ei_prev (edge_iterator *i)
|
668 |
|
|
{
|
669 |
|
|
gcc_checking_assert (i->index > 0);
|
670 |
|
|
i->index--;
|
671 |
|
|
}
|
672 |
|
|
|
673 |
|
|
/* Return the edge pointed to by the iterator `i'. */
|
674 |
|
|
static inline edge
|
675 |
|
|
ei_edge (edge_iterator i)
|
676 |
|
|
{
|
677 |
|
|
return EDGE_I (ei_container (i), i.index);
|
678 |
|
|
}
|
679 |
|
|
|
680 |
|
|
/* Return an edge pointed to by the iterator. Do it safely so that
|
681 |
|
|
NULL is returned when the iterator is pointing at the end of the
|
682 |
|
|
sequence. */
|
683 |
|
|
static inline edge
|
684 |
|
|
ei_safe_edge (edge_iterator i)
|
685 |
|
|
{
|
686 |
|
|
return !ei_end_p (i) ? ei_edge (i) : NULL;
|
687 |
|
|
}
|
688 |
|
|
|
689 |
|
|
/* Return 1 if we should continue to iterate. Return 0 otherwise.
|
690 |
|
|
*Edge P is set to the next edge if we are to continue to iterate
|
691 |
|
|
and NULL otherwise. */
|
692 |
|
|
|
693 |
|
|
static inline bool
|
694 |
|
|
ei_cond (edge_iterator ei, edge *p)
|
695 |
|
|
{
|
696 |
|
|
if (!ei_end_p (ei))
|
697 |
|
|
{
|
698 |
|
|
*p = ei_edge (ei);
|
699 |
|
|
return 1;
|
700 |
|
|
}
|
701 |
|
|
else
|
702 |
|
|
{
|
703 |
|
|
*p = NULL;
|
704 |
|
|
return 0;
|
705 |
|
|
}
|
706 |
|
|
}
|
707 |
|
|
|
708 |
|
|
/* This macro serves as a convenient way to iterate each edge in a
|
709 |
|
|
vector of predecessor or successor edges. It must not be used when
|
710 |
|
|
an element might be removed during the traversal, otherwise
|
711 |
|
|
elements will be missed. Instead, use a for-loop like that shown
|
712 |
|
|
in the following pseudo-code:
|
713 |
|
|
|
714 |
|
|
FOR (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
|
715 |
|
|
{
|
716 |
|
|
IF (e != taken_edge)
|
717 |
|
|
remove_edge (e);
|
718 |
|
|
ELSE
|
719 |
|
|
ei_next (&ei);
|
720 |
|
|
}
|
721 |
|
|
*/
|
722 |
|
|
|
723 |
|
|
#define FOR_EACH_EDGE(EDGE,ITER,EDGE_VEC) \
|
724 |
|
|
for ((ITER) = ei_start ((EDGE_VEC)); \
|
725 |
|
|
ei_cond ((ITER), &(EDGE)); \
|
726 |
|
|
ei_next (&(ITER)))
|
727 |
|
|
|
728 |
|
|
struct edge_list * create_edge_list (void);
|
729 |
|
|
void free_edge_list (struct edge_list *);
|
730 |
|
|
void print_edge_list (FILE *, struct edge_list *);
|
731 |
|
|
void verify_edge_list (FILE *, struct edge_list *);
|
732 |
|
|
int find_edge_index (struct edge_list *, basic_block, basic_block);
|
733 |
|
|
edge find_edge (basic_block, basic_block);
|
734 |
|
|
|
735 |
|
|
#define CLEANUP_EXPENSIVE 1 /* Do relatively expensive optimizations
|
736 |
|
|
except for edge forwarding */
|
737 |
|
|
#define CLEANUP_CROSSJUMP 2 /* Do crossjumping. */
|
738 |
|
|
#define CLEANUP_POST_REGSTACK 4 /* We run after reg-stack and need
|
739 |
|
|
to care REG_DEAD notes. */
|
740 |
|
|
#define CLEANUP_THREADING 8 /* Do jump threading. */
|
741 |
|
|
#define CLEANUP_NO_INSN_DEL 16 /* Do not try to delete trivially dead
|
742 |
|
|
insns. */
|
743 |
|
|
#define CLEANUP_CFGLAYOUT 32 /* Do cleanup in cfglayout mode. */
|
744 |
|
|
|
745 |
|
|
/* In lcm.c */
|
746 |
|
|
extern struct edge_list *pre_edge_lcm (int, sbitmap *, sbitmap *,
|
747 |
|
|
sbitmap *, sbitmap *, sbitmap **,
|
748 |
|
|
sbitmap **);
|
749 |
|
|
extern struct edge_list *pre_edge_rev_lcm (int, sbitmap *,
|
750 |
|
|
sbitmap *, sbitmap *,
|
751 |
|
|
sbitmap *, sbitmap **,
|
752 |
|
|
sbitmap **);
|
753 |
|
|
extern void compute_available (sbitmap *, sbitmap *, sbitmap *, sbitmap *);
|
754 |
|
|
|
755 |
|
|
/* In predict.c */
|
756 |
|
|
extern bool maybe_hot_bb_p (const_basic_block);
|
757 |
|
|
extern bool maybe_hot_edge_p (edge);
|
758 |
|
|
extern bool probably_never_executed_bb_p (const_basic_block);
|
759 |
|
|
extern bool optimize_bb_for_size_p (const_basic_block);
|
760 |
|
|
extern bool optimize_bb_for_speed_p (const_basic_block);
|
761 |
|
|
extern bool optimize_edge_for_size_p (edge);
|
762 |
|
|
extern bool optimize_edge_for_speed_p (edge);
|
763 |
|
|
extern bool optimize_loop_for_size_p (struct loop *);
|
764 |
|
|
extern bool optimize_loop_for_speed_p (struct loop *);
|
765 |
|
|
extern bool optimize_loop_nest_for_size_p (struct loop *);
|
766 |
|
|
extern bool optimize_loop_nest_for_speed_p (struct loop *);
|
767 |
|
|
extern bool gimple_predicted_by_p (const_basic_block, enum br_predictor);
|
768 |
|
|
extern bool rtl_predicted_by_p (const_basic_block, enum br_predictor);
|
769 |
|
|
extern void gimple_predict_edge (edge, enum br_predictor, int);
|
770 |
|
|
extern void rtl_predict_edge (edge, enum br_predictor, int);
|
771 |
|
|
extern void predict_edge_def (edge, enum br_predictor, enum prediction);
|
772 |
|
|
extern void guess_outgoing_edge_probabilities (basic_block);
|
773 |
|
|
extern void remove_predictions_associated_with_edge (edge);
|
774 |
|
|
extern bool edge_probability_reliable_p (const_edge);
|
775 |
|
|
extern bool br_prob_note_reliable_p (const_rtx);
|
776 |
|
|
extern bool predictable_edge_p (edge);
|
777 |
|
|
|
778 |
|
|
/* In cfg.c */
|
779 |
|
|
extern void init_flow (struct function *);
|
780 |
|
|
extern void debug_bb (basic_block);
|
781 |
|
|
extern basic_block debug_bb_n (int);
|
782 |
|
|
extern void expunge_block (basic_block);
|
783 |
|
|
extern void link_block (basic_block, basic_block);
|
784 |
|
|
extern void unlink_block (basic_block);
|
785 |
|
|
extern void compact_blocks (void);
|
786 |
|
|
extern basic_block alloc_block (void);
|
787 |
|
|
extern void alloc_aux_for_blocks (int);
|
788 |
|
|
extern void clear_aux_for_blocks (void);
|
789 |
|
|
extern void free_aux_for_blocks (void);
|
790 |
|
|
extern void alloc_aux_for_edges (int);
|
791 |
|
|
extern void clear_aux_for_edges (void);
|
792 |
|
|
extern void free_aux_for_edges (void);
|
793 |
|
|
|
794 |
|
|
/* In cfganal.c */
|
795 |
|
|
extern void find_unreachable_blocks (void);
|
796 |
|
|
extern bool forwarder_block_p (const_basic_block);
|
797 |
|
|
extern bool can_fallthru (basic_block, basic_block);
|
798 |
|
|
extern bool could_fall_through (basic_block, basic_block);
|
799 |
|
|
extern void flow_nodes_print (const char *, const_sbitmap, FILE *);
|
800 |
|
|
extern void flow_edge_list_print (const char *, const edge *, int, FILE *);
|
801 |
|
|
|
802 |
|
|
/* In cfgrtl.c */
|
803 |
|
|
extern rtx block_label (basic_block);
|
804 |
|
|
extern rtx bb_note (basic_block);
|
805 |
|
|
extern bool purge_all_dead_edges (void);
|
806 |
|
|
extern bool purge_dead_edges (basic_block);
|
807 |
|
|
extern bool fixup_abnormal_edges (void);
|
808 |
|
|
extern basic_block force_nonfallthru_and_redirect (edge, basic_block, rtx);
|
809 |
|
|
|
810 |
|
|
/* In cfgbuild.c. */
|
811 |
|
|
extern void find_many_sub_basic_blocks (sbitmap);
|
812 |
|
|
extern void rtl_make_eh_edge (sbitmap, basic_block, rtx);
|
813 |
|
|
|
814 |
|
|
enum replace_direction { dir_none, dir_forward, dir_backward, dir_both };
|
815 |
|
|
|
816 |
|
|
/* In cfgcleanup.c. */
|
817 |
|
|
extern bool cleanup_cfg (int);
|
818 |
|
|
extern int flow_find_cross_jump (basic_block, basic_block, rtx *, rtx *,
|
819 |
|
|
enum replace_direction*);
|
820 |
|
|
extern int flow_find_head_matching_sequence (basic_block, basic_block,
|
821 |
|
|
rtx *, rtx *, int);
|
822 |
|
|
|
823 |
|
|
extern bool delete_unreachable_blocks (void);
|
824 |
|
|
|
825 |
|
|
extern bool mark_dfs_back_edges (void);
|
826 |
|
|
extern void set_edge_can_fallthru_flag (void);
|
827 |
|
|
extern void update_br_prob_note (basic_block);
|
828 |
|
|
extern bool inside_basic_block_p (const_rtx);
|
829 |
|
|
extern bool control_flow_insn_p (const_rtx);
|
830 |
|
|
extern rtx get_last_bb_insn (basic_block);
|
831 |
|
|
|
832 |
|
|
/* In bb-reorder.c */
|
833 |
|
|
extern void reorder_basic_blocks (void);
|
834 |
|
|
|
835 |
|
|
/* In dominance.c */
|
836 |
|
|
|
837 |
|
|
enum cdi_direction
|
838 |
|
|
{
|
839 |
|
|
CDI_DOMINATORS = 1,
|
840 |
|
|
CDI_POST_DOMINATORS = 2
|
841 |
|
|
};
|
842 |
|
|
|
843 |
|
|
extern enum dom_state dom_info_state (enum cdi_direction);
|
844 |
|
|
extern void set_dom_info_availability (enum cdi_direction, enum dom_state);
|
845 |
|
|
extern bool dom_info_available_p (enum cdi_direction);
|
846 |
|
|
extern void calculate_dominance_info (enum cdi_direction);
|
847 |
|
|
extern void free_dominance_info (enum cdi_direction);
|
848 |
|
|
extern basic_block nearest_common_dominator (enum cdi_direction,
|
849 |
|
|
basic_block, basic_block);
|
850 |
|
|
extern basic_block nearest_common_dominator_for_set (enum cdi_direction,
|
851 |
|
|
bitmap);
|
852 |
|
|
extern void set_immediate_dominator (enum cdi_direction, basic_block,
|
853 |
|
|
basic_block);
|
854 |
|
|
extern basic_block get_immediate_dominator (enum cdi_direction, basic_block);
|
855 |
|
|
extern bool dominated_by_p (enum cdi_direction, const_basic_block, const_basic_block);
|
856 |
|
|
extern VEC (basic_block, heap) *get_dominated_by (enum cdi_direction, basic_block);
|
857 |
|
|
extern VEC (basic_block, heap) *get_dominated_by_region (enum cdi_direction,
|
858 |
|
|
basic_block *,
|
859 |
|
|
unsigned);
|
860 |
|
|
extern VEC (basic_block, heap) *get_dominated_to_depth (enum cdi_direction,
|
861 |
|
|
basic_block, int);
|
862 |
|
|
extern VEC (basic_block, heap) *get_all_dominated_blocks (enum cdi_direction,
|
863 |
|
|
basic_block);
|
864 |
|
|
extern void add_to_dominance_info (enum cdi_direction, basic_block);
|
865 |
|
|
extern void delete_from_dominance_info (enum cdi_direction, basic_block);
|
866 |
|
|
basic_block recompute_dominator (enum cdi_direction, basic_block);
|
867 |
|
|
extern void redirect_immediate_dominators (enum cdi_direction, basic_block,
|
868 |
|
|
basic_block);
|
869 |
|
|
extern void iterate_fix_dominators (enum cdi_direction,
|
870 |
|
|
VEC (basic_block, heap) *, bool);
|
871 |
|
|
extern void verify_dominators (enum cdi_direction);
|
872 |
|
|
extern basic_block first_dom_son (enum cdi_direction, basic_block);
|
873 |
|
|
extern basic_block next_dom_son (enum cdi_direction, basic_block);
|
874 |
|
|
unsigned bb_dom_dfs_in (enum cdi_direction, basic_block);
|
875 |
|
|
unsigned bb_dom_dfs_out (enum cdi_direction, basic_block);
|
876 |
|
|
|
877 |
|
|
extern edge try_redirect_by_replacing_jump (edge, basic_block, bool);
|
878 |
|
|
extern void break_superblocks (void);
|
879 |
|
|
extern void relink_block_chain (bool);
|
880 |
|
|
extern void check_bb_profile (basic_block, FILE *);
|
881 |
|
|
extern void update_bb_profile_for_threading (basic_block, int, gcov_type, edge);
|
882 |
|
|
extern void init_rtl_bb_info (basic_block);
|
883 |
|
|
|
884 |
|
|
extern void initialize_original_copy_tables (void);
|
885 |
|
|
extern void free_original_copy_tables (void);
|
886 |
|
|
extern void set_bb_original (basic_block, basic_block);
|
887 |
|
|
extern basic_block get_bb_original (basic_block);
|
888 |
|
|
extern void set_bb_copy (basic_block, basic_block);
|
889 |
|
|
extern basic_block get_bb_copy (basic_block);
|
890 |
|
|
void set_loop_copy (struct loop *, struct loop *);
|
891 |
|
|
struct loop *get_loop_copy (struct loop *);
|
892 |
|
|
|
893 |
|
|
#include "cfghooks.h"
|
894 |
|
|
|
895 |
|
|
/* Return true when one of the predecessor edges of BB is marked with EDGE_EH. */
|
896 |
|
|
static inline bool
|
897 |
|
|
bb_has_eh_pred (basic_block bb)
|
898 |
|
|
{
|
899 |
|
|
edge e;
|
900 |
|
|
edge_iterator ei;
|
901 |
|
|
|
902 |
|
|
FOR_EACH_EDGE (e, ei, bb->preds)
|
903 |
|
|
{
|
904 |
|
|
if (e->flags & EDGE_EH)
|
905 |
|
|
return true;
|
906 |
|
|
}
|
907 |
|
|
return false;
|
908 |
|
|
}
|
909 |
|
|
|
910 |
|
|
/* Return true when one of the predecessor edges of BB is marked with EDGE_ABNORMAL. */
|
911 |
|
|
static inline bool
|
912 |
|
|
bb_has_abnormal_pred (basic_block bb)
|
913 |
|
|
{
|
914 |
|
|
edge e;
|
915 |
|
|
edge_iterator ei;
|
916 |
|
|
|
917 |
|
|
FOR_EACH_EDGE (e, ei, bb->preds)
|
918 |
|
|
{
|
919 |
|
|
if (e->flags & EDGE_ABNORMAL)
|
920 |
|
|
return true;
|
921 |
|
|
}
|
922 |
|
|
return false;
|
923 |
|
|
}
|
924 |
|
|
|
925 |
|
|
/* Return the fallthru edge in EDGES if it exists, NULL otherwise. */
|
926 |
|
|
static inline edge
|
927 |
|
|
find_fallthru_edge (VEC(edge,gc) *edges)
|
928 |
|
|
{
|
929 |
|
|
edge e;
|
930 |
|
|
edge_iterator ei;
|
931 |
|
|
|
932 |
|
|
FOR_EACH_EDGE (e, ei, edges)
|
933 |
|
|
if (e->flags & EDGE_FALLTHRU)
|
934 |
|
|
break;
|
935 |
|
|
|
936 |
|
|
return e;
|
937 |
|
|
}
|
938 |
|
|
|
939 |
|
|
/* In cfgloopmanip.c. */
|
940 |
|
|
extern edge mfb_kj_edge;
|
941 |
|
|
extern bool mfb_keep_just (edge);
|
942 |
|
|
|
943 |
|
|
/* In cfgexpand.c. */
|
944 |
|
|
extern void rtl_profile_for_bb (basic_block);
|
945 |
|
|
extern void rtl_profile_for_edge (edge);
|
946 |
|
|
extern void default_rtl_profile (void);
|
947 |
|
|
|
948 |
|
|
#endif /* GCC_BASIC_BLOCK_H */
|