1e4b17023SJohn Marino /* Control flow functions for trees.
2e4b17023SJohn Marino Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3e4b17023SJohn Marino 2010, 2011, 2012 Free Software Foundation, Inc.
4e4b17023SJohn Marino Contributed by Diego Novillo <dnovillo@redhat.com>
5e4b17023SJohn Marino
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11e4b17023SJohn Marino any later version.
12e4b17023SJohn Marino
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16e4b17023SJohn Marino GNU General Public License for more details.
17e4b17023SJohn Marino
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21e4b17023SJohn Marino
22e4b17023SJohn Marino #include "config.h"
23e4b17023SJohn Marino #include "system.h"
24e4b17023SJohn Marino #include "coretypes.h"
25e4b17023SJohn Marino #include "tm.h"
26e4b17023SJohn Marino #include "tree.h"
27e4b17023SJohn Marino #include "tm_p.h"
28e4b17023SJohn Marino #include "basic-block.h"
29e4b17023SJohn Marino #include "output.h"
30e4b17023SJohn Marino #include "flags.h"
31e4b17023SJohn Marino #include "function.h"
32e4b17023SJohn Marino #include "ggc.h"
33e4b17023SJohn Marino #include "langhooks.h"
34e4b17023SJohn Marino #include "tree-pretty-print.h"
35e4b17023SJohn Marino #include "gimple-pretty-print.h"
36e4b17023SJohn Marino #include "tree-flow.h"
37e4b17023SJohn Marino #include "timevar.h"
38e4b17023SJohn Marino #include "tree-dump.h"
39e4b17023SJohn Marino #include "tree-pass.h"
40e4b17023SJohn Marino #include "diagnostic-core.h"
41e4b17023SJohn Marino #include "except.h"
42e4b17023SJohn Marino #include "cfgloop.h"
43e4b17023SJohn Marino #include "cfglayout.h"
44e4b17023SJohn Marino #include "tree-ssa-propagate.h"
45e4b17023SJohn Marino #include "value-prof.h"
46e4b17023SJohn Marino #include "pointer-set.h"
47e4b17023SJohn Marino #include "tree-inline.h"
48e4b17023SJohn Marino
49e4b17023SJohn Marino /* This file contains functions for building the Control Flow Graph (CFG)
50e4b17023SJohn Marino for a function tree. */
51e4b17023SJohn Marino
52e4b17023SJohn Marino /* Local declarations. */
53e4b17023SJohn Marino
54e4b17023SJohn Marino /* Initial capacity for the basic block array. */
55e4b17023SJohn Marino static const int initial_cfg_capacity = 20;
56e4b17023SJohn Marino
57e4b17023SJohn Marino /* This hash table allows us to efficiently lookup all CASE_LABEL_EXPRs
58e4b17023SJohn Marino which use a particular edge. The CASE_LABEL_EXPRs are chained together
59e4b17023SJohn Marino via their TREE_CHAIN field, which we clear after we're done with the
60e4b17023SJohn Marino hash table to prevent problems with duplication of GIMPLE_SWITCHes.
61e4b17023SJohn Marino
62e4b17023SJohn Marino Access to this list of CASE_LABEL_EXPRs allows us to efficiently
63e4b17023SJohn Marino update the case vector in response to edge redirections.
64e4b17023SJohn Marino
65e4b17023SJohn Marino Right now this table is set up and torn down at key points in the
66e4b17023SJohn Marino compilation process. It would be nice if we could make the table
67e4b17023SJohn Marino more persistent. The key is getting notification of changes to
68e4b17023SJohn Marino the CFG (particularly edge removal, creation and redirection). */
69e4b17023SJohn Marino
70e4b17023SJohn Marino static struct pointer_map_t *edge_to_cases;
71e4b17023SJohn Marino
72e4b17023SJohn Marino /* If we record edge_to_cases, this bitmap will hold indexes
73e4b17023SJohn Marino of basic blocks that end in a GIMPLE_SWITCH which we touched
74e4b17023SJohn Marino due to edge manipulations. */
75e4b17023SJohn Marino
76e4b17023SJohn Marino static bitmap touched_switch_bbs;
77e4b17023SJohn Marino
78e4b17023SJohn Marino /* CFG statistics. */
79e4b17023SJohn Marino struct cfg_stats_d
80e4b17023SJohn Marino {
81e4b17023SJohn Marino long num_merged_labels;
82e4b17023SJohn Marino };
83e4b17023SJohn Marino
84e4b17023SJohn Marino static struct cfg_stats_d cfg_stats;
85e4b17023SJohn Marino
86e4b17023SJohn Marino /* Nonzero if we found a computed goto while building basic blocks. */
87e4b17023SJohn Marino static bool found_computed_goto;
88e4b17023SJohn Marino
89e4b17023SJohn Marino /* Hash table to store last discriminator assigned for each locus. */
90e4b17023SJohn Marino struct locus_discrim_map
91e4b17023SJohn Marino {
92e4b17023SJohn Marino location_t locus;
93e4b17023SJohn Marino int discriminator;
94e4b17023SJohn Marino };
95e4b17023SJohn Marino static htab_t discriminator_per_locus;
96e4b17023SJohn Marino
97e4b17023SJohn Marino /* Basic blocks and flowgraphs. */
98e4b17023SJohn Marino static void make_blocks (gimple_seq);
99e4b17023SJohn Marino static void factor_computed_gotos (void);
100e4b17023SJohn Marino
101e4b17023SJohn Marino /* Edges. */
102e4b17023SJohn Marino static void make_edges (void);
103e4b17023SJohn Marino static void make_cond_expr_edges (basic_block);
104e4b17023SJohn Marino static void make_gimple_switch_edges (basic_block);
105e4b17023SJohn Marino static void make_goto_expr_edges (basic_block);
106e4b17023SJohn Marino static void make_gimple_asm_edges (basic_block);
107e4b17023SJohn Marino static unsigned int locus_map_hash (const void *);
108e4b17023SJohn Marino static int locus_map_eq (const void *, const void *);
109e4b17023SJohn Marino static void assign_discriminator (location_t, basic_block);
110e4b17023SJohn Marino static edge gimple_redirect_edge_and_branch (edge, basic_block);
111e4b17023SJohn Marino static edge gimple_try_redirect_by_replacing_jump (edge, basic_block);
112e4b17023SJohn Marino
113e4b17023SJohn Marino /* Various helpers. */
114e4b17023SJohn Marino static inline bool stmt_starts_bb_p (gimple, gimple);
115e4b17023SJohn Marino static int gimple_verify_flow_info (void);
116e4b17023SJohn Marino static void gimple_make_forwarder_block (edge);
117e4b17023SJohn Marino static void gimple_cfg2vcg (FILE *);
118e4b17023SJohn Marino static gimple first_non_label_stmt (basic_block);
119e4b17023SJohn Marino static bool verify_gimple_transaction (gimple);
120e4b17023SJohn Marino
121e4b17023SJohn Marino /* Flowgraph optimization and cleanup. */
122e4b17023SJohn Marino static void gimple_merge_blocks (basic_block, basic_block);
123e4b17023SJohn Marino static bool gimple_can_merge_blocks_p (basic_block, basic_block);
124e4b17023SJohn Marino static void remove_bb (basic_block);
125e4b17023SJohn Marino static edge find_taken_edge_computed_goto (basic_block, tree);
126e4b17023SJohn Marino static edge find_taken_edge_cond_expr (basic_block, tree);
127e4b17023SJohn Marino static edge find_taken_edge_switch_expr (basic_block, tree);
128e4b17023SJohn Marino static tree find_case_label_for_value (gimple, tree);
129e4b17023SJohn Marino static void group_case_labels_stmt (gimple);
130e4b17023SJohn Marino
131e4b17023SJohn Marino void
init_empty_tree_cfg_for_function(struct function * fn)132e4b17023SJohn Marino init_empty_tree_cfg_for_function (struct function *fn)
133e4b17023SJohn Marino {
134e4b17023SJohn Marino /* Initialize the basic block array. */
135e4b17023SJohn Marino init_flow (fn);
136e4b17023SJohn Marino profile_status_for_function (fn) = PROFILE_ABSENT;
137e4b17023SJohn Marino n_basic_blocks_for_function (fn) = NUM_FIXED_BLOCKS;
138e4b17023SJohn Marino last_basic_block_for_function (fn) = NUM_FIXED_BLOCKS;
139e4b17023SJohn Marino basic_block_info_for_function (fn)
140e4b17023SJohn Marino = VEC_alloc (basic_block, gc, initial_cfg_capacity);
141e4b17023SJohn Marino VEC_safe_grow_cleared (basic_block, gc,
142e4b17023SJohn Marino basic_block_info_for_function (fn),
143e4b17023SJohn Marino initial_cfg_capacity);
144e4b17023SJohn Marino
145e4b17023SJohn Marino /* Build a mapping of labels to their associated blocks. */
146e4b17023SJohn Marino label_to_block_map_for_function (fn)
147e4b17023SJohn Marino = VEC_alloc (basic_block, gc, initial_cfg_capacity);
148e4b17023SJohn Marino VEC_safe_grow_cleared (basic_block, gc,
149e4b17023SJohn Marino label_to_block_map_for_function (fn),
150e4b17023SJohn Marino initial_cfg_capacity);
151e4b17023SJohn Marino
152e4b17023SJohn Marino SET_BASIC_BLOCK_FOR_FUNCTION (fn, ENTRY_BLOCK,
153e4b17023SJohn Marino ENTRY_BLOCK_PTR_FOR_FUNCTION (fn));
154e4b17023SJohn Marino SET_BASIC_BLOCK_FOR_FUNCTION (fn, EXIT_BLOCK,
155e4b17023SJohn Marino EXIT_BLOCK_PTR_FOR_FUNCTION (fn));
156e4b17023SJohn Marino
157e4b17023SJohn Marino ENTRY_BLOCK_PTR_FOR_FUNCTION (fn)->next_bb
158e4b17023SJohn Marino = EXIT_BLOCK_PTR_FOR_FUNCTION (fn);
159e4b17023SJohn Marino EXIT_BLOCK_PTR_FOR_FUNCTION (fn)->prev_bb
160e4b17023SJohn Marino = ENTRY_BLOCK_PTR_FOR_FUNCTION (fn);
161e4b17023SJohn Marino }
162e4b17023SJohn Marino
163e4b17023SJohn Marino void
init_empty_tree_cfg(void)164e4b17023SJohn Marino init_empty_tree_cfg (void)
165e4b17023SJohn Marino {
166e4b17023SJohn Marino init_empty_tree_cfg_for_function (cfun);
167e4b17023SJohn Marino }
168e4b17023SJohn Marino
169e4b17023SJohn Marino /*---------------------------------------------------------------------------
170e4b17023SJohn Marino Create basic blocks
171e4b17023SJohn Marino ---------------------------------------------------------------------------*/
172e4b17023SJohn Marino
173e4b17023SJohn Marino /* Entry point to the CFG builder for trees. SEQ is the sequence of
174e4b17023SJohn Marino statements to be added to the flowgraph. */
175e4b17023SJohn Marino
176e4b17023SJohn Marino static void
build_gimple_cfg(gimple_seq seq)177e4b17023SJohn Marino build_gimple_cfg (gimple_seq seq)
178e4b17023SJohn Marino {
179e4b17023SJohn Marino /* Register specific gimple functions. */
180e4b17023SJohn Marino gimple_register_cfg_hooks ();
181e4b17023SJohn Marino
182e4b17023SJohn Marino memset ((void *) &cfg_stats, 0, sizeof (cfg_stats));
183e4b17023SJohn Marino
184e4b17023SJohn Marino init_empty_tree_cfg ();
185e4b17023SJohn Marino
186e4b17023SJohn Marino found_computed_goto = 0;
187e4b17023SJohn Marino make_blocks (seq);
188e4b17023SJohn Marino
189e4b17023SJohn Marino /* Computed gotos are hell to deal with, especially if there are
190e4b17023SJohn Marino lots of them with a large number of destinations. So we factor
191e4b17023SJohn Marino them to a common computed goto location before we build the
192e4b17023SJohn Marino edge list. After we convert back to normal form, we will un-factor
193e4b17023SJohn Marino the computed gotos since factoring introduces an unwanted jump. */
194e4b17023SJohn Marino if (found_computed_goto)
195e4b17023SJohn Marino factor_computed_gotos ();
196e4b17023SJohn Marino
197e4b17023SJohn Marino /* Make sure there is always at least one block, even if it's empty. */
198e4b17023SJohn Marino if (n_basic_blocks == NUM_FIXED_BLOCKS)
199e4b17023SJohn Marino create_empty_bb (ENTRY_BLOCK_PTR);
200e4b17023SJohn Marino
201e4b17023SJohn Marino /* Adjust the size of the array. */
202e4b17023SJohn Marino if (VEC_length (basic_block, basic_block_info) < (size_t) n_basic_blocks)
203e4b17023SJohn Marino VEC_safe_grow_cleared (basic_block, gc, basic_block_info, n_basic_blocks);
204e4b17023SJohn Marino
205e4b17023SJohn Marino /* To speed up statement iterator walks, we first purge dead labels. */
206e4b17023SJohn Marino cleanup_dead_labels ();
207e4b17023SJohn Marino
208e4b17023SJohn Marino /* Group case nodes to reduce the number of edges.
209e4b17023SJohn Marino We do this after cleaning up dead labels because otherwise we miss
210e4b17023SJohn Marino a lot of obvious case merging opportunities. */
211e4b17023SJohn Marino group_case_labels ();
212e4b17023SJohn Marino
213e4b17023SJohn Marino /* Create the edges of the flowgraph. */
214e4b17023SJohn Marino discriminator_per_locus = htab_create (13, locus_map_hash, locus_map_eq,
215e4b17023SJohn Marino free);
216e4b17023SJohn Marino make_edges ();
217e4b17023SJohn Marino cleanup_dead_labels ();
218e4b17023SJohn Marino htab_delete (discriminator_per_locus);
219e4b17023SJohn Marino
220e4b17023SJohn Marino /* Debugging dumps. */
221e4b17023SJohn Marino
222e4b17023SJohn Marino /* Write the flowgraph to a VCG file. */
223e4b17023SJohn Marino {
224e4b17023SJohn Marino int local_dump_flags;
225e4b17023SJohn Marino FILE *vcg_file = dump_begin (TDI_vcg, &local_dump_flags);
226e4b17023SJohn Marino if (vcg_file)
227e4b17023SJohn Marino {
228e4b17023SJohn Marino gimple_cfg2vcg (vcg_file);
229e4b17023SJohn Marino dump_end (TDI_vcg, vcg_file);
230e4b17023SJohn Marino }
231e4b17023SJohn Marino }
232e4b17023SJohn Marino }
233e4b17023SJohn Marino
234e4b17023SJohn Marino static unsigned int
execute_build_cfg(void)235e4b17023SJohn Marino execute_build_cfg (void)
236e4b17023SJohn Marino {
237e4b17023SJohn Marino gimple_seq body = gimple_body (current_function_decl);
238e4b17023SJohn Marino
239e4b17023SJohn Marino build_gimple_cfg (body);
240e4b17023SJohn Marino gimple_set_body (current_function_decl, NULL);
241e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS))
242e4b17023SJohn Marino {
243e4b17023SJohn Marino fprintf (dump_file, "Scope blocks:\n");
244e4b17023SJohn Marino dump_scope_blocks (dump_file, dump_flags);
245e4b17023SJohn Marino }
246e4b17023SJohn Marino return 0;
247e4b17023SJohn Marino }
248e4b17023SJohn Marino
249e4b17023SJohn Marino struct gimple_opt_pass pass_build_cfg =
250e4b17023SJohn Marino {
251e4b17023SJohn Marino {
252e4b17023SJohn Marino GIMPLE_PASS,
253e4b17023SJohn Marino "cfg", /* name */
254e4b17023SJohn Marino NULL, /* gate */
255e4b17023SJohn Marino execute_build_cfg, /* execute */
256e4b17023SJohn Marino NULL, /* sub */
257e4b17023SJohn Marino NULL, /* next */
258e4b17023SJohn Marino 0, /* static_pass_number */
259e4b17023SJohn Marino TV_TREE_CFG, /* tv_id */
260e4b17023SJohn Marino PROP_gimple_leh, /* properties_required */
261e4b17023SJohn Marino PROP_cfg, /* properties_provided */
262e4b17023SJohn Marino 0, /* properties_destroyed */
263e4b17023SJohn Marino 0, /* todo_flags_start */
264e4b17023SJohn Marino TODO_verify_stmts | TODO_cleanup_cfg /* todo_flags_finish */
265e4b17023SJohn Marino }
266e4b17023SJohn Marino };
267e4b17023SJohn Marino
268e4b17023SJohn Marino
269e4b17023SJohn Marino /* Return true if T is a computed goto. */
270e4b17023SJohn Marino
271e4b17023SJohn Marino static bool
computed_goto_p(gimple t)272e4b17023SJohn Marino computed_goto_p (gimple t)
273e4b17023SJohn Marino {
274e4b17023SJohn Marino return (gimple_code (t) == GIMPLE_GOTO
275e4b17023SJohn Marino && TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL);
276e4b17023SJohn Marino }
277e4b17023SJohn Marino
278e4b17023SJohn Marino
279e4b17023SJohn Marino /* Search the CFG for any computed gotos. If found, factor them to a
280e4b17023SJohn Marino common computed goto site. Also record the location of that site so
281e4b17023SJohn Marino that we can un-factor the gotos after we have converted back to
282e4b17023SJohn Marino normal form. */
283e4b17023SJohn Marino
284e4b17023SJohn Marino static void
factor_computed_gotos(void)285e4b17023SJohn Marino factor_computed_gotos (void)
286e4b17023SJohn Marino {
287e4b17023SJohn Marino basic_block bb;
288e4b17023SJohn Marino tree factored_label_decl = NULL;
289e4b17023SJohn Marino tree var = NULL;
290e4b17023SJohn Marino gimple factored_computed_goto_label = NULL;
291e4b17023SJohn Marino gimple factored_computed_goto = NULL;
292e4b17023SJohn Marino
293e4b17023SJohn Marino /* We know there are one or more computed gotos in this function.
294e4b17023SJohn Marino Examine the last statement in each basic block to see if the block
295e4b17023SJohn Marino ends with a computed goto. */
296e4b17023SJohn Marino
297e4b17023SJohn Marino FOR_EACH_BB (bb)
298e4b17023SJohn Marino {
299e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last_bb (bb);
300e4b17023SJohn Marino gimple last;
301e4b17023SJohn Marino
302e4b17023SJohn Marino if (gsi_end_p (gsi))
303e4b17023SJohn Marino continue;
304e4b17023SJohn Marino
305e4b17023SJohn Marino last = gsi_stmt (gsi);
306e4b17023SJohn Marino
307e4b17023SJohn Marino /* Ignore the computed goto we create when we factor the original
308e4b17023SJohn Marino computed gotos. */
309e4b17023SJohn Marino if (last == factored_computed_goto)
310e4b17023SJohn Marino continue;
311e4b17023SJohn Marino
312e4b17023SJohn Marino /* If the last statement is a computed goto, factor it. */
313e4b17023SJohn Marino if (computed_goto_p (last))
314e4b17023SJohn Marino {
315e4b17023SJohn Marino gimple assignment;
316e4b17023SJohn Marino
317e4b17023SJohn Marino /* The first time we find a computed goto we need to create
318e4b17023SJohn Marino the factored goto block and the variable each original
319e4b17023SJohn Marino computed goto will use for their goto destination. */
320e4b17023SJohn Marino if (!factored_computed_goto)
321e4b17023SJohn Marino {
322e4b17023SJohn Marino basic_block new_bb = create_empty_bb (bb);
323e4b17023SJohn Marino gimple_stmt_iterator new_gsi = gsi_start_bb (new_bb);
324e4b17023SJohn Marino
325e4b17023SJohn Marino /* Create the destination of the factored goto. Each original
326e4b17023SJohn Marino computed goto will put its desired destination into this
327e4b17023SJohn Marino variable and jump to the label we create immediately
328e4b17023SJohn Marino below. */
329e4b17023SJohn Marino var = create_tmp_var (ptr_type_node, "gotovar");
330e4b17023SJohn Marino
331e4b17023SJohn Marino /* Build a label for the new block which will contain the
332e4b17023SJohn Marino factored computed goto. */
333e4b17023SJohn Marino factored_label_decl = create_artificial_label (UNKNOWN_LOCATION);
334e4b17023SJohn Marino factored_computed_goto_label
335e4b17023SJohn Marino = gimple_build_label (factored_label_decl);
336e4b17023SJohn Marino gsi_insert_after (&new_gsi, factored_computed_goto_label,
337e4b17023SJohn Marino GSI_NEW_STMT);
338e4b17023SJohn Marino
339e4b17023SJohn Marino /* Build our new computed goto. */
340e4b17023SJohn Marino factored_computed_goto = gimple_build_goto (var);
341e4b17023SJohn Marino gsi_insert_after (&new_gsi, factored_computed_goto, GSI_NEW_STMT);
342e4b17023SJohn Marino }
343e4b17023SJohn Marino
344e4b17023SJohn Marino /* Copy the original computed goto's destination into VAR. */
345e4b17023SJohn Marino assignment = gimple_build_assign (var, gimple_goto_dest (last));
346e4b17023SJohn Marino gsi_insert_before (&gsi, assignment, GSI_SAME_STMT);
347e4b17023SJohn Marino
348e4b17023SJohn Marino /* And re-vector the computed goto to the new destination. */
349e4b17023SJohn Marino gimple_goto_set_dest (last, factored_label_decl);
350e4b17023SJohn Marino }
351e4b17023SJohn Marino }
352e4b17023SJohn Marino }
353e4b17023SJohn Marino
354e4b17023SJohn Marino
355e4b17023SJohn Marino /* Build a flowgraph for the sequence of stmts SEQ. */
356e4b17023SJohn Marino
357e4b17023SJohn Marino static void
make_blocks(gimple_seq seq)358e4b17023SJohn Marino make_blocks (gimple_seq seq)
359e4b17023SJohn Marino {
360e4b17023SJohn Marino gimple_stmt_iterator i = gsi_start (seq);
361e4b17023SJohn Marino gimple stmt = NULL;
362e4b17023SJohn Marino bool start_new_block = true;
363e4b17023SJohn Marino bool first_stmt_of_seq = true;
364e4b17023SJohn Marino basic_block bb = ENTRY_BLOCK_PTR;
365e4b17023SJohn Marino
366e4b17023SJohn Marino while (!gsi_end_p (i))
367e4b17023SJohn Marino {
368e4b17023SJohn Marino gimple prev_stmt;
369e4b17023SJohn Marino
370e4b17023SJohn Marino prev_stmt = stmt;
371e4b17023SJohn Marino stmt = gsi_stmt (i);
372e4b17023SJohn Marino
373e4b17023SJohn Marino /* If the statement starts a new basic block or if we have determined
374e4b17023SJohn Marino in a previous pass that we need to create a new block for STMT, do
375e4b17023SJohn Marino so now. */
376e4b17023SJohn Marino if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
377e4b17023SJohn Marino {
378e4b17023SJohn Marino if (!first_stmt_of_seq)
379e4b17023SJohn Marino seq = gsi_split_seq_before (&i);
380e4b17023SJohn Marino bb = create_basic_block (seq, NULL, bb);
381e4b17023SJohn Marino start_new_block = false;
382e4b17023SJohn Marino }
383e4b17023SJohn Marino
384e4b17023SJohn Marino /* Now add STMT to BB and create the subgraphs for special statement
385e4b17023SJohn Marino codes. */
386e4b17023SJohn Marino gimple_set_bb (stmt, bb);
387e4b17023SJohn Marino
388e4b17023SJohn Marino if (computed_goto_p (stmt))
389e4b17023SJohn Marino found_computed_goto = true;
390e4b17023SJohn Marino
391e4b17023SJohn Marino /* If STMT is a basic block terminator, set START_NEW_BLOCK for the
392e4b17023SJohn Marino next iteration. */
393e4b17023SJohn Marino if (stmt_ends_bb_p (stmt))
394e4b17023SJohn Marino {
395e4b17023SJohn Marino /* If the stmt can make abnormal goto use a new temporary
396e4b17023SJohn Marino for the assignment to the LHS. This makes sure the old value
397e4b17023SJohn Marino of the LHS is available on the abnormal edge. Otherwise
398e4b17023SJohn Marino we will end up with overlapping life-ranges for abnormal
399e4b17023SJohn Marino SSA names. */
400e4b17023SJohn Marino if (gimple_has_lhs (stmt)
401e4b17023SJohn Marino && stmt_can_make_abnormal_goto (stmt)
402e4b17023SJohn Marino && is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt))))
403e4b17023SJohn Marino {
404e4b17023SJohn Marino tree lhs = gimple_get_lhs (stmt);
405e4b17023SJohn Marino tree tmp = create_tmp_var (TREE_TYPE (lhs), NULL);
406e4b17023SJohn Marino gimple s = gimple_build_assign (lhs, tmp);
407e4b17023SJohn Marino gimple_set_location (s, gimple_location (stmt));
408e4b17023SJohn Marino gimple_set_block (s, gimple_block (stmt));
409e4b17023SJohn Marino gimple_set_lhs (stmt, tmp);
410e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
411e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
412e4b17023SJohn Marino DECL_GIMPLE_REG_P (tmp) = 1;
413e4b17023SJohn Marino gsi_insert_after (&i, s, GSI_SAME_STMT);
414e4b17023SJohn Marino }
415e4b17023SJohn Marino start_new_block = true;
416e4b17023SJohn Marino }
417e4b17023SJohn Marino
418e4b17023SJohn Marino gsi_next (&i);
419e4b17023SJohn Marino first_stmt_of_seq = false;
420e4b17023SJohn Marino }
421e4b17023SJohn Marino }
422e4b17023SJohn Marino
423e4b17023SJohn Marino
424e4b17023SJohn Marino /* Create and return a new empty basic block after bb AFTER. */
425e4b17023SJohn Marino
426e4b17023SJohn Marino static basic_block
create_bb(void * h,void * e,basic_block after)427e4b17023SJohn Marino create_bb (void *h, void *e, basic_block after)
428e4b17023SJohn Marino {
429e4b17023SJohn Marino basic_block bb;
430e4b17023SJohn Marino
431e4b17023SJohn Marino gcc_assert (!e);
432e4b17023SJohn Marino
433e4b17023SJohn Marino /* Create and initialize a new basic block. Since alloc_block uses
434e4b17023SJohn Marino GC allocation that clears memory to allocate a basic block, we do
435e4b17023SJohn Marino not have to clear the newly allocated basic block here. */
436e4b17023SJohn Marino bb = alloc_block ();
437e4b17023SJohn Marino
438e4b17023SJohn Marino bb->index = last_basic_block;
439e4b17023SJohn Marino bb->flags = BB_NEW;
440e4b17023SJohn Marino bb->il.gimple = ggc_alloc_cleared_gimple_bb_info ();
441e4b17023SJohn Marino set_bb_seq (bb, h ? (gimple_seq) h : gimple_seq_alloc ());
442e4b17023SJohn Marino
443e4b17023SJohn Marino /* Add the new block to the linked list of blocks. */
444e4b17023SJohn Marino link_block (bb, after);
445e4b17023SJohn Marino
446e4b17023SJohn Marino /* Grow the basic block array if needed. */
447e4b17023SJohn Marino if ((size_t) last_basic_block == VEC_length (basic_block, basic_block_info))
448e4b17023SJohn Marino {
449e4b17023SJohn Marino size_t new_size = last_basic_block + (last_basic_block + 3) / 4;
450e4b17023SJohn Marino VEC_safe_grow_cleared (basic_block, gc, basic_block_info, new_size);
451e4b17023SJohn Marino }
452e4b17023SJohn Marino
453e4b17023SJohn Marino /* Add the newly created block to the array. */
454e4b17023SJohn Marino SET_BASIC_BLOCK (last_basic_block, bb);
455e4b17023SJohn Marino
456e4b17023SJohn Marino n_basic_blocks++;
457e4b17023SJohn Marino last_basic_block++;
458e4b17023SJohn Marino
459e4b17023SJohn Marino return bb;
460e4b17023SJohn Marino }
461e4b17023SJohn Marino
462e4b17023SJohn Marino
463e4b17023SJohn Marino /*---------------------------------------------------------------------------
464e4b17023SJohn Marino Edge creation
465e4b17023SJohn Marino ---------------------------------------------------------------------------*/
466e4b17023SJohn Marino
467e4b17023SJohn Marino /* Fold COND_EXPR_COND of each COND_EXPR. */
468e4b17023SJohn Marino
469e4b17023SJohn Marino void
fold_cond_expr_cond(void)470e4b17023SJohn Marino fold_cond_expr_cond (void)
471e4b17023SJohn Marino {
472e4b17023SJohn Marino basic_block bb;
473e4b17023SJohn Marino
474e4b17023SJohn Marino FOR_EACH_BB (bb)
475e4b17023SJohn Marino {
476e4b17023SJohn Marino gimple stmt = last_stmt (bb);
477e4b17023SJohn Marino
478e4b17023SJohn Marino if (stmt && gimple_code (stmt) == GIMPLE_COND)
479e4b17023SJohn Marino {
480e4b17023SJohn Marino location_t loc = gimple_location (stmt);
481e4b17023SJohn Marino tree cond;
482e4b17023SJohn Marino bool zerop, onep;
483e4b17023SJohn Marino
484e4b17023SJohn Marino fold_defer_overflow_warnings ();
485e4b17023SJohn Marino cond = fold_binary_loc (loc, gimple_cond_code (stmt), boolean_type_node,
486e4b17023SJohn Marino gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
487e4b17023SJohn Marino if (cond)
488e4b17023SJohn Marino {
489e4b17023SJohn Marino zerop = integer_zerop (cond);
490e4b17023SJohn Marino onep = integer_onep (cond);
491e4b17023SJohn Marino }
492e4b17023SJohn Marino else
493e4b17023SJohn Marino zerop = onep = false;
494e4b17023SJohn Marino
495e4b17023SJohn Marino fold_undefer_overflow_warnings (zerop || onep,
496e4b17023SJohn Marino stmt,
497e4b17023SJohn Marino WARN_STRICT_OVERFLOW_CONDITIONAL);
498e4b17023SJohn Marino if (zerop)
499e4b17023SJohn Marino gimple_cond_make_false (stmt);
500e4b17023SJohn Marino else if (onep)
501e4b17023SJohn Marino gimple_cond_make_true (stmt);
502e4b17023SJohn Marino }
503e4b17023SJohn Marino }
504e4b17023SJohn Marino }
505e4b17023SJohn Marino
506e4b17023SJohn Marino /* Join all the blocks in the flowgraph. */
507e4b17023SJohn Marino
508e4b17023SJohn Marino static void
make_edges(void)509e4b17023SJohn Marino make_edges (void)
510e4b17023SJohn Marino {
511e4b17023SJohn Marino basic_block bb;
512e4b17023SJohn Marino struct omp_region *cur_region = NULL;
513e4b17023SJohn Marino
514e4b17023SJohn Marino /* Create an edge from entry to the first block with executable
515e4b17023SJohn Marino statements in it. */
516e4b17023SJohn Marino make_edge (ENTRY_BLOCK_PTR, BASIC_BLOCK (NUM_FIXED_BLOCKS), EDGE_FALLTHRU);
517e4b17023SJohn Marino
518e4b17023SJohn Marino /* Traverse the basic block array placing edges. */
519e4b17023SJohn Marino FOR_EACH_BB (bb)
520e4b17023SJohn Marino {
521e4b17023SJohn Marino gimple last = last_stmt (bb);
522e4b17023SJohn Marino bool fallthru;
523e4b17023SJohn Marino
524e4b17023SJohn Marino if (last)
525e4b17023SJohn Marino {
526e4b17023SJohn Marino enum gimple_code code = gimple_code (last);
527e4b17023SJohn Marino switch (code)
528e4b17023SJohn Marino {
529e4b17023SJohn Marino case GIMPLE_GOTO:
530e4b17023SJohn Marino make_goto_expr_edges (bb);
531e4b17023SJohn Marino fallthru = false;
532e4b17023SJohn Marino break;
533e4b17023SJohn Marino case GIMPLE_RETURN:
534e4b17023SJohn Marino make_edge (bb, EXIT_BLOCK_PTR, 0);
535e4b17023SJohn Marino fallthru = false;
536e4b17023SJohn Marino break;
537e4b17023SJohn Marino case GIMPLE_COND:
538e4b17023SJohn Marino make_cond_expr_edges (bb);
539e4b17023SJohn Marino fallthru = false;
540e4b17023SJohn Marino break;
541e4b17023SJohn Marino case GIMPLE_SWITCH:
542e4b17023SJohn Marino make_gimple_switch_edges (bb);
543e4b17023SJohn Marino fallthru = false;
544e4b17023SJohn Marino break;
545e4b17023SJohn Marino case GIMPLE_RESX:
546e4b17023SJohn Marino make_eh_edges (last);
547e4b17023SJohn Marino fallthru = false;
548e4b17023SJohn Marino break;
549e4b17023SJohn Marino case GIMPLE_EH_DISPATCH:
550e4b17023SJohn Marino fallthru = make_eh_dispatch_edges (last);
551e4b17023SJohn Marino break;
552e4b17023SJohn Marino
553e4b17023SJohn Marino case GIMPLE_CALL:
554e4b17023SJohn Marino /* If this function receives a nonlocal goto, then we need to
555e4b17023SJohn Marino make edges from this call site to all the nonlocal goto
556e4b17023SJohn Marino handlers. */
557e4b17023SJohn Marino if (stmt_can_make_abnormal_goto (last))
558e4b17023SJohn Marino make_abnormal_goto_edges (bb, true);
559e4b17023SJohn Marino
560e4b17023SJohn Marino /* If this statement has reachable exception handlers, then
561e4b17023SJohn Marino create abnormal edges to them. */
562e4b17023SJohn Marino make_eh_edges (last);
563e4b17023SJohn Marino
564e4b17023SJohn Marino /* BUILTIN_RETURN is really a return statement. */
565e4b17023SJohn Marino if (gimple_call_builtin_p (last, BUILT_IN_RETURN))
566e4b17023SJohn Marino make_edge (bb, EXIT_BLOCK_PTR, 0), fallthru = false;
567e4b17023SJohn Marino /* Some calls are known not to return. */
568e4b17023SJohn Marino else
569e4b17023SJohn Marino fallthru = !(gimple_call_flags (last) & ECF_NORETURN);
570e4b17023SJohn Marino break;
571e4b17023SJohn Marino
572e4b17023SJohn Marino case GIMPLE_ASSIGN:
573e4b17023SJohn Marino /* A GIMPLE_ASSIGN may throw internally and thus be considered
574e4b17023SJohn Marino control-altering. */
575e4b17023SJohn Marino if (is_ctrl_altering_stmt (last))
576e4b17023SJohn Marino make_eh_edges (last);
577e4b17023SJohn Marino fallthru = true;
578e4b17023SJohn Marino break;
579e4b17023SJohn Marino
580e4b17023SJohn Marino case GIMPLE_ASM:
581e4b17023SJohn Marino make_gimple_asm_edges (bb);
582e4b17023SJohn Marino fallthru = true;
583e4b17023SJohn Marino break;
584e4b17023SJohn Marino
585e4b17023SJohn Marino case GIMPLE_OMP_PARALLEL:
586e4b17023SJohn Marino case GIMPLE_OMP_TASK:
587e4b17023SJohn Marino case GIMPLE_OMP_FOR:
588e4b17023SJohn Marino case GIMPLE_OMP_SINGLE:
589e4b17023SJohn Marino case GIMPLE_OMP_MASTER:
590e4b17023SJohn Marino case GIMPLE_OMP_ORDERED:
591e4b17023SJohn Marino case GIMPLE_OMP_CRITICAL:
592e4b17023SJohn Marino case GIMPLE_OMP_SECTION:
593e4b17023SJohn Marino cur_region = new_omp_region (bb, code, cur_region);
594e4b17023SJohn Marino fallthru = true;
595e4b17023SJohn Marino break;
596e4b17023SJohn Marino
597e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS:
598e4b17023SJohn Marino cur_region = new_omp_region (bb, code, cur_region);
599e4b17023SJohn Marino fallthru = true;
600e4b17023SJohn Marino break;
601e4b17023SJohn Marino
602e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS_SWITCH:
603e4b17023SJohn Marino fallthru = false;
604e4b17023SJohn Marino break;
605e4b17023SJohn Marino
606e4b17023SJohn Marino case GIMPLE_OMP_ATOMIC_LOAD:
607e4b17023SJohn Marino case GIMPLE_OMP_ATOMIC_STORE:
608e4b17023SJohn Marino fallthru = true;
609e4b17023SJohn Marino break;
610e4b17023SJohn Marino
611e4b17023SJohn Marino case GIMPLE_OMP_RETURN:
612e4b17023SJohn Marino /* In the case of a GIMPLE_OMP_SECTION, the edge will go
613e4b17023SJohn Marino somewhere other than the next block. This will be
614e4b17023SJohn Marino created later. */
615e4b17023SJohn Marino cur_region->exit = bb;
616e4b17023SJohn Marino fallthru = cur_region->type != GIMPLE_OMP_SECTION;
617e4b17023SJohn Marino cur_region = cur_region->outer;
618e4b17023SJohn Marino break;
619e4b17023SJohn Marino
620e4b17023SJohn Marino case GIMPLE_OMP_CONTINUE:
621e4b17023SJohn Marino cur_region->cont = bb;
622e4b17023SJohn Marino switch (cur_region->type)
623e4b17023SJohn Marino {
624e4b17023SJohn Marino case GIMPLE_OMP_FOR:
625e4b17023SJohn Marino /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
626e4b17023SJohn Marino succs edges as abnormal to prevent splitting
627e4b17023SJohn Marino them. */
628e4b17023SJohn Marino single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
629e4b17023SJohn Marino /* Make the loopback edge. */
630e4b17023SJohn Marino make_edge (bb, single_succ (cur_region->entry),
631e4b17023SJohn Marino EDGE_ABNORMAL);
632e4b17023SJohn Marino
633e4b17023SJohn Marino /* Create an edge from GIMPLE_OMP_FOR to exit, which
634e4b17023SJohn Marino corresponds to the case that the body of the loop
635e4b17023SJohn Marino is not executed at all. */
636e4b17023SJohn Marino make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
637e4b17023SJohn Marino make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
638e4b17023SJohn Marino fallthru = false;
639e4b17023SJohn Marino break;
640e4b17023SJohn Marino
641e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS:
642e4b17023SJohn Marino /* Wire up the edges into and out of the nested sections. */
643e4b17023SJohn Marino {
644e4b17023SJohn Marino basic_block switch_bb = single_succ (cur_region->entry);
645e4b17023SJohn Marino
646e4b17023SJohn Marino struct omp_region *i;
647e4b17023SJohn Marino for (i = cur_region->inner; i ; i = i->next)
648e4b17023SJohn Marino {
649e4b17023SJohn Marino gcc_assert (i->type == GIMPLE_OMP_SECTION);
650e4b17023SJohn Marino make_edge (switch_bb, i->entry, 0);
651e4b17023SJohn Marino make_edge (i->exit, bb, EDGE_FALLTHRU);
652e4b17023SJohn Marino }
653e4b17023SJohn Marino
654e4b17023SJohn Marino /* Make the loopback edge to the block with
655e4b17023SJohn Marino GIMPLE_OMP_SECTIONS_SWITCH. */
656e4b17023SJohn Marino make_edge (bb, switch_bb, 0);
657e4b17023SJohn Marino
658e4b17023SJohn Marino /* Make the edge from the switch to exit. */
659e4b17023SJohn Marino make_edge (switch_bb, bb->next_bb, 0);
660e4b17023SJohn Marino fallthru = false;
661e4b17023SJohn Marino }
662e4b17023SJohn Marino break;
663e4b17023SJohn Marino
664e4b17023SJohn Marino default:
665e4b17023SJohn Marino gcc_unreachable ();
666e4b17023SJohn Marino }
667e4b17023SJohn Marino break;
668e4b17023SJohn Marino
669e4b17023SJohn Marino case GIMPLE_TRANSACTION:
670e4b17023SJohn Marino {
671e4b17023SJohn Marino tree abort_label = gimple_transaction_label (last);
672e4b17023SJohn Marino if (abort_label)
673e4b17023SJohn Marino make_edge (bb, label_to_block (abort_label), 0);
674e4b17023SJohn Marino fallthru = true;
675e4b17023SJohn Marino }
676e4b17023SJohn Marino break;
677e4b17023SJohn Marino
678e4b17023SJohn Marino default:
679e4b17023SJohn Marino gcc_assert (!stmt_ends_bb_p (last));
680e4b17023SJohn Marino fallthru = true;
681e4b17023SJohn Marino }
682e4b17023SJohn Marino }
683e4b17023SJohn Marino else
684e4b17023SJohn Marino fallthru = true;
685e4b17023SJohn Marino
686e4b17023SJohn Marino if (fallthru)
687e4b17023SJohn Marino {
688e4b17023SJohn Marino make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
689e4b17023SJohn Marino if (last)
690e4b17023SJohn Marino assign_discriminator (gimple_location (last), bb->next_bb);
691e4b17023SJohn Marino }
692e4b17023SJohn Marino }
693e4b17023SJohn Marino
694e4b17023SJohn Marino if (root_omp_region)
695e4b17023SJohn Marino free_omp_regions ();
696e4b17023SJohn Marino
697e4b17023SJohn Marino /* Fold COND_EXPR_COND of each COND_EXPR. */
698e4b17023SJohn Marino fold_cond_expr_cond ();
699e4b17023SJohn Marino }
700e4b17023SJohn Marino
701e4b17023SJohn Marino /* Trivial hash function for a location_t. ITEM is a pointer to
702e4b17023SJohn Marino a hash table entry that maps a location_t to a discriminator. */
703e4b17023SJohn Marino
704e4b17023SJohn Marino static unsigned int
locus_map_hash(const void * item)705e4b17023SJohn Marino locus_map_hash (const void *item)
706e4b17023SJohn Marino {
707e4b17023SJohn Marino return ((const struct locus_discrim_map *) item)->locus;
708e4b17023SJohn Marino }
709e4b17023SJohn Marino
710e4b17023SJohn Marino /* Equality function for the locus-to-discriminator map. VA and VB
711e4b17023SJohn Marino point to the two hash table entries to compare. */
712e4b17023SJohn Marino
713e4b17023SJohn Marino static int
locus_map_eq(const void * va,const void * vb)714e4b17023SJohn Marino locus_map_eq (const void *va, const void *vb)
715e4b17023SJohn Marino {
716e4b17023SJohn Marino const struct locus_discrim_map *a = (const struct locus_discrim_map *) va;
717e4b17023SJohn Marino const struct locus_discrim_map *b = (const struct locus_discrim_map *) vb;
718e4b17023SJohn Marino return a->locus == b->locus;
719e4b17023SJohn Marino }
720e4b17023SJohn Marino
721e4b17023SJohn Marino /* Find the next available discriminator value for LOCUS. The
722e4b17023SJohn Marino discriminator distinguishes among several basic blocks that
723e4b17023SJohn Marino share a common locus, allowing for more accurate sample-based
724e4b17023SJohn Marino profiling. */
725e4b17023SJohn Marino
726e4b17023SJohn Marino static int
next_discriminator_for_locus(location_t locus)727e4b17023SJohn Marino next_discriminator_for_locus (location_t locus)
728e4b17023SJohn Marino {
729e4b17023SJohn Marino struct locus_discrim_map item;
730e4b17023SJohn Marino struct locus_discrim_map **slot;
731e4b17023SJohn Marino
732e4b17023SJohn Marino item.locus = locus;
733e4b17023SJohn Marino item.discriminator = 0;
734e4b17023SJohn Marino slot = (struct locus_discrim_map **)
735e4b17023SJohn Marino htab_find_slot_with_hash (discriminator_per_locus, (void *) &item,
736e4b17023SJohn Marino (hashval_t) locus, INSERT);
737e4b17023SJohn Marino gcc_assert (slot);
738e4b17023SJohn Marino if (*slot == HTAB_EMPTY_ENTRY)
739e4b17023SJohn Marino {
740e4b17023SJohn Marino *slot = XNEW (struct locus_discrim_map);
741e4b17023SJohn Marino gcc_assert (*slot);
742e4b17023SJohn Marino (*slot)->locus = locus;
743e4b17023SJohn Marino (*slot)->discriminator = 0;
744e4b17023SJohn Marino }
745e4b17023SJohn Marino (*slot)->discriminator++;
746e4b17023SJohn Marino return (*slot)->discriminator;
747e4b17023SJohn Marino }
748e4b17023SJohn Marino
749e4b17023SJohn Marino /* Return TRUE if LOCUS1 and LOCUS2 refer to the same source line. */
750e4b17023SJohn Marino
751e4b17023SJohn Marino static bool
same_line_p(location_t locus1,location_t locus2)752e4b17023SJohn Marino same_line_p (location_t locus1, location_t locus2)
753e4b17023SJohn Marino {
754e4b17023SJohn Marino expanded_location from, to;
755e4b17023SJohn Marino
756e4b17023SJohn Marino if (locus1 == locus2)
757e4b17023SJohn Marino return true;
758e4b17023SJohn Marino
759e4b17023SJohn Marino from = expand_location (locus1);
760e4b17023SJohn Marino to = expand_location (locus2);
761e4b17023SJohn Marino
762e4b17023SJohn Marino if (from.line != to.line)
763e4b17023SJohn Marino return false;
764e4b17023SJohn Marino if (from.file == to.file)
765e4b17023SJohn Marino return true;
766e4b17023SJohn Marino return (from.file != NULL
767e4b17023SJohn Marino && to.file != NULL
768e4b17023SJohn Marino && filename_cmp (from.file, to.file) == 0);
769e4b17023SJohn Marino }
770e4b17023SJohn Marino
771e4b17023SJohn Marino /* Assign a unique discriminator value to block BB if it begins at the same
772e4b17023SJohn Marino LOCUS as its predecessor block. */
773e4b17023SJohn Marino
774e4b17023SJohn Marino static void
assign_discriminator(location_t locus,basic_block bb)775e4b17023SJohn Marino assign_discriminator (location_t locus, basic_block bb)
776e4b17023SJohn Marino {
777e4b17023SJohn Marino gimple first_in_to_bb, last_in_to_bb;
778e4b17023SJohn Marino
779e4b17023SJohn Marino if (locus == 0 || bb->discriminator != 0)
780e4b17023SJohn Marino return;
781e4b17023SJohn Marino
782e4b17023SJohn Marino first_in_to_bb = first_non_label_stmt (bb);
783e4b17023SJohn Marino last_in_to_bb = last_stmt (bb);
784e4b17023SJohn Marino if ((first_in_to_bb && same_line_p (locus, gimple_location (first_in_to_bb)))
785e4b17023SJohn Marino || (last_in_to_bb && same_line_p (locus, gimple_location (last_in_to_bb))))
786e4b17023SJohn Marino bb->discriminator = next_discriminator_for_locus (locus);
787e4b17023SJohn Marino }
788e4b17023SJohn Marino
789e4b17023SJohn Marino /* Create the edges for a GIMPLE_COND starting at block BB. */
790e4b17023SJohn Marino
791e4b17023SJohn Marino static void
make_cond_expr_edges(basic_block bb)792e4b17023SJohn Marino make_cond_expr_edges (basic_block bb)
793e4b17023SJohn Marino {
794e4b17023SJohn Marino gimple entry = last_stmt (bb);
795e4b17023SJohn Marino gimple then_stmt, else_stmt;
796e4b17023SJohn Marino basic_block then_bb, else_bb;
797e4b17023SJohn Marino tree then_label, else_label;
798e4b17023SJohn Marino edge e;
799e4b17023SJohn Marino location_t entry_locus;
800e4b17023SJohn Marino
801e4b17023SJohn Marino gcc_assert (entry);
802e4b17023SJohn Marino gcc_assert (gimple_code (entry) == GIMPLE_COND);
803e4b17023SJohn Marino
804e4b17023SJohn Marino entry_locus = gimple_location (entry);
805e4b17023SJohn Marino
806e4b17023SJohn Marino /* Entry basic blocks for each component. */
807e4b17023SJohn Marino then_label = gimple_cond_true_label (entry);
808e4b17023SJohn Marino else_label = gimple_cond_false_label (entry);
809e4b17023SJohn Marino then_bb = label_to_block (then_label);
810e4b17023SJohn Marino else_bb = label_to_block (else_label);
811e4b17023SJohn Marino then_stmt = first_stmt (then_bb);
812e4b17023SJohn Marino else_stmt = first_stmt (else_bb);
813e4b17023SJohn Marino
814e4b17023SJohn Marino e = make_edge (bb, then_bb, EDGE_TRUE_VALUE);
815e4b17023SJohn Marino assign_discriminator (entry_locus, then_bb);
816e4b17023SJohn Marino e->goto_locus = gimple_location (then_stmt);
817e4b17023SJohn Marino if (e->goto_locus)
818e4b17023SJohn Marino e->goto_block = gimple_block (then_stmt);
819e4b17023SJohn Marino e = make_edge (bb, else_bb, EDGE_FALSE_VALUE);
820e4b17023SJohn Marino if (e)
821e4b17023SJohn Marino {
822e4b17023SJohn Marino assign_discriminator (entry_locus, else_bb);
823e4b17023SJohn Marino e->goto_locus = gimple_location (else_stmt);
824e4b17023SJohn Marino if (e->goto_locus)
825e4b17023SJohn Marino e->goto_block = gimple_block (else_stmt);
826e4b17023SJohn Marino }
827e4b17023SJohn Marino
828e4b17023SJohn Marino /* We do not need the labels anymore. */
829e4b17023SJohn Marino gimple_cond_set_true_label (entry, NULL_TREE);
830e4b17023SJohn Marino gimple_cond_set_false_label (entry, NULL_TREE);
831e4b17023SJohn Marino }
832e4b17023SJohn Marino
833e4b17023SJohn Marino
834e4b17023SJohn Marino /* Called for each element in the hash table (P) as we delete the
835e4b17023SJohn Marino edge to cases hash table.
836e4b17023SJohn Marino
837e4b17023SJohn Marino Clear all the TREE_CHAINs to prevent problems with copying of
838e4b17023SJohn Marino SWITCH_EXPRs and structure sharing rules, then free the hash table
839e4b17023SJohn Marino element. */
840e4b17023SJohn Marino
841e4b17023SJohn Marino static bool
edge_to_cases_cleanup(const void * key ATTRIBUTE_UNUSED,void ** value,void * data ATTRIBUTE_UNUSED)842e4b17023SJohn Marino edge_to_cases_cleanup (const void *key ATTRIBUTE_UNUSED, void **value,
843e4b17023SJohn Marino void *data ATTRIBUTE_UNUSED)
844e4b17023SJohn Marino {
845e4b17023SJohn Marino tree t, next;
846e4b17023SJohn Marino
847e4b17023SJohn Marino for (t = (tree) *value; t; t = next)
848e4b17023SJohn Marino {
849e4b17023SJohn Marino next = CASE_CHAIN (t);
850e4b17023SJohn Marino CASE_CHAIN (t) = NULL;
851e4b17023SJohn Marino }
852e4b17023SJohn Marino
853e4b17023SJohn Marino *value = NULL;
854e4b17023SJohn Marino return true;
855e4b17023SJohn Marino }
856e4b17023SJohn Marino
857e4b17023SJohn Marino /* Start recording information mapping edges to case labels. */
858e4b17023SJohn Marino
859e4b17023SJohn Marino void
start_recording_case_labels(void)860e4b17023SJohn Marino start_recording_case_labels (void)
861e4b17023SJohn Marino {
862e4b17023SJohn Marino gcc_assert (edge_to_cases == NULL);
863e4b17023SJohn Marino edge_to_cases = pointer_map_create ();
864e4b17023SJohn Marino touched_switch_bbs = BITMAP_ALLOC (NULL);
865e4b17023SJohn Marino }
866e4b17023SJohn Marino
867e4b17023SJohn Marino /* Return nonzero if we are recording information for case labels. */
868e4b17023SJohn Marino
869e4b17023SJohn Marino static bool
recording_case_labels_p(void)870e4b17023SJohn Marino recording_case_labels_p (void)
871e4b17023SJohn Marino {
872e4b17023SJohn Marino return (edge_to_cases != NULL);
873e4b17023SJohn Marino }
874e4b17023SJohn Marino
875e4b17023SJohn Marino /* Stop recording information mapping edges to case labels and
876e4b17023SJohn Marino remove any information we have recorded. */
877e4b17023SJohn Marino void
end_recording_case_labels(void)878e4b17023SJohn Marino end_recording_case_labels (void)
879e4b17023SJohn Marino {
880e4b17023SJohn Marino bitmap_iterator bi;
881e4b17023SJohn Marino unsigned i;
882e4b17023SJohn Marino pointer_map_traverse (edge_to_cases, edge_to_cases_cleanup, NULL);
883e4b17023SJohn Marino pointer_map_destroy (edge_to_cases);
884e4b17023SJohn Marino edge_to_cases = NULL;
885e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (touched_switch_bbs, 0, i, bi)
886e4b17023SJohn Marino {
887e4b17023SJohn Marino basic_block bb = BASIC_BLOCK (i);
888e4b17023SJohn Marino if (bb)
889e4b17023SJohn Marino {
890e4b17023SJohn Marino gimple stmt = last_stmt (bb);
891e4b17023SJohn Marino if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
892e4b17023SJohn Marino group_case_labels_stmt (stmt);
893e4b17023SJohn Marino }
894e4b17023SJohn Marino }
895e4b17023SJohn Marino BITMAP_FREE (touched_switch_bbs);
896e4b17023SJohn Marino }
897e4b17023SJohn Marino
898e4b17023SJohn Marino /* If we are inside a {start,end}_recording_cases block, then return
899e4b17023SJohn Marino a chain of CASE_LABEL_EXPRs from T which reference E.
900e4b17023SJohn Marino
901e4b17023SJohn Marino Otherwise return NULL. */
902e4b17023SJohn Marino
903e4b17023SJohn Marino static tree
get_cases_for_edge(edge e,gimple t)904e4b17023SJohn Marino get_cases_for_edge (edge e, gimple t)
905e4b17023SJohn Marino {
906e4b17023SJohn Marino void **slot;
907e4b17023SJohn Marino size_t i, n;
908e4b17023SJohn Marino
909e4b17023SJohn Marino /* If we are not recording cases, then we do not have CASE_LABEL_EXPR
910e4b17023SJohn Marino chains available. Return NULL so the caller can detect this case. */
911e4b17023SJohn Marino if (!recording_case_labels_p ())
912e4b17023SJohn Marino return NULL;
913e4b17023SJohn Marino
914e4b17023SJohn Marino slot = pointer_map_contains (edge_to_cases, e);
915e4b17023SJohn Marino if (slot)
916e4b17023SJohn Marino return (tree) *slot;
917e4b17023SJohn Marino
918e4b17023SJohn Marino /* If we did not find E in the hash table, then this must be the first
919e4b17023SJohn Marino time we have been queried for information about E & T. Add all the
920e4b17023SJohn Marino elements from T to the hash table then perform the query again. */
921e4b17023SJohn Marino
922e4b17023SJohn Marino n = gimple_switch_num_labels (t);
923e4b17023SJohn Marino for (i = 0; i < n; i++)
924e4b17023SJohn Marino {
925e4b17023SJohn Marino tree elt = gimple_switch_label (t, i);
926e4b17023SJohn Marino tree lab = CASE_LABEL (elt);
927e4b17023SJohn Marino basic_block label_bb = label_to_block (lab);
928e4b17023SJohn Marino edge this_edge = find_edge (e->src, label_bb);
929e4b17023SJohn Marino
930e4b17023SJohn Marino /* Add it to the chain of CASE_LABEL_EXPRs referencing E, or create
931e4b17023SJohn Marino a new chain. */
932e4b17023SJohn Marino slot = pointer_map_insert (edge_to_cases, this_edge);
933e4b17023SJohn Marino CASE_CHAIN (elt) = (tree) *slot;
934e4b17023SJohn Marino *slot = elt;
935e4b17023SJohn Marino }
936e4b17023SJohn Marino
937e4b17023SJohn Marino return (tree) *pointer_map_contains (edge_to_cases, e);
938e4b17023SJohn Marino }
939e4b17023SJohn Marino
940e4b17023SJohn Marino /* Create the edges for a GIMPLE_SWITCH starting at block BB. */
941e4b17023SJohn Marino
942e4b17023SJohn Marino static void
make_gimple_switch_edges(basic_block bb)943e4b17023SJohn Marino make_gimple_switch_edges (basic_block bb)
944e4b17023SJohn Marino {
945e4b17023SJohn Marino gimple entry = last_stmt (bb);
946e4b17023SJohn Marino location_t entry_locus;
947e4b17023SJohn Marino size_t i, n;
948e4b17023SJohn Marino
949e4b17023SJohn Marino entry_locus = gimple_location (entry);
950e4b17023SJohn Marino
951e4b17023SJohn Marino n = gimple_switch_num_labels (entry);
952e4b17023SJohn Marino
953e4b17023SJohn Marino for (i = 0; i < n; ++i)
954e4b17023SJohn Marino {
955e4b17023SJohn Marino tree lab = CASE_LABEL (gimple_switch_label (entry, i));
956e4b17023SJohn Marino basic_block label_bb = label_to_block (lab);
957e4b17023SJohn Marino make_edge (bb, label_bb, 0);
958e4b17023SJohn Marino assign_discriminator (entry_locus, label_bb);
959e4b17023SJohn Marino }
960e4b17023SJohn Marino }
961e4b17023SJohn Marino
962e4b17023SJohn Marino
963e4b17023SJohn Marino /* Return the basic block holding label DEST. */
964e4b17023SJohn Marino
965e4b17023SJohn Marino basic_block
label_to_block_fn(struct function * ifun,tree dest)966e4b17023SJohn Marino label_to_block_fn (struct function *ifun, tree dest)
967e4b17023SJohn Marino {
968e4b17023SJohn Marino int uid = LABEL_DECL_UID (dest);
969e4b17023SJohn Marino
970e4b17023SJohn Marino /* We would die hard when faced by an undefined label. Emit a label to
971e4b17023SJohn Marino the very first basic block. This will hopefully make even the dataflow
972e4b17023SJohn Marino and undefined variable warnings quite right. */
973e4b17023SJohn Marino if (seen_error () && uid < 0)
974e4b17023SJohn Marino {
975e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_start_bb (BASIC_BLOCK (NUM_FIXED_BLOCKS));
976e4b17023SJohn Marino gimple stmt;
977e4b17023SJohn Marino
978e4b17023SJohn Marino stmt = gimple_build_label (dest);
979e4b17023SJohn Marino gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
980e4b17023SJohn Marino uid = LABEL_DECL_UID (dest);
981e4b17023SJohn Marino }
982e4b17023SJohn Marino if (VEC_length (basic_block, ifun->cfg->x_label_to_block_map)
983e4b17023SJohn Marino <= (unsigned int) uid)
984e4b17023SJohn Marino return NULL;
985e4b17023SJohn Marino return VEC_index (basic_block, ifun->cfg->x_label_to_block_map, uid);
986e4b17023SJohn Marino }
987e4b17023SJohn Marino
988e4b17023SJohn Marino /* Create edges for an abnormal goto statement at block BB. If FOR_CALL
989e4b17023SJohn Marino is true, the source statement is a CALL_EXPR instead of a GOTO_EXPR. */
990e4b17023SJohn Marino
991e4b17023SJohn Marino void
make_abnormal_goto_edges(basic_block bb,bool for_call)992e4b17023SJohn Marino make_abnormal_goto_edges (basic_block bb, bool for_call)
993e4b17023SJohn Marino {
994e4b17023SJohn Marino basic_block target_bb;
995e4b17023SJohn Marino gimple_stmt_iterator gsi;
996e4b17023SJohn Marino
997e4b17023SJohn Marino FOR_EACH_BB (target_bb)
998e4b17023SJohn Marino for (gsi = gsi_start_bb (target_bb); !gsi_end_p (gsi); gsi_next (&gsi))
999e4b17023SJohn Marino {
1000e4b17023SJohn Marino gimple label_stmt = gsi_stmt (gsi);
1001e4b17023SJohn Marino tree target;
1002e4b17023SJohn Marino
1003e4b17023SJohn Marino if (gimple_code (label_stmt) != GIMPLE_LABEL)
1004e4b17023SJohn Marino break;
1005e4b17023SJohn Marino
1006e4b17023SJohn Marino target = gimple_label_label (label_stmt);
1007e4b17023SJohn Marino
1008e4b17023SJohn Marino /* Make an edge to every label block that has been marked as a
1009e4b17023SJohn Marino potential target for a computed goto or a non-local goto. */
1010e4b17023SJohn Marino if ((FORCED_LABEL (target) && !for_call)
1011e4b17023SJohn Marino || (DECL_NONLOCAL (target) && for_call))
1012e4b17023SJohn Marino {
1013e4b17023SJohn Marino make_edge (bb, target_bb, EDGE_ABNORMAL);
1014e4b17023SJohn Marino break;
1015e4b17023SJohn Marino }
1016e4b17023SJohn Marino }
1017e4b17023SJohn Marino }
1018e4b17023SJohn Marino
1019e4b17023SJohn Marino /* Create edges for a goto statement at block BB. */
1020e4b17023SJohn Marino
1021e4b17023SJohn Marino static void
make_goto_expr_edges(basic_block bb)1022e4b17023SJohn Marino make_goto_expr_edges (basic_block bb)
1023e4b17023SJohn Marino {
1024e4b17023SJohn Marino gimple_stmt_iterator last = gsi_last_bb (bb);
1025e4b17023SJohn Marino gimple goto_t = gsi_stmt (last);
1026e4b17023SJohn Marino
1027e4b17023SJohn Marino /* A simple GOTO creates normal edges. */
1028e4b17023SJohn Marino if (simple_goto_p (goto_t))
1029e4b17023SJohn Marino {
1030e4b17023SJohn Marino tree dest = gimple_goto_dest (goto_t);
1031e4b17023SJohn Marino basic_block label_bb = label_to_block (dest);
1032e4b17023SJohn Marino edge e = make_edge (bb, label_bb, EDGE_FALLTHRU);
1033e4b17023SJohn Marino e->goto_locus = gimple_location (goto_t);
1034e4b17023SJohn Marino assign_discriminator (e->goto_locus, label_bb);
1035e4b17023SJohn Marino if (e->goto_locus)
1036e4b17023SJohn Marino e->goto_block = gimple_block (goto_t);
1037e4b17023SJohn Marino gsi_remove (&last, true);
1038e4b17023SJohn Marino return;
1039e4b17023SJohn Marino }
1040e4b17023SJohn Marino
1041e4b17023SJohn Marino /* A computed GOTO creates abnormal edges. */
1042e4b17023SJohn Marino make_abnormal_goto_edges (bb, false);
1043e4b17023SJohn Marino }
1044e4b17023SJohn Marino
1045e4b17023SJohn Marino /* Create edges for an asm statement with labels at block BB. */
1046e4b17023SJohn Marino
1047e4b17023SJohn Marino static void
make_gimple_asm_edges(basic_block bb)1048e4b17023SJohn Marino make_gimple_asm_edges (basic_block bb)
1049e4b17023SJohn Marino {
1050e4b17023SJohn Marino gimple stmt = last_stmt (bb);
1051e4b17023SJohn Marino location_t stmt_loc = gimple_location (stmt);
1052e4b17023SJohn Marino int i, n = gimple_asm_nlabels (stmt);
1053e4b17023SJohn Marino
1054e4b17023SJohn Marino for (i = 0; i < n; ++i)
1055e4b17023SJohn Marino {
1056e4b17023SJohn Marino tree label = TREE_VALUE (gimple_asm_label_op (stmt, i));
1057e4b17023SJohn Marino basic_block label_bb = label_to_block (label);
1058e4b17023SJohn Marino make_edge (bb, label_bb, 0);
1059e4b17023SJohn Marino assign_discriminator (stmt_loc, label_bb);
1060e4b17023SJohn Marino }
1061e4b17023SJohn Marino }
1062e4b17023SJohn Marino
1063e4b17023SJohn Marino /*---------------------------------------------------------------------------
1064e4b17023SJohn Marino Flowgraph analysis
1065e4b17023SJohn Marino ---------------------------------------------------------------------------*/
1066e4b17023SJohn Marino
1067e4b17023SJohn Marino /* Cleanup useless labels in basic blocks. This is something we wish
1068e4b17023SJohn Marino to do early because it allows us to group case labels before creating
1069e4b17023SJohn Marino the edges for the CFG, and it speeds up block statement iterators in
1070e4b17023SJohn Marino all passes later on.
1071e4b17023SJohn Marino We rerun this pass after CFG is created, to get rid of the labels that
1072e4b17023SJohn Marino are no longer referenced. After then we do not run it any more, since
1073e4b17023SJohn Marino (almost) no new labels should be created. */
1074e4b17023SJohn Marino
1075e4b17023SJohn Marino /* A map from basic block index to the leading label of that block. */
1076e4b17023SJohn Marino static struct label_record
1077e4b17023SJohn Marino {
1078e4b17023SJohn Marino /* The label. */
1079e4b17023SJohn Marino tree label;
1080e4b17023SJohn Marino
1081e4b17023SJohn Marino /* True if the label is referenced from somewhere. */
1082e4b17023SJohn Marino bool used;
1083e4b17023SJohn Marino } *label_for_bb;
1084e4b17023SJohn Marino
1085e4b17023SJohn Marino /* Given LABEL return the first label in the same basic block. */
1086e4b17023SJohn Marino
1087e4b17023SJohn Marino static tree
main_block_label(tree label)1088e4b17023SJohn Marino main_block_label (tree label)
1089e4b17023SJohn Marino {
1090e4b17023SJohn Marino basic_block bb = label_to_block (label);
1091e4b17023SJohn Marino tree main_label = label_for_bb[bb->index].label;
1092e4b17023SJohn Marino
1093e4b17023SJohn Marino /* label_to_block possibly inserted undefined label into the chain. */
1094e4b17023SJohn Marino if (!main_label)
1095e4b17023SJohn Marino {
1096e4b17023SJohn Marino label_for_bb[bb->index].label = label;
1097e4b17023SJohn Marino main_label = label;
1098e4b17023SJohn Marino }
1099e4b17023SJohn Marino
1100e4b17023SJohn Marino label_for_bb[bb->index].used = true;
1101e4b17023SJohn Marino return main_label;
1102e4b17023SJohn Marino }
1103e4b17023SJohn Marino
1104e4b17023SJohn Marino /* Clean up redundant labels within the exception tree. */
1105e4b17023SJohn Marino
1106e4b17023SJohn Marino static void
cleanup_dead_labels_eh(void)1107e4b17023SJohn Marino cleanup_dead_labels_eh (void)
1108e4b17023SJohn Marino {
1109e4b17023SJohn Marino eh_landing_pad lp;
1110e4b17023SJohn Marino eh_region r;
1111e4b17023SJohn Marino tree lab;
1112e4b17023SJohn Marino int i;
1113e4b17023SJohn Marino
1114e4b17023SJohn Marino if (cfun->eh == NULL)
1115e4b17023SJohn Marino return;
1116e4b17023SJohn Marino
1117e4b17023SJohn Marino for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
1118e4b17023SJohn Marino if (lp && lp->post_landing_pad)
1119e4b17023SJohn Marino {
1120e4b17023SJohn Marino lab = main_block_label (lp->post_landing_pad);
1121e4b17023SJohn Marino if (lab != lp->post_landing_pad)
1122e4b17023SJohn Marino {
1123e4b17023SJohn Marino EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
1124e4b17023SJohn Marino EH_LANDING_PAD_NR (lab) = lp->index;
1125e4b17023SJohn Marino }
1126e4b17023SJohn Marino }
1127e4b17023SJohn Marino
1128e4b17023SJohn Marino FOR_ALL_EH_REGION (r)
1129e4b17023SJohn Marino switch (r->type)
1130e4b17023SJohn Marino {
1131e4b17023SJohn Marino case ERT_CLEANUP:
1132e4b17023SJohn Marino case ERT_MUST_NOT_THROW:
1133e4b17023SJohn Marino break;
1134e4b17023SJohn Marino
1135e4b17023SJohn Marino case ERT_TRY:
1136e4b17023SJohn Marino {
1137e4b17023SJohn Marino eh_catch c;
1138e4b17023SJohn Marino for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
1139e4b17023SJohn Marino {
1140e4b17023SJohn Marino lab = c->label;
1141e4b17023SJohn Marino if (lab)
1142e4b17023SJohn Marino c->label = main_block_label (lab);
1143e4b17023SJohn Marino }
1144e4b17023SJohn Marino }
1145e4b17023SJohn Marino break;
1146e4b17023SJohn Marino
1147e4b17023SJohn Marino case ERT_ALLOWED_EXCEPTIONS:
1148e4b17023SJohn Marino lab = r->u.allowed.label;
1149e4b17023SJohn Marino if (lab)
1150e4b17023SJohn Marino r->u.allowed.label = main_block_label (lab);
1151e4b17023SJohn Marino break;
1152e4b17023SJohn Marino }
1153e4b17023SJohn Marino }
1154e4b17023SJohn Marino
1155e4b17023SJohn Marino
1156e4b17023SJohn Marino /* Cleanup redundant labels. This is a three-step process:
1157e4b17023SJohn Marino 1) Find the leading label for each block.
1158e4b17023SJohn Marino 2) Redirect all references to labels to the leading labels.
1159e4b17023SJohn Marino 3) Cleanup all useless labels. */
1160e4b17023SJohn Marino
1161e4b17023SJohn Marino void
cleanup_dead_labels(void)1162e4b17023SJohn Marino cleanup_dead_labels (void)
1163e4b17023SJohn Marino {
1164e4b17023SJohn Marino basic_block bb;
1165e4b17023SJohn Marino label_for_bb = XCNEWVEC (struct label_record, last_basic_block);
1166e4b17023SJohn Marino
1167e4b17023SJohn Marino /* Find a suitable label for each block. We use the first user-defined
1168e4b17023SJohn Marino label if there is one, or otherwise just the first label we see. */
1169e4b17023SJohn Marino FOR_EACH_BB (bb)
1170e4b17023SJohn Marino {
1171e4b17023SJohn Marino gimple_stmt_iterator i;
1172e4b17023SJohn Marino
1173e4b17023SJohn Marino for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
1174e4b17023SJohn Marino {
1175e4b17023SJohn Marino tree label;
1176e4b17023SJohn Marino gimple stmt = gsi_stmt (i);
1177e4b17023SJohn Marino
1178e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_LABEL)
1179e4b17023SJohn Marino break;
1180e4b17023SJohn Marino
1181e4b17023SJohn Marino label = gimple_label_label (stmt);
1182e4b17023SJohn Marino
1183e4b17023SJohn Marino /* If we have not yet seen a label for the current block,
1184e4b17023SJohn Marino remember this one and see if there are more labels. */
1185e4b17023SJohn Marino if (!label_for_bb[bb->index].label)
1186e4b17023SJohn Marino {
1187e4b17023SJohn Marino label_for_bb[bb->index].label = label;
1188e4b17023SJohn Marino continue;
1189e4b17023SJohn Marino }
1190e4b17023SJohn Marino
1191e4b17023SJohn Marino /* If we did see a label for the current block already, but it
1192e4b17023SJohn Marino is an artificially created label, replace it if the current
1193e4b17023SJohn Marino label is a user defined label. */
1194e4b17023SJohn Marino if (!DECL_ARTIFICIAL (label)
1195e4b17023SJohn Marino && DECL_ARTIFICIAL (label_for_bb[bb->index].label))
1196e4b17023SJohn Marino {
1197e4b17023SJohn Marino label_for_bb[bb->index].label = label;
1198e4b17023SJohn Marino break;
1199e4b17023SJohn Marino }
1200e4b17023SJohn Marino }
1201e4b17023SJohn Marino }
1202e4b17023SJohn Marino
1203e4b17023SJohn Marino /* Now redirect all jumps/branches to the selected label.
1204e4b17023SJohn Marino First do so for each block ending in a control statement. */
1205e4b17023SJohn Marino FOR_EACH_BB (bb)
1206e4b17023SJohn Marino {
1207e4b17023SJohn Marino gimple stmt = last_stmt (bb);
1208e4b17023SJohn Marino tree label, new_label;
1209e4b17023SJohn Marino
1210e4b17023SJohn Marino if (!stmt)
1211e4b17023SJohn Marino continue;
1212e4b17023SJohn Marino
1213e4b17023SJohn Marino switch (gimple_code (stmt))
1214e4b17023SJohn Marino {
1215e4b17023SJohn Marino case GIMPLE_COND:
1216e4b17023SJohn Marino label = gimple_cond_true_label (stmt);
1217e4b17023SJohn Marino if (label)
1218e4b17023SJohn Marino {
1219e4b17023SJohn Marino new_label = main_block_label (label);
1220e4b17023SJohn Marino if (new_label != label)
1221e4b17023SJohn Marino gimple_cond_set_true_label (stmt, new_label);
1222e4b17023SJohn Marino }
1223e4b17023SJohn Marino
1224e4b17023SJohn Marino label = gimple_cond_false_label (stmt);
1225e4b17023SJohn Marino if (label)
1226e4b17023SJohn Marino {
1227e4b17023SJohn Marino new_label = main_block_label (label);
1228e4b17023SJohn Marino if (new_label != label)
1229e4b17023SJohn Marino gimple_cond_set_false_label (stmt, new_label);
1230e4b17023SJohn Marino }
1231e4b17023SJohn Marino break;
1232e4b17023SJohn Marino
1233e4b17023SJohn Marino case GIMPLE_SWITCH:
1234e4b17023SJohn Marino {
1235e4b17023SJohn Marino size_t i, n = gimple_switch_num_labels (stmt);
1236e4b17023SJohn Marino
1237e4b17023SJohn Marino /* Replace all destination labels. */
1238e4b17023SJohn Marino for (i = 0; i < n; ++i)
1239e4b17023SJohn Marino {
1240e4b17023SJohn Marino tree case_label = gimple_switch_label (stmt, i);
1241e4b17023SJohn Marino label = CASE_LABEL (case_label);
1242e4b17023SJohn Marino new_label = main_block_label (label);
1243e4b17023SJohn Marino if (new_label != label)
1244e4b17023SJohn Marino CASE_LABEL (case_label) = new_label;
1245e4b17023SJohn Marino }
1246e4b17023SJohn Marino break;
1247e4b17023SJohn Marino }
1248e4b17023SJohn Marino
1249e4b17023SJohn Marino case GIMPLE_ASM:
1250e4b17023SJohn Marino {
1251e4b17023SJohn Marino int i, n = gimple_asm_nlabels (stmt);
1252e4b17023SJohn Marino
1253e4b17023SJohn Marino for (i = 0; i < n; ++i)
1254e4b17023SJohn Marino {
1255e4b17023SJohn Marino tree cons = gimple_asm_label_op (stmt, i);
1256e4b17023SJohn Marino tree label = main_block_label (TREE_VALUE (cons));
1257e4b17023SJohn Marino TREE_VALUE (cons) = label;
1258e4b17023SJohn Marino }
1259e4b17023SJohn Marino break;
1260e4b17023SJohn Marino }
1261e4b17023SJohn Marino
1262e4b17023SJohn Marino /* We have to handle gotos until they're removed, and we don't
1263e4b17023SJohn Marino remove them until after we've created the CFG edges. */
1264e4b17023SJohn Marino case GIMPLE_GOTO:
1265e4b17023SJohn Marino if (!computed_goto_p (stmt))
1266e4b17023SJohn Marino {
1267e4b17023SJohn Marino label = gimple_goto_dest (stmt);
1268e4b17023SJohn Marino new_label = main_block_label (label);
1269e4b17023SJohn Marino if (new_label != label)
1270e4b17023SJohn Marino gimple_goto_set_dest (stmt, new_label);
1271e4b17023SJohn Marino }
1272e4b17023SJohn Marino break;
1273e4b17023SJohn Marino
1274e4b17023SJohn Marino case GIMPLE_TRANSACTION:
1275e4b17023SJohn Marino {
1276e4b17023SJohn Marino tree label = gimple_transaction_label (stmt);
1277e4b17023SJohn Marino if (label)
1278e4b17023SJohn Marino {
1279e4b17023SJohn Marino tree new_label = main_block_label (label);
1280e4b17023SJohn Marino if (new_label != label)
1281e4b17023SJohn Marino gimple_transaction_set_label (stmt, new_label);
1282e4b17023SJohn Marino }
1283e4b17023SJohn Marino }
1284e4b17023SJohn Marino break;
1285e4b17023SJohn Marino
1286e4b17023SJohn Marino default:
1287e4b17023SJohn Marino break;
1288e4b17023SJohn Marino }
1289e4b17023SJohn Marino }
1290e4b17023SJohn Marino
1291e4b17023SJohn Marino /* Do the same for the exception region tree labels. */
1292e4b17023SJohn Marino cleanup_dead_labels_eh ();
1293e4b17023SJohn Marino
1294e4b17023SJohn Marino /* Finally, purge dead labels. All user-defined labels and labels that
1295e4b17023SJohn Marino can be the target of non-local gotos and labels which have their
1296e4b17023SJohn Marino address taken are preserved. */
1297e4b17023SJohn Marino FOR_EACH_BB (bb)
1298e4b17023SJohn Marino {
1299e4b17023SJohn Marino gimple_stmt_iterator i;
1300e4b17023SJohn Marino tree label_for_this_bb = label_for_bb[bb->index].label;
1301e4b17023SJohn Marino
1302e4b17023SJohn Marino if (!label_for_this_bb)
1303e4b17023SJohn Marino continue;
1304e4b17023SJohn Marino
1305e4b17023SJohn Marino /* If the main label of the block is unused, we may still remove it. */
1306e4b17023SJohn Marino if (!label_for_bb[bb->index].used)
1307e4b17023SJohn Marino label_for_this_bb = NULL;
1308e4b17023SJohn Marino
1309e4b17023SJohn Marino for (i = gsi_start_bb (bb); !gsi_end_p (i); )
1310e4b17023SJohn Marino {
1311e4b17023SJohn Marino tree label;
1312e4b17023SJohn Marino gimple stmt = gsi_stmt (i);
1313e4b17023SJohn Marino
1314e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_LABEL)
1315e4b17023SJohn Marino break;
1316e4b17023SJohn Marino
1317e4b17023SJohn Marino label = gimple_label_label (stmt);
1318e4b17023SJohn Marino
1319e4b17023SJohn Marino if (label == label_for_this_bb
1320e4b17023SJohn Marino || !DECL_ARTIFICIAL (label)
1321e4b17023SJohn Marino || DECL_NONLOCAL (label)
1322e4b17023SJohn Marino || FORCED_LABEL (label))
1323e4b17023SJohn Marino gsi_next (&i);
1324e4b17023SJohn Marino else
1325e4b17023SJohn Marino gsi_remove (&i, true);
1326e4b17023SJohn Marino }
1327e4b17023SJohn Marino }
1328e4b17023SJohn Marino
1329e4b17023SJohn Marino free (label_for_bb);
1330e4b17023SJohn Marino }
1331e4b17023SJohn Marino
1332e4b17023SJohn Marino /* Scan the sorted vector of cases in STMT (a GIMPLE_SWITCH) and combine
1333e4b17023SJohn Marino the ones jumping to the same label.
1334e4b17023SJohn Marino Eg. three separate entries 1: 2: 3: become one entry 1..3: */
1335e4b17023SJohn Marino
1336e4b17023SJohn Marino static void
group_case_labels_stmt(gimple stmt)1337e4b17023SJohn Marino group_case_labels_stmt (gimple stmt)
1338e4b17023SJohn Marino {
1339e4b17023SJohn Marino int old_size = gimple_switch_num_labels (stmt);
1340e4b17023SJohn Marino int i, j, new_size = old_size;
1341e4b17023SJohn Marino tree default_case = NULL_TREE;
1342e4b17023SJohn Marino tree default_label = NULL_TREE;
1343e4b17023SJohn Marino bool has_default;
1344e4b17023SJohn Marino
1345e4b17023SJohn Marino /* The default label is always the first case in a switch
1346e4b17023SJohn Marino statement after gimplification if it was not optimized
1347e4b17023SJohn Marino away */
1348e4b17023SJohn Marino if (!CASE_LOW (gimple_switch_default_label (stmt))
1349e4b17023SJohn Marino && !CASE_HIGH (gimple_switch_default_label (stmt)))
1350e4b17023SJohn Marino {
1351e4b17023SJohn Marino default_case = gimple_switch_default_label (stmt);
1352e4b17023SJohn Marino default_label = CASE_LABEL (default_case);
1353e4b17023SJohn Marino has_default = true;
1354e4b17023SJohn Marino }
1355e4b17023SJohn Marino else
1356e4b17023SJohn Marino has_default = false;
1357e4b17023SJohn Marino
1358e4b17023SJohn Marino /* Look for possible opportunities to merge cases. */
1359e4b17023SJohn Marino if (has_default)
1360e4b17023SJohn Marino i = 1;
1361e4b17023SJohn Marino else
1362e4b17023SJohn Marino i = 0;
1363e4b17023SJohn Marino while (i < old_size)
1364e4b17023SJohn Marino {
1365e4b17023SJohn Marino tree base_case, base_label, base_high;
1366e4b17023SJohn Marino base_case = gimple_switch_label (stmt, i);
1367e4b17023SJohn Marino
1368e4b17023SJohn Marino gcc_assert (base_case);
1369e4b17023SJohn Marino base_label = CASE_LABEL (base_case);
1370e4b17023SJohn Marino
1371e4b17023SJohn Marino /* Discard cases that have the same destination as the
1372e4b17023SJohn Marino default case. */
1373e4b17023SJohn Marino if (base_label == default_label)
1374e4b17023SJohn Marino {
1375e4b17023SJohn Marino gimple_switch_set_label (stmt, i, NULL_TREE);
1376e4b17023SJohn Marino i++;
1377e4b17023SJohn Marino new_size--;
1378e4b17023SJohn Marino continue;
1379e4b17023SJohn Marino }
1380e4b17023SJohn Marino
1381e4b17023SJohn Marino base_high = CASE_HIGH (base_case)
1382e4b17023SJohn Marino ? CASE_HIGH (base_case)
1383e4b17023SJohn Marino : CASE_LOW (base_case);
1384e4b17023SJohn Marino i++;
1385e4b17023SJohn Marino
1386e4b17023SJohn Marino /* Try to merge case labels. Break out when we reach the end
1387e4b17023SJohn Marino of the label vector or when we cannot merge the next case
1388e4b17023SJohn Marino label with the current one. */
1389e4b17023SJohn Marino while (i < old_size)
1390e4b17023SJohn Marino {
1391e4b17023SJohn Marino tree merge_case = gimple_switch_label (stmt, i);
1392e4b17023SJohn Marino tree merge_label = CASE_LABEL (merge_case);
1393e4b17023SJohn Marino double_int bhp1 = double_int_add (tree_to_double_int (base_high),
1394e4b17023SJohn Marino double_int_one);
1395e4b17023SJohn Marino
1396e4b17023SJohn Marino /* Merge the cases if they jump to the same place,
1397e4b17023SJohn Marino and their ranges are consecutive. */
1398e4b17023SJohn Marino if (merge_label == base_label
1399e4b17023SJohn Marino && double_int_equal_p (tree_to_double_int (CASE_LOW (merge_case)),
1400e4b17023SJohn Marino bhp1))
1401e4b17023SJohn Marino {
1402e4b17023SJohn Marino base_high = CASE_HIGH (merge_case) ?
1403e4b17023SJohn Marino CASE_HIGH (merge_case) : CASE_LOW (merge_case);
1404e4b17023SJohn Marino CASE_HIGH (base_case) = base_high;
1405e4b17023SJohn Marino gimple_switch_set_label (stmt, i, NULL_TREE);
1406e4b17023SJohn Marino new_size--;
1407e4b17023SJohn Marino i++;
1408e4b17023SJohn Marino }
1409e4b17023SJohn Marino else
1410e4b17023SJohn Marino break;
1411e4b17023SJohn Marino }
1412e4b17023SJohn Marino }
1413e4b17023SJohn Marino
1414e4b17023SJohn Marino /* Compress the case labels in the label vector, and adjust the
1415e4b17023SJohn Marino length of the vector. */
1416e4b17023SJohn Marino for (i = 0, j = 0; i < new_size; i++)
1417e4b17023SJohn Marino {
1418e4b17023SJohn Marino while (! gimple_switch_label (stmt, j))
1419e4b17023SJohn Marino j++;
1420e4b17023SJohn Marino gimple_switch_set_label (stmt, i,
1421e4b17023SJohn Marino gimple_switch_label (stmt, j++));
1422e4b17023SJohn Marino }
1423e4b17023SJohn Marino
1424e4b17023SJohn Marino gcc_assert (new_size <= old_size);
1425e4b17023SJohn Marino gimple_switch_set_num_labels (stmt, new_size);
1426e4b17023SJohn Marino }
1427e4b17023SJohn Marino
1428e4b17023SJohn Marino /* Look for blocks ending in a multiway branch (a GIMPLE_SWITCH),
1429e4b17023SJohn Marino and scan the sorted vector of cases. Combine the ones jumping to the
1430e4b17023SJohn Marino same label. */
1431e4b17023SJohn Marino
1432e4b17023SJohn Marino void
group_case_labels(void)1433e4b17023SJohn Marino group_case_labels (void)
1434e4b17023SJohn Marino {
1435e4b17023SJohn Marino basic_block bb;
1436e4b17023SJohn Marino
1437e4b17023SJohn Marino FOR_EACH_BB (bb)
1438e4b17023SJohn Marino {
1439e4b17023SJohn Marino gimple stmt = last_stmt (bb);
1440e4b17023SJohn Marino if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
1441e4b17023SJohn Marino group_case_labels_stmt (stmt);
1442e4b17023SJohn Marino }
1443e4b17023SJohn Marino }
1444e4b17023SJohn Marino
1445e4b17023SJohn Marino /* Checks whether we can merge block B into block A. */
1446e4b17023SJohn Marino
1447e4b17023SJohn Marino static bool
gimple_can_merge_blocks_p(basic_block a,basic_block b)1448e4b17023SJohn Marino gimple_can_merge_blocks_p (basic_block a, basic_block b)
1449e4b17023SJohn Marino {
1450e4b17023SJohn Marino gimple stmt;
1451e4b17023SJohn Marino gimple_stmt_iterator gsi;
1452e4b17023SJohn Marino gimple_seq phis;
1453e4b17023SJohn Marino
1454e4b17023SJohn Marino if (!single_succ_p (a))
1455e4b17023SJohn Marino return false;
1456e4b17023SJohn Marino
1457e4b17023SJohn Marino if (single_succ_edge (a)->flags & (EDGE_ABNORMAL | EDGE_EH | EDGE_PRESERVE))
1458e4b17023SJohn Marino return false;
1459e4b17023SJohn Marino
1460e4b17023SJohn Marino if (single_succ (a) != b)
1461e4b17023SJohn Marino return false;
1462e4b17023SJohn Marino
1463e4b17023SJohn Marino if (!single_pred_p (b))
1464e4b17023SJohn Marino return false;
1465e4b17023SJohn Marino
1466e4b17023SJohn Marino if (b == EXIT_BLOCK_PTR)
1467e4b17023SJohn Marino return false;
1468e4b17023SJohn Marino
1469e4b17023SJohn Marino /* If A ends by a statement causing exceptions or something similar, we
1470e4b17023SJohn Marino cannot merge the blocks. */
1471e4b17023SJohn Marino stmt = last_stmt (a);
1472e4b17023SJohn Marino if (stmt && stmt_ends_bb_p (stmt))
1473e4b17023SJohn Marino return false;
1474e4b17023SJohn Marino
1475e4b17023SJohn Marino /* Do not allow a block with only a non-local label to be merged. */
1476e4b17023SJohn Marino if (stmt
1477e4b17023SJohn Marino && gimple_code (stmt) == GIMPLE_LABEL
1478e4b17023SJohn Marino && DECL_NONLOCAL (gimple_label_label (stmt)))
1479e4b17023SJohn Marino return false;
1480e4b17023SJohn Marino
1481e4b17023SJohn Marino /* Examine the labels at the beginning of B. */
1482e4b17023SJohn Marino for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
1483e4b17023SJohn Marino {
1484e4b17023SJohn Marino tree lab;
1485e4b17023SJohn Marino stmt = gsi_stmt (gsi);
1486e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_LABEL)
1487e4b17023SJohn Marino break;
1488e4b17023SJohn Marino lab = gimple_label_label (stmt);
1489e4b17023SJohn Marino
1490e4b17023SJohn Marino /* Do not remove user forced labels or for -O0 any user labels. */
1491e4b17023SJohn Marino if (!DECL_ARTIFICIAL (lab) && (!optimize || FORCED_LABEL (lab)))
1492e4b17023SJohn Marino return false;
1493e4b17023SJohn Marino }
1494e4b17023SJohn Marino
1495e4b17023SJohn Marino /* Protect the loop latches. */
1496e4b17023SJohn Marino if (current_loops && b->loop_father->latch == b)
1497e4b17023SJohn Marino return false;
1498e4b17023SJohn Marino
1499e4b17023SJohn Marino /* It must be possible to eliminate all phi nodes in B. If ssa form
1500e4b17023SJohn Marino is not up-to-date and a name-mapping is registered, we cannot eliminate
1501e4b17023SJohn Marino any phis. Symbols marked for renaming are never a problem though. */
1502e4b17023SJohn Marino phis = phi_nodes (b);
1503e4b17023SJohn Marino if (!gimple_seq_empty_p (phis)
1504e4b17023SJohn Marino && name_mappings_registered_p ())
1505e4b17023SJohn Marino return false;
1506e4b17023SJohn Marino
1507e4b17023SJohn Marino /* When not optimizing, don't merge if we'd lose goto_locus. */
1508e4b17023SJohn Marino if (!optimize
1509e4b17023SJohn Marino && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION)
1510e4b17023SJohn Marino {
1511e4b17023SJohn Marino location_t goto_locus = single_succ_edge (a)->goto_locus;
1512e4b17023SJohn Marino gimple_stmt_iterator prev, next;
1513e4b17023SJohn Marino prev = gsi_last_nondebug_bb (a);
1514e4b17023SJohn Marino next = gsi_after_labels (b);
1515e4b17023SJohn Marino if (!gsi_end_p (next) && is_gimple_debug (gsi_stmt (next)))
1516e4b17023SJohn Marino gsi_next_nondebug (&next);
1517e4b17023SJohn Marino if ((gsi_end_p (prev)
1518e4b17023SJohn Marino || gimple_location (gsi_stmt (prev)) != goto_locus)
1519e4b17023SJohn Marino && (gsi_end_p (next)
1520e4b17023SJohn Marino || gimple_location (gsi_stmt (next)) != goto_locus))
1521e4b17023SJohn Marino return false;
1522e4b17023SJohn Marino }
1523e4b17023SJohn Marino
1524e4b17023SJohn Marino return true;
1525e4b17023SJohn Marino }
1526e4b17023SJohn Marino
1527e4b17023SJohn Marino /* Return true if the var whose chain of uses starts at PTR has no
1528e4b17023SJohn Marino nondebug uses. */
1529e4b17023SJohn Marino bool
has_zero_uses_1(const ssa_use_operand_t * head)1530e4b17023SJohn Marino has_zero_uses_1 (const ssa_use_operand_t *head)
1531e4b17023SJohn Marino {
1532e4b17023SJohn Marino const ssa_use_operand_t *ptr;
1533e4b17023SJohn Marino
1534e4b17023SJohn Marino for (ptr = head->next; ptr != head; ptr = ptr->next)
1535e4b17023SJohn Marino if (!is_gimple_debug (USE_STMT (ptr)))
1536e4b17023SJohn Marino return false;
1537e4b17023SJohn Marino
1538e4b17023SJohn Marino return true;
1539e4b17023SJohn Marino }
1540e4b17023SJohn Marino
1541e4b17023SJohn Marino /* Return true if the var whose chain of uses starts at PTR has a
1542e4b17023SJohn Marino single nondebug use. Set USE_P and STMT to that single nondebug
1543e4b17023SJohn Marino use, if so, or to NULL otherwise. */
1544e4b17023SJohn Marino bool
single_imm_use_1(const ssa_use_operand_t * head,use_operand_p * use_p,gimple * stmt)1545e4b17023SJohn Marino single_imm_use_1 (const ssa_use_operand_t *head,
1546e4b17023SJohn Marino use_operand_p *use_p, gimple *stmt)
1547e4b17023SJohn Marino {
1548e4b17023SJohn Marino ssa_use_operand_t *ptr, *single_use = 0;
1549e4b17023SJohn Marino
1550e4b17023SJohn Marino for (ptr = head->next; ptr != head; ptr = ptr->next)
1551e4b17023SJohn Marino if (!is_gimple_debug (USE_STMT (ptr)))
1552e4b17023SJohn Marino {
1553e4b17023SJohn Marino if (single_use)
1554e4b17023SJohn Marino {
1555e4b17023SJohn Marino single_use = NULL;
1556e4b17023SJohn Marino break;
1557e4b17023SJohn Marino }
1558e4b17023SJohn Marino single_use = ptr;
1559e4b17023SJohn Marino }
1560e4b17023SJohn Marino
1561e4b17023SJohn Marino if (use_p)
1562e4b17023SJohn Marino *use_p = single_use;
1563e4b17023SJohn Marino
1564e4b17023SJohn Marino if (stmt)
1565e4b17023SJohn Marino *stmt = single_use ? single_use->loc.stmt : NULL;
1566e4b17023SJohn Marino
1567e4b17023SJohn Marino return !!single_use;
1568e4b17023SJohn Marino }
1569e4b17023SJohn Marino
1570e4b17023SJohn Marino /* Replaces all uses of NAME by VAL. */
1571e4b17023SJohn Marino
1572e4b17023SJohn Marino void
replace_uses_by(tree name,tree val)1573e4b17023SJohn Marino replace_uses_by (tree name, tree val)
1574e4b17023SJohn Marino {
1575e4b17023SJohn Marino imm_use_iterator imm_iter;
1576e4b17023SJohn Marino use_operand_p use;
1577e4b17023SJohn Marino gimple stmt;
1578e4b17023SJohn Marino edge e;
1579e4b17023SJohn Marino
1580e4b17023SJohn Marino FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
1581e4b17023SJohn Marino {
1582e4b17023SJohn Marino FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)
1583e4b17023SJohn Marino {
1584e4b17023SJohn Marino replace_exp (use, val);
1585e4b17023SJohn Marino
1586e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_PHI)
1587e4b17023SJohn Marino {
1588e4b17023SJohn Marino e = gimple_phi_arg_edge (stmt, PHI_ARG_INDEX_FROM_USE (use));
1589e4b17023SJohn Marino if (e->flags & EDGE_ABNORMAL)
1590e4b17023SJohn Marino {
1591e4b17023SJohn Marino /* This can only occur for virtual operands, since
1592e4b17023SJohn Marino for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
1593e4b17023SJohn Marino would prevent replacement. */
1594e4b17023SJohn Marino gcc_checking_assert (!is_gimple_reg (name));
1595e4b17023SJohn Marino SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1;
1596e4b17023SJohn Marino }
1597e4b17023SJohn Marino }
1598e4b17023SJohn Marino }
1599e4b17023SJohn Marino
1600e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_PHI)
1601e4b17023SJohn Marino {
1602e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
1603e4b17023SJohn Marino gimple orig_stmt = stmt;
1604e4b17023SJohn Marino size_t i;
1605e4b17023SJohn Marino
1606e4b17023SJohn Marino /* Mark the block if we changed the last stmt in it. */
1607e4b17023SJohn Marino if (cfgcleanup_altered_bbs
1608e4b17023SJohn Marino && stmt_ends_bb_p (stmt))
1609e4b17023SJohn Marino bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
1610e4b17023SJohn Marino
1611e4b17023SJohn Marino /* FIXME. It shouldn't be required to keep TREE_CONSTANT
1612e4b17023SJohn Marino on ADDR_EXPRs up-to-date on GIMPLE. Propagation will
1613e4b17023SJohn Marino only change sth from non-invariant to invariant, and only
1614e4b17023SJohn Marino when propagating constants. */
1615e4b17023SJohn Marino if (is_gimple_min_invariant (val))
1616e4b17023SJohn Marino for (i = 0; i < gimple_num_ops (stmt); i++)
1617e4b17023SJohn Marino {
1618e4b17023SJohn Marino tree op = gimple_op (stmt, i);
1619e4b17023SJohn Marino /* Operands may be empty here. For example, the labels
1620e4b17023SJohn Marino of a GIMPLE_COND are nulled out following the creation
1621e4b17023SJohn Marino of the corresponding CFG edges. */
1622e4b17023SJohn Marino if (op && TREE_CODE (op) == ADDR_EXPR)
1623e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (op);
1624e4b17023SJohn Marino }
1625e4b17023SJohn Marino
1626e4b17023SJohn Marino if (fold_stmt (&gsi))
1627e4b17023SJohn Marino stmt = gsi_stmt (gsi);
1628e4b17023SJohn Marino
1629e4b17023SJohn Marino if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
1630e4b17023SJohn Marino gimple_purge_dead_eh_edges (gimple_bb (stmt));
1631e4b17023SJohn Marino
1632e4b17023SJohn Marino update_stmt (stmt);
1633e4b17023SJohn Marino }
1634e4b17023SJohn Marino }
1635e4b17023SJohn Marino
1636e4b17023SJohn Marino gcc_checking_assert (has_zero_uses (name));
1637e4b17023SJohn Marino
1638e4b17023SJohn Marino /* Also update the trees stored in loop structures. */
1639e4b17023SJohn Marino if (current_loops)
1640e4b17023SJohn Marino {
1641e4b17023SJohn Marino struct loop *loop;
1642e4b17023SJohn Marino loop_iterator li;
1643e4b17023SJohn Marino
1644e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, 0)
1645e4b17023SJohn Marino {
1646e4b17023SJohn Marino substitute_in_loop_info (loop, name, val);
1647e4b17023SJohn Marino }
1648e4b17023SJohn Marino }
1649e4b17023SJohn Marino }
1650e4b17023SJohn Marino
1651e4b17023SJohn Marino /* Merge block B into block A. */
1652e4b17023SJohn Marino
1653e4b17023SJohn Marino static void
gimple_merge_blocks(basic_block a,basic_block b)1654e4b17023SJohn Marino gimple_merge_blocks (basic_block a, basic_block b)
1655e4b17023SJohn Marino {
1656e4b17023SJohn Marino gimple_stmt_iterator last, gsi, psi;
1657e4b17023SJohn Marino gimple_seq phis = phi_nodes (b);
1658e4b17023SJohn Marino
1659e4b17023SJohn Marino if (dump_file)
1660e4b17023SJohn Marino fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index);
1661e4b17023SJohn Marino
1662e4b17023SJohn Marino /* Remove all single-valued PHI nodes from block B of the form
1663e4b17023SJohn Marino V_i = PHI <V_j> by propagating V_j to all the uses of V_i. */
1664e4b17023SJohn Marino gsi = gsi_last_bb (a);
1665e4b17023SJohn Marino for (psi = gsi_start (phis); !gsi_end_p (psi); )
1666e4b17023SJohn Marino {
1667e4b17023SJohn Marino gimple phi = gsi_stmt (psi);
1668e4b17023SJohn Marino tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0);
1669e4b17023SJohn Marino gimple copy;
1670e4b17023SJohn Marino bool may_replace_uses = !is_gimple_reg (def)
1671e4b17023SJohn Marino || may_propagate_copy (def, use);
1672e4b17023SJohn Marino
1673e4b17023SJohn Marino /* In case we maintain loop closed ssa form, do not propagate arguments
1674e4b17023SJohn Marino of loop exit phi nodes. */
1675e4b17023SJohn Marino if (current_loops
1676e4b17023SJohn Marino && loops_state_satisfies_p (LOOP_CLOSED_SSA)
1677e4b17023SJohn Marino && is_gimple_reg (def)
1678e4b17023SJohn Marino && TREE_CODE (use) == SSA_NAME
1679e4b17023SJohn Marino && a->loop_father != b->loop_father)
1680e4b17023SJohn Marino may_replace_uses = false;
1681e4b17023SJohn Marino
1682e4b17023SJohn Marino if (!may_replace_uses)
1683e4b17023SJohn Marino {
1684e4b17023SJohn Marino gcc_assert (is_gimple_reg (def));
1685e4b17023SJohn Marino
1686e4b17023SJohn Marino /* Note that just emitting the copies is fine -- there is no problem
1687e4b17023SJohn Marino with ordering of phi nodes. This is because A is the single
1688e4b17023SJohn Marino predecessor of B, therefore results of the phi nodes cannot
1689e4b17023SJohn Marino appear as arguments of the phi nodes. */
1690e4b17023SJohn Marino copy = gimple_build_assign (def, use);
1691e4b17023SJohn Marino gsi_insert_after (&gsi, copy, GSI_NEW_STMT);
1692e4b17023SJohn Marino remove_phi_node (&psi, false);
1693e4b17023SJohn Marino }
1694e4b17023SJohn Marino else
1695e4b17023SJohn Marino {
1696e4b17023SJohn Marino /* If we deal with a PHI for virtual operands, we can simply
1697e4b17023SJohn Marino propagate these without fussing with folding or updating
1698e4b17023SJohn Marino the stmt. */
1699e4b17023SJohn Marino if (!is_gimple_reg (def))
1700e4b17023SJohn Marino {
1701e4b17023SJohn Marino imm_use_iterator iter;
1702e4b17023SJohn Marino use_operand_p use_p;
1703e4b17023SJohn Marino gimple stmt;
1704e4b17023SJohn Marino
1705e4b17023SJohn Marino FOR_EACH_IMM_USE_STMT (stmt, iter, def)
1706e4b17023SJohn Marino FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
1707e4b17023SJohn Marino SET_USE (use_p, use);
1708e4b17023SJohn Marino
1709e4b17023SJohn Marino if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def))
1710e4b17023SJohn Marino SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use) = 1;
1711e4b17023SJohn Marino }
1712e4b17023SJohn Marino else
1713e4b17023SJohn Marino replace_uses_by (def, use);
1714e4b17023SJohn Marino
1715e4b17023SJohn Marino remove_phi_node (&psi, true);
1716e4b17023SJohn Marino }
1717e4b17023SJohn Marino }
1718e4b17023SJohn Marino
1719e4b17023SJohn Marino /* Ensure that B follows A. */
1720e4b17023SJohn Marino move_block_after (b, a);
1721e4b17023SJohn Marino
1722e4b17023SJohn Marino gcc_assert (single_succ_edge (a)->flags & EDGE_FALLTHRU);
1723e4b17023SJohn Marino gcc_assert (!last_stmt (a) || !stmt_ends_bb_p (last_stmt (a)));
1724e4b17023SJohn Marino
1725e4b17023SJohn Marino /* Remove labels from B and set gimple_bb to A for other statements. */
1726e4b17023SJohn Marino for (gsi = gsi_start_bb (b); !gsi_end_p (gsi);)
1727e4b17023SJohn Marino {
1728e4b17023SJohn Marino gimple stmt = gsi_stmt (gsi);
1729e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL)
1730e4b17023SJohn Marino {
1731e4b17023SJohn Marino tree label = gimple_label_label (stmt);
1732e4b17023SJohn Marino int lp_nr;
1733e4b17023SJohn Marino
1734e4b17023SJohn Marino gsi_remove (&gsi, false);
1735e4b17023SJohn Marino
1736e4b17023SJohn Marino /* Now that we can thread computed gotos, we might have
1737e4b17023SJohn Marino a situation where we have a forced label in block B
1738e4b17023SJohn Marino However, the label at the start of block B might still be
1739e4b17023SJohn Marino used in other ways (think about the runtime checking for
1740e4b17023SJohn Marino Fortran assigned gotos). So we can not just delete the
1741e4b17023SJohn Marino label. Instead we move the label to the start of block A. */
1742e4b17023SJohn Marino if (FORCED_LABEL (label))
1743e4b17023SJohn Marino {
1744e4b17023SJohn Marino gimple_stmt_iterator dest_gsi = gsi_start_bb (a);
1745e4b17023SJohn Marino gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT);
1746e4b17023SJohn Marino }
1747e4b17023SJohn Marino /* Other user labels keep around in a form of a debug stmt. */
1748e4b17023SJohn Marino else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_STMTS)
1749e4b17023SJohn Marino {
1750e4b17023SJohn Marino gimple dbg = gimple_build_debug_bind (label,
1751e4b17023SJohn Marino integer_zero_node,
1752e4b17023SJohn Marino stmt);
1753e4b17023SJohn Marino gimple_debug_bind_reset_value (dbg);
1754e4b17023SJohn Marino gsi_insert_before (&gsi, dbg, GSI_SAME_STMT);
1755e4b17023SJohn Marino }
1756e4b17023SJohn Marino
1757e4b17023SJohn Marino lp_nr = EH_LANDING_PAD_NR (label);
1758e4b17023SJohn Marino if (lp_nr)
1759e4b17023SJohn Marino {
1760e4b17023SJohn Marino eh_landing_pad lp = get_eh_landing_pad_from_number (lp_nr);
1761e4b17023SJohn Marino lp->post_landing_pad = NULL;
1762e4b17023SJohn Marino }
1763e4b17023SJohn Marino }
1764e4b17023SJohn Marino else
1765e4b17023SJohn Marino {
1766e4b17023SJohn Marino gimple_set_bb (stmt, a);
1767e4b17023SJohn Marino gsi_next (&gsi);
1768e4b17023SJohn Marino }
1769e4b17023SJohn Marino }
1770e4b17023SJohn Marino
1771e4b17023SJohn Marino /* Merge the sequences. */
1772e4b17023SJohn Marino last = gsi_last_bb (a);
1773e4b17023SJohn Marino gsi_insert_seq_after (&last, bb_seq (b), GSI_NEW_STMT);
1774e4b17023SJohn Marino set_bb_seq (b, NULL);
1775e4b17023SJohn Marino
1776e4b17023SJohn Marino if (cfgcleanup_altered_bbs)
1777e4b17023SJohn Marino bitmap_set_bit (cfgcleanup_altered_bbs, a->index);
1778e4b17023SJohn Marino }
1779e4b17023SJohn Marino
1780e4b17023SJohn Marino
1781e4b17023SJohn Marino /* Return the one of two successors of BB that is not reachable by a
1782e4b17023SJohn Marino complex edge, if there is one. Else, return BB. We use
1783e4b17023SJohn Marino this in optimizations that use post-dominators for their heuristics,
1784e4b17023SJohn Marino to catch the cases in C++ where function calls are involved. */
1785e4b17023SJohn Marino
1786e4b17023SJohn Marino basic_block
single_noncomplex_succ(basic_block bb)1787e4b17023SJohn Marino single_noncomplex_succ (basic_block bb)
1788e4b17023SJohn Marino {
1789e4b17023SJohn Marino edge e0, e1;
1790e4b17023SJohn Marino if (EDGE_COUNT (bb->succs) != 2)
1791e4b17023SJohn Marino return bb;
1792e4b17023SJohn Marino
1793e4b17023SJohn Marino e0 = EDGE_SUCC (bb, 0);
1794e4b17023SJohn Marino e1 = EDGE_SUCC (bb, 1);
1795e4b17023SJohn Marino if (e0->flags & EDGE_COMPLEX)
1796e4b17023SJohn Marino return e1->dest;
1797e4b17023SJohn Marino if (e1->flags & EDGE_COMPLEX)
1798e4b17023SJohn Marino return e0->dest;
1799e4b17023SJohn Marino
1800e4b17023SJohn Marino return bb;
1801e4b17023SJohn Marino }
1802e4b17023SJohn Marino
1803e4b17023SJohn Marino /* T is CALL_EXPR. Set current_function_calls_* flags. */
1804e4b17023SJohn Marino
1805e4b17023SJohn Marino void
notice_special_calls(gimple call)1806e4b17023SJohn Marino notice_special_calls (gimple call)
1807e4b17023SJohn Marino {
1808e4b17023SJohn Marino int flags = gimple_call_flags (call);
1809e4b17023SJohn Marino
1810e4b17023SJohn Marino if (flags & ECF_MAY_BE_ALLOCA)
1811e4b17023SJohn Marino cfun->calls_alloca = true;
1812e4b17023SJohn Marino if (flags & ECF_RETURNS_TWICE)
1813e4b17023SJohn Marino cfun->calls_setjmp = true;
1814e4b17023SJohn Marino }
1815e4b17023SJohn Marino
1816e4b17023SJohn Marino
1817e4b17023SJohn Marino /* Clear flags set by notice_special_calls. Used by dead code removal
1818e4b17023SJohn Marino to update the flags. */
1819e4b17023SJohn Marino
1820e4b17023SJohn Marino void
clear_special_calls(void)1821e4b17023SJohn Marino clear_special_calls (void)
1822e4b17023SJohn Marino {
1823e4b17023SJohn Marino cfun->calls_alloca = false;
1824e4b17023SJohn Marino cfun->calls_setjmp = false;
1825e4b17023SJohn Marino }
1826e4b17023SJohn Marino
1827e4b17023SJohn Marino /* Remove PHI nodes associated with basic block BB and all edges out of BB. */
1828e4b17023SJohn Marino
1829e4b17023SJohn Marino static void
remove_phi_nodes_and_edges_for_unreachable_block(basic_block bb)1830e4b17023SJohn Marino remove_phi_nodes_and_edges_for_unreachable_block (basic_block bb)
1831e4b17023SJohn Marino {
1832e4b17023SJohn Marino /* Since this block is no longer reachable, we can just delete all
1833e4b17023SJohn Marino of its PHI nodes. */
1834e4b17023SJohn Marino remove_phi_nodes (bb);
1835e4b17023SJohn Marino
1836e4b17023SJohn Marino /* Remove edges to BB's successors. */
1837e4b17023SJohn Marino while (EDGE_COUNT (bb->succs) > 0)
1838e4b17023SJohn Marino remove_edge (EDGE_SUCC (bb, 0));
1839e4b17023SJohn Marino }
1840e4b17023SJohn Marino
1841e4b17023SJohn Marino
1842e4b17023SJohn Marino /* Remove statements of basic block BB. */
1843e4b17023SJohn Marino
1844e4b17023SJohn Marino static void
remove_bb(basic_block bb)1845e4b17023SJohn Marino remove_bb (basic_block bb)
1846e4b17023SJohn Marino {
1847e4b17023SJohn Marino gimple_stmt_iterator i;
1848e4b17023SJohn Marino
1849e4b17023SJohn Marino if (dump_file)
1850e4b17023SJohn Marino {
1851e4b17023SJohn Marino fprintf (dump_file, "Removing basic block %d\n", bb->index);
1852e4b17023SJohn Marino if (dump_flags & TDF_DETAILS)
1853e4b17023SJohn Marino {
1854e4b17023SJohn Marino dump_bb (bb, dump_file, 0);
1855e4b17023SJohn Marino fprintf (dump_file, "\n");
1856e4b17023SJohn Marino }
1857e4b17023SJohn Marino }
1858e4b17023SJohn Marino
1859e4b17023SJohn Marino if (current_loops)
1860e4b17023SJohn Marino {
1861e4b17023SJohn Marino struct loop *loop = bb->loop_father;
1862e4b17023SJohn Marino
1863e4b17023SJohn Marino /* If a loop gets removed, clean up the information associated
1864e4b17023SJohn Marino with it. */
1865e4b17023SJohn Marino if (loop->latch == bb
1866e4b17023SJohn Marino || loop->header == bb)
1867e4b17023SJohn Marino free_numbers_of_iterations_estimates_loop (loop);
1868e4b17023SJohn Marino }
1869e4b17023SJohn Marino
1870e4b17023SJohn Marino /* Remove all the instructions in the block. */
1871e4b17023SJohn Marino if (bb_seq (bb) != NULL)
1872e4b17023SJohn Marino {
1873e4b17023SJohn Marino /* Walk backwards so as to get a chance to substitute all
1874e4b17023SJohn Marino released DEFs into debug stmts. See
1875e4b17023SJohn Marino eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
1876e4b17023SJohn Marino details. */
1877e4b17023SJohn Marino for (i = gsi_last_bb (bb); !gsi_end_p (i);)
1878e4b17023SJohn Marino {
1879e4b17023SJohn Marino gimple stmt = gsi_stmt (i);
1880e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL
1881e4b17023SJohn Marino && (FORCED_LABEL (gimple_label_label (stmt))
1882e4b17023SJohn Marino || DECL_NONLOCAL (gimple_label_label (stmt))))
1883e4b17023SJohn Marino {
1884e4b17023SJohn Marino basic_block new_bb;
1885e4b17023SJohn Marino gimple_stmt_iterator new_gsi;
1886e4b17023SJohn Marino
1887e4b17023SJohn Marino /* A non-reachable non-local label may still be referenced.
1888e4b17023SJohn Marino But it no longer needs to carry the extra semantics of
1889e4b17023SJohn Marino non-locality. */
1890e4b17023SJohn Marino if (DECL_NONLOCAL (gimple_label_label (stmt)))
1891e4b17023SJohn Marino {
1892e4b17023SJohn Marino DECL_NONLOCAL (gimple_label_label (stmt)) = 0;
1893e4b17023SJohn Marino FORCED_LABEL (gimple_label_label (stmt)) = 1;
1894e4b17023SJohn Marino }
1895e4b17023SJohn Marino
1896e4b17023SJohn Marino new_bb = bb->prev_bb;
1897e4b17023SJohn Marino new_gsi = gsi_start_bb (new_bb);
1898e4b17023SJohn Marino gsi_remove (&i, false);
1899e4b17023SJohn Marino gsi_insert_before (&new_gsi, stmt, GSI_NEW_STMT);
1900e4b17023SJohn Marino }
1901e4b17023SJohn Marino else
1902e4b17023SJohn Marino {
1903e4b17023SJohn Marino /* Release SSA definitions if we are in SSA. Note that we
1904e4b17023SJohn Marino may be called when not in SSA. For example,
1905e4b17023SJohn Marino final_cleanup calls this function via
1906e4b17023SJohn Marino cleanup_tree_cfg. */
1907e4b17023SJohn Marino if (gimple_in_ssa_p (cfun))
1908e4b17023SJohn Marino release_defs (stmt);
1909e4b17023SJohn Marino
1910e4b17023SJohn Marino gsi_remove (&i, true);
1911e4b17023SJohn Marino }
1912e4b17023SJohn Marino
1913e4b17023SJohn Marino if (gsi_end_p (i))
1914e4b17023SJohn Marino i = gsi_last_bb (bb);
1915e4b17023SJohn Marino else
1916e4b17023SJohn Marino gsi_prev (&i);
1917e4b17023SJohn Marino }
1918e4b17023SJohn Marino }
1919e4b17023SJohn Marino
1920e4b17023SJohn Marino remove_phi_nodes_and_edges_for_unreachable_block (bb);
1921e4b17023SJohn Marino bb->il.gimple = NULL;
1922e4b17023SJohn Marino }
1923e4b17023SJohn Marino
1924e4b17023SJohn Marino
1925e4b17023SJohn Marino /* Given a basic block BB ending with COND_EXPR or SWITCH_EXPR, and a
1926e4b17023SJohn Marino predicate VAL, return the edge that will be taken out of the block.
1927e4b17023SJohn Marino If VAL does not match a unique edge, NULL is returned. */
1928e4b17023SJohn Marino
1929e4b17023SJohn Marino edge
find_taken_edge(basic_block bb,tree val)1930e4b17023SJohn Marino find_taken_edge (basic_block bb, tree val)
1931e4b17023SJohn Marino {
1932e4b17023SJohn Marino gimple stmt;
1933e4b17023SJohn Marino
1934e4b17023SJohn Marino stmt = last_stmt (bb);
1935e4b17023SJohn Marino
1936e4b17023SJohn Marino gcc_assert (stmt);
1937e4b17023SJohn Marino gcc_assert (is_ctrl_stmt (stmt));
1938e4b17023SJohn Marino
1939e4b17023SJohn Marino if (val == NULL)
1940e4b17023SJohn Marino return NULL;
1941e4b17023SJohn Marino
1942e4b17023SJohn Marino if (!is_gimple_min_invariant (val))
1943e4b17023SJohn Marino return NULL;
1944e4b17023SJohn Marino
1945e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_COND)
1946e4b17023SJohn Marino return find_taken_edge_cond_expr (bb, val);
1947e4b17023SJohn Marino
1948e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_SWITCH)
1949e4b17023SJohn Marino return find_taken_edge_switch_expr (bb, val);
1950e4b17023SJohn Marino
1951e4b17023SJohn Marino if (computed_goto_p (stmt))
1952e4b17023SJohn Marino {
1953e4b17023SJohn Marino /* Only optimize if the argument is a label, if the argument is
1954e4b17023SJohn Marino not a label then we can not construct a proper CFG.
1955e4b17023SJohn Marino
1956e4b17023SJohn Marino It may be the case that we only need to allow the LABEL_REF to
1957e4b17023SJohn Marino appear inside an ADDR_EXPR, but we also allow the LABEL_REF to
1958e4b17023SJohn Marino appear inside a LABEL_EXPR just to be safe. */
1959e4b17023SJohn Marino if ((TREE_CODE (val) == ADDR_EXPR || TREE_CODE (val) == LABEL_EXPR)
1960e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (val, 0)) == LABEL_DECL)
1961e4b17023SJohn Marino return find_taken_edge_computed_goto (bb, TREE_OPERAND (val, 0));
1962e4b17023SJohn Marino return NULL;
1963e4b17023SJohn Marino }
1964e4b17023SJohn Marino
1965e4b17023SJohn Marino gcc_unreachable ();
1966e4b17023SJohn Marino }
1967e4b17023SJohn Marino
1968e4b17023SJohn Marino /* Given a constant value VAL and the entry block BB to a GOTO_EXPR
1969e4b17023SJohn Marino statement, determine which of the outgoing edges will be taken out of the
1970e4b17023SJohn Marino block. Return NULL if either edge may be taken. */
1971e4b17023SJohn Marino
1972e4b17023SJohn Marino static edge
find_taken_edge_computed_goto(basic_block bb,tree val)1973e4b17023SJohn Marino find_taken_edge_computed_goto (basic_block bb, tree val)
1974e4b17023SJohn Marino {
1975e4b17023SJohn Marino basic_block dest;
1976e4b17023SJohn Marino edge e = NULL;
1977e4b17023SJohn Marino
1978e4b17023SJohn Marino dest = label_to_block (val);
1979e4b17023SJohn Marino if (dest)
1980e4b17023SJohn Marino {
1981e4b17023SJohn Marino e = find_edge (bb, dest);
1982e4b17023SJohn Marino gcc_assert (e != NULL);
1983e4b17023SJohn Marino }
1984e4b17023SJohn Marino
1985e4b17023SJohn Marino return e;
1986e4b17023SJohn Marino }
1987e4b17023SJohn Marino
1988e4b17023SJohn Marino /* Given a constant value VAL and the entry block BB to a COND_EXPR
1989e4b17023SJohn Marino statement, determine which of the two edges will be taken out of the
1990e4b17023SJohn Marino block. Return NULL if either edge may be taken. */
1991e4b17023SJohn Marino
1992e4b17023SJohn Marino static edge
find_taken_edge_cond_expr(basic_block bb,tree val)1993e4b17023SJohn Marino find_taken_edge_cond_expr (basic_block bb, tree val)
1994e4b17023SJohn Marino {
1995e4b17023SJohn Marino edge true_edge, false_edge;
1996e4b17023SJohn Marino
1997e4b17023SJohn Marino extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
1998e4b17023SJohn Marino
1999e4b17023SJohn Marino gcc_assert (TREE_CODE (val) == INTEGER_CST);
2000e4b17023SJohn Marino return (integer_zerop (val) ? false_edge : true_edge);
2001e4b17023SJohn Marino }
2002e4b17023SJohn Marino
2003e4b17023SJohn Marino /* Given an INTEGER_CST VAL and the entry block BB to a SWITCH_EXPR
2004e4b17023SJohn Marino statement, determine which edge will be taken out of the block. Return
2005e4b17023SJohn Marino NULL if any edge may be taken. */
2006e4b17023SJohn Marino
2007e4b17023SJohn Marino static edge
find_taken_edge_switch_expr(basic_block bb,tree val)2008e4b17023SJohn Marino find_taken_edge_switch_expr (basic_block bb, tree val)
2009e4b17023SJohn Marino {
2010e4b17023SJohn Marino basic_block dest_bb;
2011e4b17023SJohn Marino edge e;
2012e4b17023SJohn Marino gimple switch_stmt;
2013e4b17023SJohn Marino tree taken_case;
2014e4b17023SJohn Marino
2015e4b17023SJohn Marino switch_stmt = last_stmt (bb);
2016e4b17023SJohn Marino taken_case = find_case_label_for_value (switch_stmt, val);
2017e4b17023SJohn Marino dest_bb = label_to_block (CASE_LABEL (taken_case));
2018e4b17023SJohn Marino
2019e4b17023SJohn Marino e = find_edge (bb, dest_bb);
2020e4b17023SJohn Marino gcc_assert (e);
2021e4b17023SJohn Marino return e;
2022e4b17023SJohn Marino }
2023e4b17023SJohn Marino
2024e4b17023SJohn Marino
2025e4b17023SJohn Marino /* Return the CASE_LABEL_EXPR that SWITCH_STMT will take for VAL.
2026e4b17023SJohn Marino We can make optimal use here of the fact that the case labels are
2027e4b17023SJohn Marino sorted: We can do a binary search for a case matching VAL. */
2028e4b17023SJohn Marino
2029e4b17023SJohn Marino static tree
find_case_label_for_value(gimple switch_stmt,tree val)2030e4b17023SJohn Marino find_case_label_for_value (gimple switch_stmt, tree val)
2031e4b17023SJohn Marino {
2032e4b17023SJohn Marino size_t low, high, n = gimple_switch_num_labels (switch_stmt);
2033e4b17023SJohn Marino tree default_case = gimple_switch_default_label (switch_stmt);
2034e4b17023SJohn Marino
2035e4b17023SJohn Marino for (low = 0, high = n; high - low > 1; )
2036e4b17023SJohn Marino {
2037e4b17023SJohn Marino size_t i = (high + low) / 2;
2038e4b17023SJohn Marino tree t = gimple_switch_label (switch_stmt, i);
2039e4b17023SJohn Marino int cmp;
2040e4b17023SJohn Marino
2041e4b17023SJohn Marino /* Cache the result of comparing CASE_LOW and val. */
2042e4b17023SJohn Marino cmp = tree_int_cst_compare (CASE_LOW (t), val);
2043e4b17023SJohn Marino
2044e4b17023SJohn Marino if (cmp > 0)
2045e4b17023SJohn Marino high = i;
2046e4b17023SJohn Marino else
2047e4b17023SJohn Marino low = i;
2048e4b17023SJohn Marino
2049e4b17023SJohn Marino if (CASE_HIGH (t) == NULL)
2050e4b17023SJohn Marino {
2051e4b17023SJohn Marino /* A singe-valued case label. */
2052e4b17023SJohn Marino if (cmp == 0)
2053e4b17023SJohn Marino return t;
2054e4b17023SJohn Marino }
2055e4b17023SJohn Marino else
2056e4b17023SJohn Marino {
2057e4b17023SJohn Marino /* A case range. We can only handle integer ranges. */
2058e4b17023SJohn Marino if (cmp <= 0 && tree_int_cst_compare (CASE_HIGH (t), val) >= 0)
2059e4b17023SJohn Marino return t;
2060e4b17023SJohn Marino }
2061e4b17023SJohn Marino }
2062e4b17023SJohn Marino
2063e4b17023SJohn Marino return default_case;
2064e4b17023SJohn Marino }
2065e4b17023SJohn Marino
2066e4b17023SJohn Marino
2067e4b17023SJohn Marino /* Dump a basic block on stderr. */
2068e4b17023SJohn Marino
2069e4b17023SJohn Marino void
gimple_debug_bb(basic_block bb)2070e4b17023SJohn Marino gimple_debug_bb (basic_block bb)
2071e4b17023SJohn Marino {
2072e4b17023SJohn Marino gimple_dump_bb (bb, stderr, 0, TDF_VOPS|TDF_MEMSYMS);
2073e4b17023SJohn Marino }
2074e4b17023SJohn Marino
2075e4b17023SJohn Marino
2076e4b17023SJohn Marino /* Dump basic block with index N on stderr. */
2077e4b17023SJohn Marino
2078e4b17023SJohn Marino basic_block
gimple_debug_bb_n(int n)2079e4b17023SJohn Marino gimple_debug_bb_n (int n)
2080e4b17023SJohn Marino {
2081e4b17023SJohn Marino gimple_debug_bb (BASIC_BLOCK (n));
2082e4b17023SJohn Marino return BASIC_BLOCK (n);
2083e4b17023SJohn Marino }
2084e4b17023SJohn Marino
2085e4b17023SJohn Marino
2086e4b17023SJohn Marino /* Dump the CFG on stderr.
2087e4b17023SJohn Marino
2088e4b17023SJohn Marino FLAGS are the same used by the tree dumping functions
2089e4b17023SJohn Marino (see TDF_* in tree-pass.h). */
2090e4b17023SJohn Marino
2091e4b17023SJohn Marino void
gimple_debug_cfg(int flags)2092e4b17023SJohn Marino gimple_debug_cfg (int flags)
2093e4b17023SJohn Marino {
2094e4b17023SJohn Marino gimple_dump_cfg (stderr, flags);
2095e4b17023SJohn Marino }
2096e4b17023SJohn Marino
2097e4b17023SJohn Marino
2098e4b17023SJohn Marino /* Dump the program showing basic block boundaries on the given FILE.
2099e4b17023SJohn Marino
2100e4b17023SJohn Marino FLAGS are the same used by the tree dumping functions (see TDF_* in
2101e4b17023SJohn Marino tree.h). */
2102e4b17023SJohn Marino
2103e4b17023SJohn Marino void
gimple_dump_cfg(FILE * file,int flags)2104e4b17023SJohn Marino gimple_dump_cfg (FILE *file, int flags)
2105e4b17023SJohn Marino {
2106e4b17023SJohn Marino if (flags & TDF_DETAILS)
2107e4b17023SJohn Marino {
2108e4b17023SJohn Marino dump_function_header (file, current_function_decl, flags);
2109e4b17023SJohn Marino fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n",
2110e4b17023SJohn Marino n_basic_blocks, n_edges, last_basic_block);
2111e4b17023SJohn Marino
2112e4b17023SJohn Marino brief_dump_cfg (file);
2113e4b17023SJohn Marino fprintf (file, "\n");
2114e4b17023SJohn Marino }
2115e4b17023SJohn Marino
2116e4b17023SJohn Marino if (flags & TDF_STATS)
2117e4b17023SJohn Marino dump_cfg_stats (file);
2118e4b17023SJohn Marino
2119e4b17023SJohn Marino dump_function_to_file (current_function_decl, file, flags | TDF_BLOCKS);
2120e4b17023SJohn Marino }
2121e4b17023SJohn Marino
2122e4b17023SJohn Marino
2123e4b17023SJohn Marino /* Dump CFG statistics on FILE. */
2124e4b17023SJohn Marino
2125e4b17023SJohn Marino void
dump_cfg_stats(FILE * file)2126e4b17023SJohn Marino dump_cfg_stats (FILE *file)
2127e4b17023SJohn Marino {
2128e4b17023SJohn Marino static long max_num_merged_labels = 0;
2129e4b17023SJohn Marino unsigned long size, total = 0;
2130e4b17023SJohn Marino long num_edges;
2131e4b17023SJohn Marino basic_block bb;
2132e4b17023SJohn Marino const char * const fmt_str = "%-30s%-13s%12s\n";
2133e4b17023SJohn Marino const char * const fmt_str_1 = "%-30s%13d%11lu%c\n";
2134e4b17023SJohn Marino const char * const fmt_str_2 = "%-30s%13ld%11lu%c\n";
2135e4b17023SJohn Marino const char * const fmt_str_3 = "%-43s%11lu%c\n";
2136e4b17023SJohn Marino const char *funcname
2137e4b17023SJohn Marino = lang_hooks.decl_printable_name (current_function_decl, 2);
2138e4b17023SJohn Marino
2139e4b17023SJohn Marino
2140e4b17023SJohn Marino fprintf (file, "\nCFG Statistics for %s\n\n", funcname);
2141e4b17023SJohn Marino
2142e4b17023SJohn Marino fprintf (file, "---------------------------------------------------------\n");
2143e4b17023SJohn Marino fprintf (file, fmt_str, "", " Number of ", "Memory");
2144e4b17023SJohn Marino fprintf (file, fmt_str, "", " instances ", "used ");
2145e4b17023SJohn Marino fprintf (file, "---------------------------------------------------------\n");
2146e4b17023SJohn Marino
2147e4b17023SJohn Marino size = n_basic_blocks * sizeof (struct basic_block_def);
2148e4b17023SJohn Marino total += size;
2149e4b17023SJohn Marino fprintf (file, fmt_str_1, "Basic blocks", n_basic_blocks,
2150e4b17023SJohn Marino SCALE (size), LABEL (size));
2151e4b17023SJohn Marino
2152e4b17023SJohn Marino num_edges = 0;
2153e4b17023SJohn Marino FOR_EACH_BB (bb)
2154e4b17023SJohn Marino num_edges += EDGE_COUNT (bb->succs);
2155e4b17023SJohn Marino size = num_edges * sizeof (struct edge_def);
2156e4b17023SJohn Marino total += size;
2157e4b17023SJohn Marino fprintf (file, fmt_str_2, "Edges", num_edges, SCALE (size), LABEL (size));
2158e4b17023SJohn Marino
2159e4b17023SJohn Marino fprintf (file, "---------------------------------------------------------\n");
2160e4b17023SJohn Marino fprintf (file, fmt_str_3, "Total memory used by CFG data", SCALE (total),
2161e4b17023SJohn Marino LABEL (total));
2162e4b17023SJohn Marino fprintf (file, "---------------------------------------------------------\n");
2163e4b17023SJohn Marino fprintf (file, "\n");
2164e4b17023SJohn Marino
2165e4b17023SJohn Marino if (cfg_stats.num_merged_labels > max_num_merged_labels)
2166e4b17023SJohn Marino max_num_merged_labels = cfg_stats.num_merged_labels;
2167e4b17023SJohn Marino
2168e4b17023SJohn Marino fprintf (file, "Coalesced label blocks: %ld (Max so far: %ld)\n",
2169e4b17023SJohn Marino cfg_stats.num_merged_labels, max_num_merged_labels);
2170e4b17023SJohn Marino
2171e4b17023SJohn Marino fprintf (file, "\n");
2172e4b17023SJohn Marino }
2173e4b17023SJohn Marino
2174e4b17023SJohn Marino
2175e4b17023SJohn Marino /* Dump CFG statistics on stderr. Keep extern so that it's always
2176e4b17023SJohn Marino linked in the final executable. */
2177e4b17023SJohn Marino
2178e4b17023SJohn Marino DEBUG_FUNCTION void
debug_cfg_stats(void)2179e4b17023SJohn Marino debug_cfg_stats (void)
2180e4b17023SJohn Marino {
2181e4b17023SJohn Marino dump_cfg_stats (stderr);
2182e4b17023SJohn Marino }
2183e4b17023SJohn Marino
2184e4b17023SJohn Marino
2185e4b17023SJohn Marino /* Dump the flowgraph to a .vcg FILE. */
2186e4b17023SJohn Marino
2187e4b17023SJohn Marino static void
gimple_cfg2vcg(FILE * file)2188e4b17023SJohn Marino gimple_cfg2vcg (FILE *file)
2189e4b17023SJohn Marino {
2190e4b17023SJohn Marino edge e;
2191e4b17023SJohn Marino edge_iterator ei;
2192e4b17023SJohn Marino basic_block bb;
2193e4b17023SJohn Marino const char *funcname
2194e4b17023SJohn Marino = lang_hooks.decl_printable_name (current_function_decl, 2);
2195e4b17023SJohn Marino
2196e4b17023SJohn Marino /* Write the file header. */
2197e4b17023SJohn Marino fprintf (file, "graph: { title: \"%s\"\n", funcname);
2198e4b17023SJohn Marino fprintf (file, "node: { title: \"ENTRY\" label: \"ENTRY\" }\n");
2199e4b17023SJohn Marino fprintf (file, "node: { title: \"EXIT\" label: \"EXIT\" }\n");
2200e4b17023SJohn Marino
2201e4b17023SJohn Marino /* Write blocks and edges. */
2202e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
2203e4b17023SJohn Marino {
2204e4b17023SJohn Marino fprintf (file, "edge: { sourcename: \"ENTRY\" targetname: \"%d\"",
2205e4b17023SJohn Marino e->dest->index);
2206e4b17023SJohn Marino
2207e4b17023SJohn Marino if (e->flags & EDGE_FAKE)
2208e4b17023SJohn Marino fprintf (file, " linestyle: dotted priority: 10");
2209e4b17023SJohn Marino else
2210e4b17023SJohn Marino fprintf (file, " linestyle: solid priority: 100");
2211e4b17023SJohn Marino
2212e4b17023SJohn Marino fprintf (file, " }\n");
2213e4b17023SJohn Marino }
2214e4b17023SJohn Marino fputc ('\n', file);
2215e4b17023SJohn Marino
2216e4b17023SJohn Marino FOR_EACH_BB (bb)
2217e4b17023SJohn Marino {
2218e4b17023SJohn Marino enum gimple_code head_code, end_code;
2219e4b17023SJohn Marino const char *head_name, *end_name;
2220e4b17023SJohn Marino int head_line = 0;
2221e4b17023SJohn Marino int end_line = 0;
2222e4b17023SJohn Marino gimple first = first_stmt (bb);
2223e4b17023SJohn Marino gimple last = last_stmt (bb);
2224e4b17023SJohn Marino
2225e4b17023SJohn Marino if (first)
2226e4b17023SJohn Marino {
2227e4b17023SJohn Marino head_code = gimple_code (first);
2228e4b17023SJohn Marino head_name = gimple_code_name[head_code];
2229e4b17023SJohn Marino head_line = get_lineno (first);
2230e4b17023SJohn Marino }
2231e4b17023SJohn Marino else
2232e4b17023SJohn Marino head_name = "no-statement";
2233e4b17023SJohn Marino
2234e4b17023SJohn Marino if (last)
2235e4b17023SJohn Marino {
2236e4b17023SJohn Marino end_code = gimple_code (last);
2237e4b17023SJohn Marino end_name = gimple_code_name[end_code];
2238e4b17023SJohn Marino end_line = get_lineno (last);
2239e4b17023SJohn Marino }
2240e4b17023SJohn Marino else
2241e4b17023SJohn Marino end_name = "no-statement";
2242e4b17023SJohn Marino
2243e4b17023SJohn Marino fprintf (file, "node: { title: \"%d\" label: \"#%d\\n%s (%d)\\n%s (%d)\"}\n",
2244e4b17023SJohn Marino bb->index, bb->index, head_name, head_line, end_name,
2245e4b17023SJohn Marino end_line);
2246e4b17023SJohn Marino
2247e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
2248e4b17023SJohn Marino {
2249e4b17023SJohn Marino if (e->dest == EXIT_BLOCK_PTR)
2250e4b17023SJohn Marino fprintf (file, "edge: { sourcename: \"%d\" targetname: \"EXIT\"", bb->index);
2251e4b17023SJohn Marino else
2252e4b17023SJohn Marino fprintf (file, "edge: { sourcename: \"%d\" targetname: \"%d\"", bb->index, e->dest->index);
2253e4b17023SJohn Marino
2254e4b17023SJohn Marino if (e->flags & EDGE_FAKE)
2255e4b17023SJohn Marino fprintf (file, " priority: 10 linestyle: dotted");
2256e4b17023SJohn Marino else
2257e4b17023SJohn Marino fprintf (file, " priority: 100 linestyle: solid");
2258e4b17023SJohn Marino
2259e4b17023SJohn Marino fprintf (file, " }\n");
2260e4b17023SJohn Marino }
2261e4b17023SJohn Marino
2262e4b17023SJohn Marino if (bb->next_bb != EXIT_BLOCK_PTR)
2263e4b17023SJohn Marino fputc ('\n', file);
2264e4b17023SJohn Marino }
2265e4b17023SJohn Marino
2266e4b17023SJohn Marino fputs ("}\n\n", file);
2267e4b17023SJohn Marino }
2268e4b17023SJohn Marino
2269e4b17023SJohn Marino
2270e4b17023SJohn Marino
2271e4b17023SJohn Marino /*---------------------------------------------------------------------------
2272e4b17023SJohn Marino Miscellaneous helpers
2273e4b17023SJohn Marino ---------------------------------------------------------------------------*/
2274e4b17023SJohn Marino
2275e4b17023SJohn Marino /* Return true if T, a GIMPLE_CALL, can make an abnormal transfer of control
2276e4b17023SJohn Marino flow. Transfers of control flow associated with EH are excluded. */
2277e4b17023SJohn Marino
2278e4b17023SJohn Marino static bool
call_can_make_abnormal_goto(gimple t)2279e4b17023SJohn Marino call_can_make_abnormal_goto (gimple t)
2280e4b17023SJohn Marino {
2281e4b17023SJohn Marino /* If the function has no non-local labels, then a call cannot make an
2282e4b17023SJohn Marino abnormal transfer of control. */
2283e4b17023SJohn Marino if (!cfun->has_nonlocal_label)
2284e4b17023SJohn Marino return false;
2285e4b17023SJohn Marino
2286e4b17023SJohn Marino /* Likewise if the call has no side effects. */
2287e4b17023SJohn Marino if (!gimple_has_side_effects (t))
2288e4b17023SJohn Marino return false;
2289e4b17023SJohn Marino
2290e4b17023SJohn Marino /* Likewise if the called function is leaf. */
2291e4b17023SJohn Marino if (gimple_call_flags (t) & ECF_LEAF)
2292e4b17023SJohn Marino return false;
2293e4b17023SJohn Marino
2294e4b17023SJohn Marino return true;
2295e4b17023SJohn Marino }
2296e4b17023SJohn Marino
2297e4b17023SJohn Marino
2298e4b17023SJohn Marino /* Return true if T can make an abnormal transfer of control flow.
2299e4b17023SJohn Marino Transfers of control flow associated with EH are excluded. */
2300e4b17023SJohn Marino
2301e4b17023SJohn Marino bool
stmt_can_make_abnormal_goto(gimple t)2302e4b17023SJohn Marino stmt_can_make_abnormal_goto (gimple t)
2303e4b17023SJohn Marino {
2304e4b17023SJohn Marino if (computed_goto_p (t))
2305e4b17023SJohn Marino return true;
2306e4b17023SJohn Marino if (is_gimple_call (t))
2307e4b17023SJohn Marino return call_can_make_abnormal_goto (t);
2308e4b17023SJohn Marino return false;
2309e4b17023SJohn Marino }
2310e4b17023SJohn Marino
2311e4b17023SJohn Marino
2312e4b17023SJohn Marino /* Return true if T represents a stmt that always transfers control. */
2313e4b17023SJohn Marino
2314e4b17023SJohn Marino bool
is_ctrl_stmt(gimple t)2315e4b17023SJohn Marino is_ctrl_stmt (gimple t)
2316e4b17023SJohn Marino {
2317e4b17023SJohn Marino switch (gimple_code (t))
2318e4b17023SJohn Marino {
2319e4b17023SJohn Marino case GIMPLE_COND:
2320e4b17023SJohn Marino case GIMPLE_SWITCH:
2321e4b17023SJohn Marino case GIMPLE_GOTO:
2322e4b17023SJohn Marino case GIMPLE_RETURN:
2323e4b17023SJohn Marino case GIMPLE_RESX:
2324e4b17023SJohn Marino return true;
2325e4b17023SJohn Marino default:
2326e4b17023SJohn Marino return false;
2327e4b17023SJohn Marino }
2328e4b17023SJohn Marino }
2329e4b17023SJohn Marino
2330e4b17023SJohn Marino
2331e4b17023SJohn Marino /* Return true if T is a statement that may alter the flow of control
2332e4b17023SJohn Marino (e.g., a call to a non-returning function). */
2333e4b17023SJohn Marino
2334e4b17023SJohn Marino bool
is_ctrl_altering_stmt(gimple t)2335e4b17023SJohn Marino is_ctrl_altering_stmt (gimple t)
2336e4b17023SJohn Marino {
2337e4b17023SJohn Marino gcc_assert (t);
2338e4b17023SJohn Marino
2339e4b17023SJohn Marino switch (gimple_code (t))
2340e4b17023SJohn Marino {
2341e4b17023SJohn Marino case GIMPLE_CALL:
2342e4b17023SJohn Marino {
2343e4b17023SJohn Marino int flags = gimple_call_flags (t);
2344e4b17023SJohn Marino
2345e4b17023SJohn Marino /* A call alters control flow if it can make an abnormal goto. */
2346e4b17023SJohn Marino if (call_can_make_abnormal_goto (t))
2347e4b17023SJohn Marino return true;
2348e4b17023SJohn Marino
2349e4b17023SJohn Marino /* A call also alters control flow if it does not return. */
2350e4b17023SJohn Marino if (flags & ECF_NORETURN)
2351e4b17023SJohn Marino return true;
2352e4b17023SJohn Marino
2353e4b17023SJohn Marino /* TM ending statements have backedges out of the transaction.
2354e4b17023SJohn Marino Return true so we split the basic block containing them.
2355e4b17023SJohn Marino Note that the TM_BUILTIN test is merely an optimization. */
2356e4b17023SJohn Marino if ((flags & ECF_TM_BUILTIN)
2357e4b17023SJohn Marino && is_tm_ending_fndecl (gimple_call_fndecl (t)))
2358e4b17023SJohn Marino return true;
2359e4b17023SJohn Marino
2360e4b17023SJohn Marino /* BUILT_IN_RETURN call is same as return statement. */
2361e4b17023SJohn Marino if (gimple_call_builtin_p (t, BUILT_IN_RETURN))
2362e4b17023SJohn Marino return true;
2363e4b17023SJohn Marino }
2364e4b17023SJohn Marino break;
2365e4b17023SJohn Marino
2366e4b17023SJohn Marino case GIMPLE_EH_DISPATCH:
2367e4b17023SJohn Marino /* EH_DISPATCH branches to the individual catch handlers at
2368e4b17023SJohn Marino this level of a try or allowed-exceptions region. It can
2369e4b17023SJohn Marino fallthru to the next statement as well. */
2370e4b17023SJohn Marino return true;
2371e4b17023SJohn Marino
2372e4b17023SJohn Marino case GIMPLE_ASM:
2373e4b17023SJohn Marino if (gimple_asm_nlabels (t) > 0)
2374e4b17023SJohn Marino return true;
2375e4b17023SJohn Marino break;
2376e4b17023SJohn Marino
2377e4b17023SJohn Marino CASE_GIMPLE_OMP:
2378e4b17023SJohn Marino /* OpenMP directives alter control flow. */
2379e4b17023SJohn Marino return true;
2380e4b17023SJohn Marino
2381e4b17023SJohn Marino case GIMPLE_TRANSACTION:
2382e4b17023SJohn Marino /* A transaction start alters control flow. */
2383e4b17023SJohn Marino return true;
2384e4b17023SJohn Marino
2385e4b17023SJohn Marino default:
2386e4b17023SJohn Marino break;
2387e4b17023SJohn Marino }
2388e4b17023SJohn Marino
2389e4b17023SJohn Marino /* If a statement can throw, it alters control flow. */
2390e4b17023SJohn Marino return stmt_can_throw_internal (t);
2391e4b17023SJohn Marino }
2392e4b17023SJohn Marino
2393e4b17023SJohn Marino
2394e4b17023SJohn Marino /* Return true if T is a simple local goto. */
2395e4b17023SJohn Marino
2396e4b17023SJohn Marino bool
simple_goto_p(gimple t)2397e4b17023SJohn Marino simple_goto_p (gimple t)
2398e4b17023SJohn Marino {
2399e4b17023SJohn Marino return (gimple_code (t) == GIMPLE_GOTO
2400e4b17023SJohn Marino && TREE_CODE (gimple_goto_dest (t)) == LABEL_DECL);
2401e4b17023SJohn Marino }
2402e4b17023SJohn Marino
2403e4b17023SJohn Marino
2404e4b17023SJohn Marino /* Return true if STMT should start a new basic block. PREV_STMT is
2405e4b17023SJohn Marino the statement preceding STMT. It is used when STMT is a label or a
2406e4b17023SJohn Marino case label. Labels should only start a new basic block if their
2407e4b17023SJohn Marino previous statement wasn't a label. Otherwise, sequence of labels
2408e4b17023SJohn Marino would generate unnecessary basic blocks that only contain a single
2409e4b17023SJohn Marino label. */
2410e4b17023SJohn Marino
2411e4b17023SJohn Marino static inline bool
stmt_starts_bb_p(gimple stmt,gimple prev_stmt)2412e4b17023SJohn Marino stmt_starts_bb_p (gimple stmt, gimple prev_stmt)
2413e4b17023SJohn Marino {
2414e4b17023SJohn Marino if (stmt == NULL)
2415e4b17023SJohn Marino return false;
2416e4b17023SJohn Marino
2417e4b17023SJohn Marino /* Labels start a new basic block only if the preceding statement
2418e4b17023SJohn Marino wasn't a label of the same type. This prevents the creation of
2419e4b17023SJohn Marino consecutive blocks that have nothing but a single label. */
2420e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL)
2421e4b17023SJohn Marino {
2422e4b17023SJohn Marino /* Nonlocal and computed GOTO targets always start a new block. */
2423e4b17023SJohn Marino if (DECL_NONLOCAL (gimple_label_label (stmt))
2424e4b17023SJohn Marino || FORCED_LABEL (gimple_label_label (stmt)))
2425e4b17023SJohn Marino return true;
2426e4b17023SJohn Marino
2427e4b17023SJohn Marino if (prev_stmt && gimple_code (prev_stmt) == GIMPLE_LABEL)
2428e4b17023SJohn Marino {
2429e4b17023SJohn Marino if (DECL_NONLOCAL (gimple_label_label (prev_stmt)))
2430e4b17023SJohn Marino return true;
2431e4b17023SJohn Marino
2432e4b17023SJohn Marino cfg_stats.num_merged_labels++;
2433e4b17023SJohn Marino return false;
2434e4b17023SJohn Marino }
2435e4b17023SJohn Marino else
2436e4b17023SJohn Marino return true;
2437e4b17023SJohn Marino }
2438e4b17023SJohn Marino
2439e4b17023SJohn Marino return false;
2440e4b17023SJohn Marino }
2441e4b17023SJohn Marino
2442e4b17023SJohn Marino
2443e4b17023SJohn Marino /* Return true if T should end a basic block. */
2444e4b17023SJohn Marino
2445e4b17023SJohn Marino bool
stmt_ends_bb_p(gimple t)2446e4b17023SJohn Marino stmt_ends_bb_p (gimple t)
2447e4b17023SJohn Marino {
2448e4b17023SJohn Marino return is_ctrl_stmt (t) || is_ctrl_altering_stmt (t);
2449e4b17023SJohn Marino }
2450e4b17023SJohn Marino
2451e4b17023SJohn Marino /* Remove block annotations and other data structures. */
2452e4b17023SJohn Marino
2453e4b17023SJohn Marino void
delete_tree_cfg_annotations(void)2454e4b17023SJohn Marino delete_tree_cfg_annotations (void)
2455e4b17023SJohn Marino {
2456e4b17023SJohn Marino label_to_block_map = NULL;
2457e4b17023SJohn Marino }
2458e4b17023SJohn Marino
2459e4b17023SJohn Marino
2460e4b17023SJohn Marino /* Return the first statement in basic block BB. */
2461e4b17023SJohn Marino
2462e4b17023SJohn Marino gimple
first_stmt(basic_block bb)2463e4b17023SJohn Marino first_stmt (basic_block bb)
2464e4b17023SJohn Marino {
2465e4b17023SJohn Marino gimple_stmt_iterator i = gsi_start_bb (bb);
2466e4b17023SJohn Marino gimple stmt = NULL;
2467e4b17023SJohn Marino
2468e4b17023SJohn Marino while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
2469e4b17023SJohn Marino {
2470e4b17023SJohn Marino gsi_next (&i);
2471e4b17023SJohn Marino stmt = NULL;
2472e4b17023SJohn Marino }
2473e4b17023SJohn Marino return stmt;
2474e4b17023SJohn Marino }
2475e4b17023SJohn Marino
2476e4b17023SJohn Marino /* Return the first non-label statement in basic block BB. */
2477e4b17023SJohn Marino
2478e4b17023SJohn Marino static gimple
first_non_label_stmt(basic_block bb)2479e4b17023SJohn Marino first_non_label_stmt (basic_block bb)
2480e4b17023SJohn Marino {
2481e4b17023SJohn Marino gimple_stmt_iterator i = gsi_start_bb (bb);
2482e4b17023SJohn Marino while (!gsi_end_p (i) && gimple_code (gsi_stmt (i)) == GIMPLE_LABEL)
2483e4b17023SJohn Marino gsi_next (&i);
2484e4b17023SJohn Marino return !gsi_end_p (i) ? gsi_stmt (i) : NULL;
2485e4b17023SJohn Marino }
2486e4b17023SJohn Marino
2487e4b17023SJohn Marino /* Return the last statement in basic block BB. */
2488e4b17023SJohn Marino
2489e4b17023SJohn Marino gimple
last_stmt(basic_block bb)2490e4b17023SJohn Marino last_stmt (basic_block bb)
2491e4b17023SJohn Marino {
2492e4b17023SJohn Marino gimple_stmt_iterator i = gsi_last_bb (bb);
2493e4b17023SJohn Marino gimple stmt = NULL;
2494e4b17023SJohn Marino
2495e4b17023SJohn Marino while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
2496e4b17023SJohn Marino {
2497e4b17023SJohn Marino gsi_prev (&i);
2498e4b17023SJohn Marino stmt = NULL;
2499e4b17023SJohn Marino }
2500e4b17023SJohn Marino return stmt;
2501e4b17023SJohn Marino }
2502e4b17023SJohn Marino
2503e4b17023SJohn Marino /* Return the last statement of an otherwise empty block. Return NULL
2504e4b17023SJohn Marino if the block is totally empty, or if it contains more than one
2505e4b17023SJohn Marino statement. */
2506e4b17023SJohn Marino
2507e4b17023SJohn Marino gimple
last_and_only_stmt(basic_block bb)2508e4b17023SJohn Marino last_and_only_stmt (basic_block bb)
2509e4b17023SJohn Marino {
2510e4b17023SJohn Marino gimple_stmt_iterator i = gsi_last_nondebug_bb (bb);
2511e4b17023SJohn Marino gimple last, prev;
2512e4b17023SJohn Marino
2513e4b17023SJohn Marino if (gsi_end_p (i))
2514e4b17023SJohn Marino return NULL;
2515e4b17023SJohn Marino
2516e4b17023SJohn Marino last = gsi_stmt (i);
2517e4b17023SJohn Marino gsi_prev_nondebug (&i);
2518e4b17023SJohn Marino if (gsi_end_p (i))
2519e4b17023SJohn Marino return last;
2520e4b17023SJohn Marino
2521e4b17023SJohn Marino /* Empty statements should no longer appear in the instruction stream.
2522e4b17023SJohn Marino Everything that might have appeared before should be deleted by
2523e4b17023SJohn Marino remove_useless_stmts, and the optimizers should just gsi_remove
2524e4b17023SJohn Marino instead of smashing with build_empty_stmt.
2525e4b17023SJohn Marino
2526e4b17023SJohn Marino Thus the only thing that should appear here in a block containing
2527e4b17023SJohn Marino one executable statement is a label. */
2528e4b17023SJohn Marino prev = gsi_stmt (i);
2529e4b17023SJohn Marino if (gimple_code (prev) == GIMPLE_LABEL)
2530e4b17023SJohn Marino return last;
2531e4b17023SJohn Marino else
2532e4b17023SJohn Marino return NULL;
2533e4b17023SJohn Marino }
2534e4b17023SJohn Marino
2535e4b17023SJohn Marino /* Reinstall those PHI arguments queued in OLD_EDGE to NEW_EDGE. */
2536e4b17023SJohn Marino
2537e4b17023SJohn Marino static void
reinstall_phi_args(edge new_edge,edge old_edge)2538e4b17023SJohn Marino reinstall_phi_args (edge new_edge, edge old_edge)
2539e4b17023SJohn Marino {
2540e4b17023SJohn Marino edge_var_map_vector v;
2541e4b17023SJohn Marino edge_var_map *vm;
2542e4b17023SJohn Marino int i;
2543e4b17023SJohn Marino gimple_stmt_iterator phis;
2544e4b17023SJohn Marino
2545e4b17023SJohn Marino v = redirect_edge_var_map_vector (old_edge);
2546e4b17023SJohn Marino if (!v)
2547e4b17023SJohn Marino return;
2548e4b17023SJohn Marino
2549e4b17023SJohn Marino for (i = 0, phis = gsi_start_phis (new_edge->dest);
2550e4b17023SJohn Marino VEC_iterate (edge_var_map, v, i, vm) && !gsi_end_p (phis);
2551e4b17023SJohn Marino i++, gsi_next (&phis))
2552e4b17023SJohn Marino {
2553e4b17023SJohn Marino gimple phi = gsi_stmt (phis);
2554e4b17023SJohn Marino tree result = redirect_edge_var_map_result (vm);
2555e4b17023SJohn Marino tree arg = redirect_edge_var_map_def (vm);
2556e4b17023SJohn Marino
2557e4b17023SJohn Marino gcc_assert (result == gimple_phi_result (phi));
2558e4b17023SJohn Marino
2559e4b17023SJohn Marino add_phi_arg (phi, arg, new_edge, redirect_edge_var_map_location (vm));
2560e4b17023SJohn Marino }
2561e4b17023SJohn Marino
2562e4b17023SJohn Marino redirect_edge_var_map_clear (old_edge);
2563e4b17023SJohn Marino }
2564e4b17023SJohn Marino
2565e4b17023SJohn Marino /* Returns the basic block after which the new basic block created
2566e4b17023SJohn Marino by splitting edge EDGE_IN should be placed. Tries to keep the new block
2567e4b17023SJohn Marino near its "logical" location. This is of most help to humans looking
2568e4b17023SJohn Marino at debugging dumps. */
2569e4b17023SJohn Marino
2570e4b17023SJohn Marino static basic_block
split_edge_bb_loc(edge edge_in)2571e4b17023SJohn Marino split_edge_bb_loc (edge edge_in)
2572e4b17023SJohn Marino {
2573e4b17023SJohn Marino basic_block dest = edge_in->dest;
2574e4b17023SJohn Marino basic_block dest_prev = dest->prev_bb;
2575e4b17023SJohn Marino
2576e4b17023SJohn Marino if (dest_prev)
2577e4b17023SJohn Marino {
2578e4b17023SJohn Marino edge e = find_edge (dest_prev, dest);
2579e4b17023SJohn Marino if (e && !(e->flags & EDGE_COMPLEX))
2580e4b17023SJohn Marino return edge_in->src;
2581e4b17023SJohn Marino }
2582e4b17023SJohn Marino return dest_prev;
2583e4b17023SJohn Marino }
2584e4b17023SJohn Marino
2585e4b17023SJohn Marino /* Split a (typically critical) edge EDGE_IN. Return the new block.
2586e4b17023SJohn Marino Abort on abnormal edges. */
2587e4b17023SJohn Marino
2588e4b17023SJohn Marino static basic_block
gimple_split_edge(edge edge_in)2589e4b17023SJohn Marino gimple_split_edge (edge edge_in)
2590e4b17023SJohn Marino {
2591e4b17023SJohn Marino basic_block new_bb, after_bb, dest;
2592e4b17023SJohn Marino edge new_edge, e;
2593e4b17023SJohn Marino
2594e4b17023SJohn Marino /* Abnormal edges cannot be split. */
2595e4b17023SJohn Marino gcc_assert (!(edge_in->flags & EDGE_ABNORMAL));
2596e4b17023SJohn Marino
2597e4b17023SJohn Marino dest = edge_in->dest;
2598e4b17023SJohn Marino
2599e4b17023SJohn Marino after_bb = split_edge_bb_loc (edge_in);
2600e4b17023SJohn Marino
2601e4b17023SJohn Marino new_bb = create_empty_bb (after_bb);
2602e4b17023SJohn Marino new_bb->frequency = EDGE_FREQUENCY (edge_in);
2603e4b17023SJohn Marino new_bb->count = edge_in->count;
2604e4b17023SJohn Marino new_edge = make_edge (new_bb, dest, EDGE_FALLTHRU);
2605e4b17023SJohn Marino new_edge->probability = REG_BR_PROB_BASE;
2606e4b17023SJohn Marino new_edge->count = edge_in->count;
2607e4b17023SJohn Marino
2608e4b17023SJohn Marino e = redirect_edge_and_branch (edge_in, new_bb);
2609e4b17023SJohn Marino gcc_assert (e == edge_in);
2610e4b17023SJohn Marino reinstall_phi_args (new_edge, e);
2611e4b17023SJohn Marino
2612e4b17023SJohn Marino return new_bb;
2613e4b17023SJohn Marino }
2614e4b17023SJohn Marino
2615e4b17023SJohn Marino
2616e4b17023SJohn Marino /* Verify properties of the address expression T with base object BASE. */
2617e4b17023SJohn Marino
2618e4b17023SJohn Marino static tree
verify_address(tree t,tree base)2619e4b17023SJohn Marino verify_address (tree t, tree base)
2620e4b17023SJohn Marino {
2621e4b17023SJohn Marino bool old_constant;
2622e4b17023SJohn Marino bool old_side_effects;
2623e4b17023SJohn Marino bool new_constant;
2624e4b17023SJohn Marino bool new_side_effects;
2625e4b17023SJohn Marino
2626e4b17023SJohn Marino old_constant = TREE_CONSTANT (t);
2627e4b17023SJohn Marino old_side_effects = TREE_SIDE_EFFECTS (t);
2628e4b17023SJohn Marino
2629e4b17023SJohn Marino recompute_tree_invariant_for_addr_expr (t);
2630e4b17023SJohn Marino new_side_effects = TREE_SIDE_EFFECTS (t);
2631e4b17023SJohn Marino new_constant = TREE_CONSTANT (t);
2632e4b17023SJohn Marino
2633e4b17023SJohn Marino if (old_constant != new_constant)
2634e4b17023SJohn Marino {
2635e4b17023SJohn Marino error ("constant not recomputed when ADDR_EXPR changed");
2636e4b17023SJohn Marino return t;
2637e4b17023SJohn Marino }
2638e4b17023SJohn Marino if (old_side_effects != new_side_effects)
2639e4b17023SJohn Marino {
2640e4b17023SJohn Marino error ("side effects not recomputed when ADDR_EXPR changed");
2641e4b17023SJohn Marino return t;
2642e4b17023SJohn Marino }
2643e4b17023SJohn Marino
2644e4b17023SJohn Marino if (!(TREE_CODE (base) == VAR_DECL
2645e4b17023SJohn Marino || TREE_CODE (base) == PARM_DECL
2646e4b17023SJohn Marino || TREE_CODE (base) == RESULT_DECL))
2647e4b17023SJohn Marino return NULL_TREE;
2648e4b17023SJohn Marino
2649e4b17023SJohn Marino if (DECL_GIMPLE_REG_P (base))
2650e4b17023SJohn Marino {
2651e4b17023SJohn Marino error ("DECL_GIMPLE_REG_P set on a variable with address taken");
2652e4b17023SJohn Marino return base;
2653e4b17023SJohn Marino }
2654e4b17023SJohn Marino
2655e4b17023SJohn Marino return NULL_TREE;
2656e4b17023SJohn Marino }
2657e4b17023SJohn Marino
2658e4b17023SJohn Marino /* Callback for walk_tree, check that all elements with address taken are
2659e4b17023SJohn Marino properly noticed as such. The DATA is an int* that is 1 if TP was seen
2660e4b17023SJohn Marino inside a PHI node. */
2661e4b17023SJohn Marino
2662e4b17023SJohn Marino static tree
verify_expr(tree * tp,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)2663e4b17023SJohn Marino verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
2664e4b17023SJohn Marino {
2665e4b17023SJohn Marino tree t = *tp, x;
2666e4b17023SJohn Marino
2667e4b17023SJohn Marino if (TYPE_P (t))
2668e4b17023SJohn Marino *walk_subtrees = 0;
2669e4b17023SJohn Marino
2670e4b17023SJohn Marino /* Check operand N for being valid GIMPLE and give error MSG if not. */
2671e4b17023SJohn Marino #define CHECK_OP(N, MSG) \
2672e4b17023SJohn Marino do { if (!is_gimple_val (TREE_OPERAND (t, N))) \
2673e4b17023SJohn Marino { error (MSG); return TREE_OPERAND (t, N); }} while (0)
2674e4b17023SJohn Marino
2675e4b17023SJohn Marino switch (TREE_CODE (t))
2676e4b17023SJohn Marino {
2677e4b17023SJohn Marino case SSA_NAME:
2678e4b17023SJohn Marino if (SSA_NAME_IN_FREE_LIST (t))
2679e4b17023SJohn Marino {
2680e4b17023SJohn Marino error ("SSA name in freelist but still referenced");
2681e4b17023SJohn Marino return *tp;
2682e4b17023SJohn Marino }
2683e4b17023SJohn Marino break;
2684e4b17023SJohn Marino
2685e4b17023SJohn Marino case INDIRECT_REF:
2686e4b17023SJohn Marino error ("INDIRECT_REF in gimple IL");
2687e4b17023SJohn Marino return t;
2688e4b17023SJohn Marino
2689e4b17023SJohn Marino case MEM_REF:
2690e4b17023SJohn Marino x = TREE_OPERAND (t, 0);
2691e4b17023SJohn Marino if (!POINTER_TYPE_P (TREE_TYPE (x))
2692e4b17023SJohn Marino || !is_gimple_mem_ref_addr (x))
2693e4b17023SJohn Marino {
2694e4b17023SJohn Marino error ("invalid first operand of MEM_REF");
2695e4b17023SJohn Marino return x;
2696e4b17023SJohn Marino }
2697e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST
2698e4b17023SJohn Marino || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1))))
2699e4b17023SJohn Marino {
2700e4b17023SJohn Marino error ("invalid offset operand of MEM_REF");
2701e4b17023SJohn Marino return TREE_OPERAND (t, 1);
2702e4b17023SJohn Marino }
2703e4b17023SJohn Marino if (TREE_CODE (x) == ADDR_EXPR
2704e4b17023SJohn Marino && (x = verify_address (x, TREE_OPERAND (x, 0))))
2705e4b17023SJohn Marino return x;
2706e4b17023SJohn Marino *walk_subtrees = 0;
2707e4b17023SJohn Marino break;
2708e4b17023SJohn Marino
2709e4b17023SJohn Marino case ASSERT_EXPR:
2710e4b17023SJohn Marino x = fold (ASSERT_EXPR_COND (t));
2711e4b17023SJohn Marino if (x == boolean_false_node)
2712e4b17023SJohn Marino {
2713e4b17023SJohn Marino error ("ASSERT_EXPR with an always-false condition");
2714e4b17023SJohn Marino return *tp;
2715e4b17023SJohn Marino }
2716e4b17023SJohn Marino break;
2717e4b17023SJohn Marino
2718e4b17023SJohn Marino case MODIFY_EXPR:
2719e4b17023SJohn Marino error ("MODIFY_EXPR not expected while having tuples");
2720e4b17023SJohn Marino return *tp;
2721e4b17023SJohn Marino
2722e4b17023SJohn Marino case ADDR_EXPR:
2723e4b17023SJohn Marino {
2724e4b17023SJohn Marino tree tem;
2725e4b17023SJohn Marino
2726e4b17023SJohn Marino gcc_assert (is_gimple_address (t));
2727e4b17023SJohn Marino
2728e4b17023SJohn Marino /* Skip any references (they will be checked when we recurse down the
2729e4b17023SJohn Marino tree) and ensure that any variable used as a prefix is marked
2730e4b17023SJohn Marino addressable. */
2731e4b17023SJohn Marino for (x = TREE_OPERAND (t, 0);
2732e4b17023SJohn Marino handled_component_p (x);
2733e4b17023SJohn Marino x = TREE_OPERAND (x, 0))
2734e4b17023SJohn Marino ;
2735e4b17023SJohn Marino
2736e4b17023SJohn Marino if ((tem = verify_address (t, x)))
2737e4b17023SJohn Marino return tem;
2738e4b17023SJohn Marino
2739e4b17023SJohn Marino if (!(TREE_CODE (x) == VAR_DECL
2740e4b17023SJohn Marino || TREE_CODE (x) == PARM_DECL
2741e4b17023SJohn Marino || TREE_CODE (x) == RESULT_DECL))
2742e4b17023SJohn Marino return NULL;
2743e4b17023SJohn Marino
2744e4b17023SJohn Marino if (!TREE_ADDRESSABLE (x))
2745e4b17023SJohn Marino {
2746e4b17023SJohn Marino error ("address taken, but ADDRESSABLE bit not set");
2747e4b17023SJohn Marino return x;
2748e4b17023SJohn Marino }
2749e4b17023SJohn Marino
2750e4b17023SJohn Marino break;
2751e4b17023SJohn Marino }
2752e4b17023SJohn Marino
2753e4b17023SJohn Marino case COND_EXPR:
2754e4b17023SJohn Marino x = COND_EXPR_COND (t);
2755e4b17023SJohn Marino if (!INTEGRAL_TYPE_P (TREE_TYPE (x)))
2756e4b17023SJohn Marino {
2757e4b17023SJohn Marino error ("non-integral used in condition");
2758e4b17023SJohn Marino return x;
2759e4b17023SJohn Marino }
2760e4b17023SJohn Marino if (!is_gimple_condexpr (x))
2761e4b17023SJohn Marino {
2762e4b17023SJohn Marino error ("invalid conditional operand");
2763e4b17023SJohn Marino return x;
2764e4b17023SJohn Marino }
2765e4b17023SJohn Marino break;
2766e4b17023SJohn Marino
2767e4b17023SJohn Marino case NON_LVALUE_EXPR:
2768e4b17023SJohn Marino case TRUTH_NOT_EXPR:
2769e4b17023SJohn Marino gcc_unreachable ();
2770e4b17023SJohn Marino
2771e4b17023SJohn Marino CASE_CONVERT:
2772e4b17023SJohn Marino case FIX_TRUNC_EXPR:
2773e4b17023SJohn Marino case FLOAT_EXPR:
2774e4b17023SJohn Marino case NEGATE_EXPR:
2775e4b17023SJohn Marino case ABS_EXPR:
2776e4b17023SJohn Marino case BIT_NOT_EXPR:
2777e4b17023SJohn Marino CHECK_OP (0, "invalid operand to unary operator");
2778e4b17023SJohn Marino break;
2779e4b17023SJohn Marino
2780e4b17023SJohn Marino case REALPART_EXPR:
2781e4b17023SJohn Marino case IMAGPART_EXPR:
2782e4b17023SJohn Marino case COMPONENT_REF:
2783e4b17023SJohn Marino case ARRAY_REF:
2784e4b17023SJohn Marino case ARRAY_RANGE_REF:
2785e4b17023SJohn Marino case BIT_FIELD_REF:
2786e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
2787e4b17023SJohn Marino /* We have a nest of references. Verify that each of the operands
2788e4b17023SJohn Marino that determine where to reference is either a constant or a variable,
2789e4b17023SJohn Marino verify that the base is valid, and then show we've already checked
2790e4b17023SJohn Marino the subtrees. */
2791e4b17023SJohn Marino while (handled_component_p (t))
2792e4b17023SJohn Marino {
2793e4b17023SJohn Marino if (TREE_CODE (t) == COMPONENT_REF && TREE_OPERAND (t, 2))
2794e4b17023SJohn Marino CHECK_OP (2, "invalid COMPONENT_REF offset operator");
2795e4b17023SJohn Marino else if (TREE_CODE (t) == ARRAY_REF
2796e4b17023SJohn Marino || TREE_CODE (t) == ARRAY_RANGE_REF)
2797e4b17023SJohn Marino {
2798e4b17023SJohn Marino CHECK_OP (1, "invalid array index");
2799e4b17023SJohn Marino if (TREE_OPERAND (t, 2))
2800e4b17023SJohn Marino CHECK_OP (2, "invalid array lower bound");
2801e4b17023SJohn Marino if (TREE_OPERAND (t, 3))
2802e4b17023SJohn Marino CHECK_OP (3, "invalid array stride");
2803e4b17023SJohn Marino }
2804e4b17023SJohn Marino else if (TREE_CODE (t) == BIT_FIELD_REF)
2805e4b17023SJohn Marino {
2806e4b17023SJohn Marino if (!host_integerp (TREE_OPERAND (t, 1), 1)
2807e4b17023SJohn Marino || !host_integerp (TREE_OPERAND (t, 2), 1))
2808e4b17023SJohn Marino {
2809e4b17023SJohn Marino error ("invalid position or size operand to BIT_FIELD_REF");
2810e4b17023SJohn Marino return t;
2811e4b17023SJohn Marino }
2812e4b17023SJohn Marino else if (INTEGRAL_TYPE_P (TREE_TYPE (t))
2813e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (t))
2814e4b17023SJohn Marino != TREE_INT_CST_LOW (TREE_OPERAND (t, 1))))
2815e4b17023SJohn Marino {
2816e4b17023SJohn Marino error ("integral result type precision does not match "
2817e4b17023SJohn Marino "field size of BIT_FIELD_REF");
2818e4b17023SJohn Marino return t;
2819e4b17023SJohn Marino }
2820e4b17023SJohn Marino if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
2821e4b17023SJohn Marino && (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (t)))
2822e4b17023SJohn Marino != TREE_INT_CST_LOW (TREE_OPERAND (t, 1))))
2823e4b17023SJohn Marino {
2824e4b17023SJohn Marino error ("mode precision of non-integral result does not "
2825e4b17023SJohn Marino "match field size of BIT_FIELD_REF");
2826e4b17023SJohn Marino return t;
2827e4b17023SJohn Marino }
2828e4b17023SJohn Marino }
2829e4b17023SJohn Marino
2830e4b17023SJohn Marino t = TREE_OPERAND (t, 0);
2831e4b17023SJohn Marino }
2832e4b17023SJohn Marino
2833e4b17023SJohn Marino if (!is_gimple_min_invariant (t) && !is_gimple_lvalue (t))
2834e4b17023SJohn Marino {
2835e4b17023SJohn Marino error ("invalid reference prefix");
2836e4b17023SJohn Marino return t;
2837e4b17023SJohn Marino }
2838e4b17023SJohn Marino *walk_subtrees = 0;
2839e4b17023SJohn Marino break;
2840e4b17023SJohn Marino case PLUS_EXPR:
2841e4b17023SJohn Marino case MINUS_EXPR:
2842e4b17023SJohn Marino /* PLUS_EXPR and MINUS_EXPR don't work on pointers, they should be done using
2843e4b17023SJohn Marino POINTER_PLUS_EXPR. */
2844e4b17023SJohn Marino if (POINTER_TYPE_P (TREE_TYPE (t)))
2845e4b17023SJohn Marino {
2846e4b17023SJohn Marino error ("invalid operand to plus/minus, type is a pointer");
2847e4b17023SJohn Marino return t;
2848e4b17023SJohn Marino }
2849e4b17023SJohn Marino CHECK_OP (0, "invalid operand to binary operator");
2850e4b17023SJohn Marino CHECK_OP (1, "invalid operand to binary operator");
2851e4b17023SJohn Marino break;
2852e4b17023SJohn Marino
2853e4b17023SJohn Marino case POINTER_PLUS_EXPR:
2854e4b17023SJohn Marino /* Check to make sure the first operand is a pointer or reference type. */
2855e4b17023SJohn Marino if (!POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
2856e4b17023SJohn Marino {
2857e4b17023SJohn Marino error ("invalid operand to pointer plus, first operand is not a pointer");
2858e4b17023SJohn Marino return t;
2859e4b17023SJohn Marino }
2860e4b17023SJohn Marino /* Check to make sure the second operand is a ptrofftype. */
2861e4b17023SJohn Marino if (!ptrofftype_p (TREE_TYPE (TREE_OPERAND (t, 1))))
2862e4b17023SJohn Marino {
2863e4b17023SJohn Marino error ("invalid operand to pointer plus, second operand is not an "
2864e4b17023SJohn Marino "integer type of appropriate width");
2865e4b17023SJohn Marino return t;
2866e4b17023SJohn Marino }
2867e4b17023SJohn Marino /* FALLTHROUGH */
2868e4b17023SJohn Marino case LT_EXPR:
2869e4b17023SJohn Marino case LE_EXPR:
2870e4b17023SJohn Marino case GT_EXPR:
2871e4b17023SJohn Marino case GE_EXPR:
2872e4b17023SJohn Marino case EQ_EXPR:
2873e4b17023SJohn Marino case NE_EXPR:
2874e4b17023SJohn Marino case UNORDERED_EXPR:
2875e4b17023SJohn Marino case ORDERED_EXPR:
2876e4b17023SJohn Marino case UNLT_EXPR:
2877e4b17023SJohn Marino case UNLE_EXPR:
2878e4b17023SJohn Marino case UNGT_EXPR:
2879e4b17023SJohn Marino case UNGE_EXPR:
2880e4b17023SJohn Marino case UNEQ_EXPR:
2881e4b17023SJohn Marino case LTGT_EXPR:
2882e4b17023SJohn Marino case MULT_EXPR:
2883e4b17023SJohn Marino case TRUNC_DIV_EXPR:
2884e4b17023SJohn Marino case CEIL_DIV_EXPR:
2885e4b17023SJohn Marino case FLOOR_DIV_EXPR:
2886e4b17023SJohn Marino case ROUND_DIV_EXPR:
2887e4b17023SJohn Marino case TRUNC_MOD_EXPR:
2888e4b17023SJohn Marino case CEIL_MOD_EXPR:
2889e4b17023SJohn Marino case FLOOR_MOD_EXPR:
2890e4b17023SJohn Marino case ROUND_MOD_EXPR:
2891e4b17023SJohn Marino case RDIV_EXPR:
2892e4b17023SJohn Marino case EXACT_DIV_EXPR:
2893e4b17023SJohn Marino case MIN_EXPR:
2894e4b17023SJohn Marino case MAX_EXPR:
2895e4b17023SJohn Marino case LSHIFT_EXPR:
2896e4b17023SJohn Marino case RSHIFT_EXPR:
2897e4b17023SJohn Marino case LROTATE_EXPR:
2898e4b17023SJohn Marino case RROTATE_EXPR:
2899e4b17023SJohn Marino case BIT_IOR_EXPR:
2900e4b17023SJohn Marino case BIT_XOR_EXPR:
2901e4b17023SJohn Marino case BIT_AND_EXPR:
2902e4b17023SJohn Marino CHECK_OP (0, "invalid operand to binary operator");
2903e4b17023SJohn Marino CHECK_OP (1, "invalid operand to binary operator");
2904e4b17023SJohn Marino break;
2905e4b17023SJohn Marino
2906e4b17023SJohn Marino case CONSTRUCTOR:
2907e4b17023SJohn Marino if (TREE_CONSTANT (t) && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
2908e4b17023SJohn Marino *walk_subtrees = 0;
2909e4b17023SJohn Marino break;
2910e4b17023SJohn Marino
2911e4b17023SJohn Marino case CASE_LABEL_EXPR:
2912e4b17023SJohn Marino if (CASE_CHAIN (t))
2913e4b17023SJohn Marino {
2914e4b17023SJohn Marino error ("invalid CASE_CHAIN");
2915e4b17023SJohn Marino return t;
2916e4b17023SJohn Marino }
2917e4b17023SJohn Marino break;
2918e4b17023SJohn Marino
2919e4b17023SJohn Marino default:
2920e4b17023SJohn Marino break;
2921e4b17023SJohn Marino }
2922e4b17023SJohn Marino return NULL;
2923e4b17023SJohn Marino
2924e4b17023SJohn Marino #undef CHECK_OP
2925e4b17023SJohn Marino }
2926e4b17023SJohn Marino
2927e4b17023SJohn Marino
2928e4b17023SJohn Marino /* Verify if EXPR is either a GIMPLE ID or a GIMPLE indirect reference.
2929e4b17023SJohn Marino Returns true if there is an error, otherwise false. */
2930e4b17023SJohn Marino
2931e4b17023SJohn Marino static bool
verify_types_in_gimple_min_lval(tree expr)2932e4b17023SJohn Marino verify_types_in_gimple_min_lval (tree expr)
2933e4b17023SJohn Marino {
2934e4b17023SJohn Marino tree op;
2935e4b17023SJohn Marino
2936e4b17023SJohn Marino if (is_gimple_id (expr))
2937e4b17023SJohn Marino return false;
2938e4b17023SJohn Marino
2939e4b17023SJohn Marino if (TREE_CODE (expr) != TARGET_MEM_REF
2940e4b17023SJohn Marino && TREE_CODE (expr) != MEM_REF)
2941e4b17023SJohn Marino {
2942e4b17023SJohn Marino error ("invalid expression for min lvalue");
2943e4b17023SJohn Marino return true;
2944e4b17023SJohn Marino }
2945e4b17023SJohn Marino
2946e4b17023SJohn Marino /* TARGET_MEM_REFs are strange beasts. */
2947e4b17023SJohn Marino if (TREE_CODE (expr) == TARGET_MEM_REF)
2948e4b17023SJohn Marino return false;
2949e4b17023SJohn Marino
2950e4b17023SJohn Marino op = TREE_OPERAND (expr, 0);
2951e4b17023SJohn Marino if (!is_gimple_val (op))
2952e4b17023SJohn Marino {
2953e4b17023SJohn Marino error ("invalid operand in indirect reference");
2954e4b17023SJohn Marino debug_generic_stmt (op);
2955e4b17023SJohn Marino return true;
2956e4b17023SJohn Marino }
2957e4b17023SJohn Marino /* Memory references now generally can involve a value conversion. */
2958e4b17023SJohn Marino
2959e4b17023SJohn Marino return false;
2960e4b17023SJohn Marino }
2961e4b17023SJohn Marino
2962e4b17023SJohn Marino /* Verify if EXPR is a valid GIMPLE reference expression. If
2963e4b17023SJohn Marino REQUIRE_LVALUE is true verifies it is an lvalue. Returns true
2964e4b17023SJohn Marino if there is an error, otherwise false. */
2965e4b17023SJohn Marino
2966e4b17023SJohn Marino static bool
verify_types_in_gimple_reference(tree expr,bool require_lvalue)2967e4b17023SJohn Marino verify_types_in_gimple_reference (tree expr, bool require_lvalue)
2968e4b17023SJohn Marino {
2969e4b17023SJohn Marino while (handled_component_p (expr))
2970e4b17023SJohn Marino {
2971e4b17023SJohn Marino tree op = TREE_OPERAND (expr, 0);
2972e4b17023SJohn Marino
2973e4b17023SJohn Marino if (TREE_CODE (expr) == ARRAY_REF
2974e4b17023SJohn Marino || TREE_CODE (expr) == ARRAY_RANGE_REF)
2975e4b17023SJohn Marino {
2976e4b17023SJohn Marino if (!is_gimple_val (TREE_OPERAND (expr, 1))
2977e4b17023SJohn Marino || (TREE_OPERAND (expr, 2)
2978e4b17023SJohn Marino && !is_gimple_val (TREE_OPERAND (expr, 2)))
2979e4b17023SJohn Marino || (TREE_OPERAND (expr, 3)
2980e4b17023SJohn Marino && !is_gimple_val (TREE_OPERAND (expr, 3))))
2981e4b17023SJohn Marino {
2982e4b17023SJohn Marino error ("invalid operands to array reference");
2983e4b17023SJohn Marino debug_generic_stmt (expr);
2984e4b17023SJohn Marino return true;
2985e4b17023SJohn Marino }
2986e4b17023SJohn Marino }
2987e4b17023SJohn Marino
2988e4b17023SJohn Marino /* Verify if the reference array element types are compatible. */
2989e4b17023SJohn Marino if (TREE_CODE (expr) == ARRAY_REF
2990e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (expr),
2991e4b17023SJohn Marino TREE_TYPE (TREE_TYPE (op))))
2992e4b17023SJohn Marino {
2993e4b17023SJohn Marino error ("type mismatch in array reference");
2994e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (expr));
2995e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
2996e4b17023SJohn Marino return true;
2997e4b17023SJohn Marino }
2998e4b17023SJohn Marino if (TREE_CODE (expr) == ARRAY_RANGE_REF
2999e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (TREE_TYPE (expr)),
3000e4b17023SJohn Marino TREE_TYPE (TREE_TYPE (op))))
3001e4b17023SJohn Marino {
3002e4b17023SJohn Marino error ("type mismatch in array range reference");
3003e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (TREE_TYPE (expr)));
3004e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
3005e4b17023SJohn Marino return true;
3006e4b17023SJohn Marino }
3007e4b17023SJohn Marino
3008e4b17023SJohn Marino if ((TREE_CODE (expr) == REALPART_EXPR
3009e4b17023SJohn Marino || TREE_CODE (expr) == IMAGPART_EXPR)
3010e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (expr),
3011e4b17023SJohn Marino TREE_TYPE (TREE_TYPE (op))))
3012e4b17023SJohn Marino {
3013e4b17023SJohn Marino error ("type mismatch in real/imagpart reference");
3014e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (expr));
3015e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
3016e4b17023SJohn Marino return true;
3017e4b17023SJohn Marino }
3018e4b17023SJohn Marino
3019e4b17023SJohn Marino if (TREE_CODE (expr) == COMPONENT_REF
3020e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (expr),
3021e4b17023SJohn Marino TREE_TYPE (TREE_OPERAND (expr, 1))))
3022e4b17023SJohn Marino {
3023e4b17023SJohn Marino error ("type mismatch in component reference");
3024e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (expr));
3025e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (TREE_OPERAND (expr, 1)));
3026e4b17023SJohn Marino return true;
3027e4b17023SJohn Marino }
3028e4b17023SJohn Marino
3029e4b17023SJohn Marino if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
3030e4b17023SJohn Marino {
3031e4b17023SJohn Marino /* For VIEW_CONVERT_EXPRs which are allowed here too, we only check
3032e4b17023SJohn Marino that their operand is not an SSA name or an invariant when
3033e4b17023SJohn Marino requiring an lvalue (this usually means there is a SRA or IPA-SRA
3034e4b17023SJohn Marino bug). Otherwise there is nothing to verify, gross mismatches at
3035e4b17023SJohn Marino most invoke undefined behavior. */
3036e4b17023SJohn Marino if (require_lvalue
3037e4b17023SJohn Marino && (TREE_CODE (op) == SSA_NAME
3038e4b17023SJohn Marino || is_gimple_min_invariant (op)))
3039e4b17023SJohn Marino {
3040e4b17023SJohn Marino error ("conversion of an SSA_NAME on the left hand side");
3041e4b17023SJohn Marino debug_generic_stmt (expr);
3042e4b17023SJohn Marino return true;
3043e4b17023SJohn Marino }
3044e4b17023SJohn Marino else if (TREE_CODE (op) == SSA_NAME
3045e4b17023SJohn Marino && TYPE_SIZE (TREE_TYPE (expr)) != TYPE_SIZE (TREE_TYPE (op)))
3046e4b17023SJohn Marino {
3047e4b17023SJohn Marino error ("conversion of register to a different size");
3048e4b17023SJohn Marino debug_generic_stmt (expr);
3049e4b17023SJohn Marino return true;
3050e4b17023SJohn Marino }
3051e4b17023SJohn Marino else if (!handled_component_p (op))
3052e4b17023SJohn Marino return false;
3053e4b17023SJohn Marino }
3054e4b17023SJohn Marino
3055e4b17023SJohn Marino expr = op;
3056e4b17023SJohn Marino }
3057e4b17023SJohn Marino
3058e4b17023SJohn Marino if (TREE_CODE (expr) == MEM_REF)
3059e4b17023SJohn Marino {
3060e4b17023SJohn Marino if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)))
3061e4b17023SJohn Marino {
3062e4b17023SJohn Marino error ("invalid address operand in MEM_REF");
3063e4b17023SJohn Marino debug_generic_stmt (expr);
3064e4b17023SJohn Marino return true;
3065e4b17023SJohn Marino }
3066e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
3067e4b17023SJohn Marino || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
3068e4b17023SJohn Marino {
3069e4b17023SJohn Marino error ("invalid offset operand in MEM_REF");
3070e4b17023SJohn Marino debug_generic_stmt (expr);
3071e4b17023SJohn Marino return true;
3072e4b17023SJohn Marino }
3073e4b17023SJohn Marino }
3074e4b17023SJohn Marino else if (TREE_CODE (expr) == TARGET_MEM_REF)
3075e4b17023SJohn Marino {
3076e4b17023SJohn Marino if (!TMR_BASE (expr)
3077e4b17023SJohn Marino || !is_gimple_mem_ref_addr (TMR_BASE (expr)))
3078e4b17023SJohn Marino {
3079e4b17023SJohn Marino error ("invalid address operand in TARGET_MEM_REF");
3080e4b17023SJohn Marino return true;
3081e4b17023SJohn Marino }
3082e4b17023SJohn Marino if (!TMR_OFFSET (expr)
3083e4b17023SJohn Marino || TREE_CODE (TMR_OFFSET (expr)) != INTEGER_CST
3084e4b17023SJohn Marino || !POINTER_TYPE_P (TREE_TYPE (TMR_OFFSET (expr))))
3085e4b17023SJohn Marino {
3086e4b17023SJohn Marino error ("invalid offset operand in TARGET_MEM_REF");
3087e4b17023SJohn Marino debug_generic_stmt (expr);
3088e4b17023SJohn Marino return true;
3089e4b17023SJohn Marino }
3090e4b17023SJohn Marino }
3091e4b17023SJohn Marino
3092e4b17023SJohn Marino return ((require_lvalue || !is_gimple_min_invariant (expr))
3093e4b17023SJohn Marino && verify_types_in_gimple_min_lval (expr));
3094e4b17023SJohn Marino }
3095e4b17023SJohn Marino
3096e4b17023SJohn Marino /* Returns true if there is one pointer type in TYPE_POINTER_TO (SRC_OBJ)
3097e4b17023SJohn Marino list of pointer-to types that is trivially convertible to DEST. */
3098e4b17023SJohn Marino
3099e4b17023SJohn Marino static bool
one_pointer_to_useless_type_conversion_p(tree dest,tree src_obj)3100e4b17023SJohn Marino one_pointer_to_useless_type_conversion_p (tree dest, tree src_obj)
3101e4b17023SJohn Marino {
3102e4b17023SJohn Marino tree src;
3103e4b17023SJohn Marino
3104e4b17023SJohn Marino if (!TYPE_POINTER_TO (src_obj))
3105e4b17023SJohn Marino return true;
3106e4b17023SJohn Marino
3107e4b17023SJohn Marino for (src = TYPE_POINTER_TO (src_obj); src; src = TYPE_NEXT_PTR_TO (src))
3108e4b17023SJohn Marino if (useless_type_conversion_p (dest, src))
3109e4b17023SJohn Marino return true;
3110e4b17023SJohn Marino
3111e4b17023SJohn Marino return false;
3112e4b17023SJohn Marino }
3113e4b17023SJohn Marino
3114e4b17023SJohn Marino /* Return true if TYPE1 is a fixed-point type and if conversions to and
3115e4b17023SJohn Marino from TYPE2 can be handled by FIXED_CONVERT_EXPR. */
3116e4b17023SJohn Marino
3117e4b17023SJohn Marino static bool
valid_fixed_convert_types_p(tree type1,tree type2)3118e4b17023SJohn Marino valid_fixed_convert_types_p (tree type1, tree type2)
3119e4b17023SJohn Marino {
3120e4b17023SJohn Marino return (FIXED_POINT_TYPE_P (type1)
3121e4b17023SJohn Marino && (INTEGRAL_TYPE_P (type2)
3122e4b17023SJohn Marino || SCALAR_FLOAT_TYPE_P (type2)
3123e4b17023SJohn Marino || FIXED_POINT_TYPE_P (type2)));
3124e4b17023SJohn Marino }
3125e4b17023SJohn Marino
3126e4b17023SJohn Marino /* Verify the contents of a GIMPLE_CALL STMT. Returns true when there
3127e4b17023SJohn Marino is a problem, otherwise false. */
3128e4b17023SJohn Marino
3129e4b17023SJohn Marino static bool
verify_gimple_call(gimple stmt)3130e4b17023SJohn Marino verify_gimple_call (gimple stmt)
3131e4b17023SJohn Marino {
3132e4b17023SJohn Marino tree fn = gimple_call_fn (stmt);
3133e4b17023SJohn Marino tree fntype, fndecl;
3134e4b17023SJohn Marino unsigned i;
3135e4b17023SJohn Marino
3136e4b17023SJohn Marino if (gimple_call_internal_p (stmt))
3137e4b17023SJohn Marino {
3138e4b17023SJohn Marino if (fn)
3139e4b17023SJohn Marino {
3140e4b17023SJohn Marino error ("gimple call has two targets");
3141e4b17023SJohn Marino debug_generic_stmt (fn);
3142e4b17023SJohn Marino return true;
3143e4b17023SJohn Marino }
3144e4b17023SJohn Marino }
3145e4b17023SJohn Marino else
3146e4b17023SJohn Marino {
3147e4b17023SJohn Marino if (!fn)
3148e4b17023SJohn Marino {
3149e4b17023SJohn Marino error ("gimple call has no target");
3150e4b17023SJohn Marino return true;
3151e4b17023SJohn Marino }
3152e4b17023SJohn Marino }
3153e4b17023SJohn Marino
3154e4b17023SJohn Marino if (fn && !is_gimple_call_addr (fn))
3155e4b17023SJohn Marino {
3156e4b17023SJohn Marino error ("invalid function in gimple call");
3157e4b17023SJohn Marino debug_generic_stmt (fn);
3158e4b17023SJohn Marino return true;
3159e4b17023SJohn Marino }
3160e4b17023SJohn Marino
3161e4b17023SJohn Marino if (fn
3162e4b17023SJohn Marino && (!POINTER_TYPE_P (TREE_TYPE (fn))
3163e4b17023SJohn Marino || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
3164e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE)))
3165e4b17023SJohn Marino {
3166e4b17023SJohn Marino error ("non-function in gimple call");
3167e4b17023SJohn Marino return true;
3168e4b17023SJohn Marino }
3169e4b17023SJohn Marino
3170e4b17023SJohn Marino fndecl = gimple_call_fndecl (stmt);
3171e4b17023SJohn Marino if (fndecl
3172e4b17023SJohn Marino && TREE_CODE (fndecl) == FUNCTION_DECL
3173e4b17023SJohn Marino && DECL_LOOPING_CONST_OR_PURE_P (fndecl)
3174e4b17023SJohn Marino && !DECL_PURE_P (fndecl)
3175e4b17023SJohn Marino && !TREE_READONLY (fndecl))
3176e4b17023SJohn Marino {
3177e4b17023SJohn Marino error ("invalid pure const state for function");
3178e4b17023SJohn Marino return true;
3179e4b17023SJohn Marino }
3180e4b17023SJohn Marino
3181e4b17023SJohn Marino if (gimple_call_lhs (stmt)
3182e4b17023SJohn Marino && (!is_gimple_lvalue (gimple_call_lhs (stmt))
3183e4b17023SJohn Marino || verify_types_in_gimple_reference (gimple_call_lhs (stmt), true)))
3184e4b17023SJohn Marino {
3185e4b17023SJohn Marino error ("invalid LHS in gimple call");
3186e4b17023SJohn Marino return true;
3187e4b17023SJohn Marino }
3188e4b17023SJohn Marino
3189e4b17023SJohn Marino if (gimple_call_lhs (stmt) && gimple_call_noreturn_p (stmt))
3190e4b17023SJohn Marino {
3191e4b17023SJohn Marino error ("LHS in noreturn call");
3192e4b17023SJohn Marino return true;
3193e4b17023SJohn Marino }
3194e4b17023SJohn Marino
3195e4b17023SJohn Marino fntype = gimple_call_fntype (stmt);
3196e4b17023SJohn Marino if (fntype
3197e4b17023SJohn Marino && gimple_call_lhs (stmt)
3198e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)),
3199e4b17023SJohn Marino TREE_TYPE (fntype))
3200e4b17023SJohn Marino /* ??? At least C++ misses conversions at assignments from
3201e4b17023SJohn Marino void * call results.
3202e4b17023SJohn Marino ??? Java is completely off. Especially with functions
3203e4b17023SJohn Marino returning java.lang.Object.
3204e4b17023SJohn Marino For now simply allow arbitrary pointer type conversions. */
3205e4b17023SJohn Marino && !(POINTER_TYPE_P (TREE_TYPE (gimple_call_lhs (stmt)))
3206e4b17023SJohn Marino && POINTER_TYPE_P (TREE_TYPE (fntype))))
3207e4b17023SJohn Marino {
3208e4b17023SJohn Marino error ("invalid conversion in gimple call");
3209e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (gimple_call_lhs (stmt)));
3210e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (fntype));
3211e4b17023SJohn Marino return true;
3212e4b17023SJohn Marino }
3213e4b17023SJohn Marino
3214e4b17023SJohn Marino if (gimple_call_chain (stmt)
3215e4b17023SJohn Marino && !is_gimple_val (gimple_call_chain (stmt)))
3216e4b17023SJohn Marino {
3217e4b17023SJohn Marino error ("invalid static chain in gimple call");
3218e4b17023SJohn Marino debug_generic_stmt (gimple_call_chain (stmt));
3219e4b17023SJohn Marino return true;
3220e4b17023SJohn Marino }
3221e4b17023SJohn Marino
3222e4b17023SJohn Marino /* If there is a static chain argument, this should not be an indirect
3223e4b17023SJohn Marino call, and the decl should have DECL_STATIC_CHAIN set. */
3224e4b17023SJohn Marino if (gimple_call_chain (stmt))
3225e4b17023SJohn Marino {
3226e4b17023SJohn Marino if (!gimple_call_fndecl (stmt))
3227e4b17023SJohn Marino {
3228e4b17023SJohn Marino error ("static chain in indirect gimple call");
3229e4b17023SJohn Marino return true;
3230e4b17023SJohn Marino }
3231e4b17023SJohn Marino fn = TREE_OPERAND (fn, 0);
3232e4b17023SJohn Marino
3233e4b17023SJohn Marino if (!DECL_STATIC_CHAIN (fn))
3234e4b17023SJohn Marino {
3235e4b17023SJohn Marino error ("static chain with function that doesn%'t use one");
3236e4b17023SJohn Marino return true;
3237e4b17023SJohn Marino }
3238e4b17023SJohn Marino }
3239e4b17023SJohn Marino
3240e4b17023SJohn Marino /* ??? The C frontend passes unpromoted arguments in case it
3241e4b17023SJohn Marino didn't see a function declaration before the call. So for now
3242e4b17023SJohn Marino leave the call arguments mostly unverified. Once we gimplify
3243e4b17023SJohn Marino unit-at-a-time we have a chance to fix this. */
3244e4b17023SJohn Marino
3245e4b17023SJohn Marino for (i = 0; i < gimple_call_num_args (stmt); ++i)
3246e4b17023SJohn Marino {
3247e4b17023SJohn Marino tree arg = gimple_call_arg (stmt, i);
3248e4b17023SJohn Marino if ((is_gimple_reg_type (TREE_TYPE (arg))
3249e4b17023SJohn Marino && !is_gimple_val (arg))
3250e4b17023SJohn Marino || (!is_gimple_reg_type (TREE_TYPE (arg))
3251e4b17023SJohn Marino && !is_gimple_lvalue (arg)))
3252e4b17023SJohn Marino {
3253e4b17023SJohn Marino error ("invalid argument to gimple call");
3254e4b17023SJohn Marino debug_generic_expr (arg);
3255e4b17023SJohn Marino return true;
3256e4b17023SJohn Marino }
3257e4b17023SJohn Marino }
3258e4b17023SJohn Marino
3259e4b17023SJohn Marino return false;
3260e4b17023SJohn Marino }
3261e4b17023SJohn Marino
3262e4b17023SJohn Marino /* Verifies the gimple comparison with the result type TYPE and
3263e4b17023SJohn Marino the operands OP0 and OP1. */
3264e4b17023SJohn Marino
3265e4b17023SJohn Marino static bool
verify_gimple_comparison(tree type,tree op0,tree op1)3266e4b17023SJohn Marino verify_gimple_comparison (tree type, tree op0, tree op1)
3267e4b17023SJohn Marino {
3268e4b17023SJohn Marino tree op0_type = TREE_TYPE (op0);
3269e4b17023SJohn Marino tree op1_type = TREE_TYPE (op1);
3270e4b17023SJohn Marino
3271e4b17023SJohn Marino if (!is_gimple_val (op0) || !is_gimple_val (op1))
3272e4b17023SJohn Marino {
3273e4b17023SJohn Marino error ("invalid operands in gimple comparison");
3274e4b17023SJohn Marino return true;
3275e4b17023SJohn Marino }
3276e4b17023SJohn Marino
3277e4b17023SJohn Marino /* For comparisons we do not have the operations type as the
3278e4b17023SJohn Marino effective type the comparison is carried out in. Instead
3279e4b17023SJohn Marino we require that either the first operand is trivially
3280e4b17023SJohn Marino convertible into the second, or the other way around.
3281e4b17023SJohn Marino Because we special-case pointers to void we allow
3282e4b17023SJohn Marino comparisons of pointers with the same mode as well. */
3283e4b17023SJohn Marino if (!useless_type_conversion_p (op0_type, op1_type)
3284e4b17023SJohn Marino && !useless_type_conversion_p (op1_type, op0_type)
3285e4b17023SJohn Marino && (!POINTER_TYPE_P (op0_type)
3286e4b17023SJohn Marino || !POINTER_TYPE_P (op1_type)
3287e4b17023SJohn Marino || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
3288e4b17023SJohn Marino {
3289e4b17023SJohn Marino error ("mismatching comparison operand types");
3290e4b17023SJohn Marino debug_generic_expr (op0_type);
3291e4b17023SJohn Marino debug_generic_expr (op1_type);
3292e4b17023SJohn Marino return true;
3293e4b17023SJohn Marino }
3294e4b17023SJohn Marino
3295e4b17023SJohn Marino /* The resulting type of a comparison may be an effective boolean type. */
3296e4b17023SJohn Marino if (INTEGRAL_TYPE_P (type)
3297e4b17023SJohn Marino && (TREE_CODE (type) == BOOLEAN_TYPE
3298e4b17023SJohn Marino || TYPE_PRECISION (type) == 1))
3299e4b17023SJohn Marino ;
3300e4b17023SJohn Marino /* Or an integer vector type with the same size and element count
3301e4b17023SJohn Marino as the comparison operand types. */
3302e4b17023SJohn Marino else if (TREE_CODE (type) == VECTOR_TYPE
3303e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
3304e4b17023SJohn Marino {
3305e4b17023SJohn Marino if (TREE_CODE (op0_type) != VECTOR_TYPE
3306e4b17023SJohn Marino || TREE_CODE (op1_type) != VECTOR_TYPE)
3307e4b17023SJohn Marino {
3308e4b17023SJohn Marino error ("non-vector operands in vector comparison");
3309e4b17023SJohn Marino debug_generic_expr (op0_type);
3310e4b17023SJohn Marino debug_generic_expr (op1_type);
3311e4b17023SJohn Marino return true;
3312e4b17023SJohn Marino }
3313e4b17023SJohn Marino
3314e4b17023SJohn Marino if (TYPE_VECTOR_SUBPARTS (type) != TYPE_VECTOR_SUBPARTS (op0_type)
3315e4b17023SJohn Marino || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type)))
3316e4b17023SJohn Marino != GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0_type)))))
3317e4b17023SJohn Marino {
3318e4b17023SJohn Marino error ("invalid vector comparison resulting type");
3319e4b17023SJohn Marino debug_generic_expr (type);
3320e4b17023SJohn Marino return true;
3321e4b17023SJohn Marino }
3322e4b17023SJohn Marino }
3323e4b17023SJohn Marino else
3324e4b17023SJohn Marino {
3325e4b17023SJohn Marino error ("bogus comparison result type");
3326e4b17023SJohn Marino debug_generic_expr (type);
3327e4b17023SJohn Marino return true;
3328e4b17023SJohn Marino }
3329e4b17023SJohn Marino
3330e4b17023SJohn Marino return false;
3331e4b17023SJohn Marino }
3332e4b17023SJohn Marino
3333e4b17023SJohn Marino /* Verify a gimple assignment statement STMT with an unary rhs.
3334e4b17023SJohn Marino Returns true if anything is wrong. */
3335e4b17023SJohn Marino
3336e4b17023SJohn Marino static bool
verify_gimple_assign_unary(gimple stmt)3337e4b17023SJohn Marino verify_gimple_assign_unary (gimple stmt)
3338e4b17023SJohn Marino {
3339e4b17023SJohn Marino enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
3340e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt);
3341e4b17023SJohn Marino tree lhs_type = TREE_TYPE (lhs);
3342e4b17023SJohn Marino tree rhs1 = gimple_assign_rhs1 (stmt);
3343e4b17023SJohn Marino tree rhs1_type = TREE_TYPE (rhs1);
3344e4b17023SJohn Marino
3345e4b17023SJohn Marino if (!is_gimple_reg (lhs))
3346e4b17023SJohn Marino {
3347e4b17023SJohn Marino error ("non-register as LHS of unary operation");
3348e4b17023SJohn Marino return true;
3349e4b17023SJohn Marino }
3350e4b17023SJohn Marino
3351e4b17023SJohn Marino if (!is_gimple_val (rhs1))
3352e4b17023SJohn Marino {
3353e4b17023SJohn Marino error ("invalid operand in unary operation");
3354e4b17023SJohn Marino return true;
3355e4b17023SJohn Marino }
3356e4b17023SJohn Marino
3357e4b17023SJohn Marino /* First handle conversions. */
3358e4b17023SJohn Marino switch (rhs_code)
3359e4b17023SJohn Marino {
3360e4b17023SJohn Marino CASE_CONVERT:
3361e4b17023SJohn Marino {
3362e4b17023SJohn Marino /* Allow conversions from pointer type to integral type only if
3363e4b17023SJohn Marino there is no sign or zero extension involved.
3364e4b17023SJohn Marino For targets were the precision of ptrofftype doesn't match that
3365e4b17023SJohn Marino of pointers we need to allow arbitrary conversions to ptrofftype. */
3366e4b17023SJohn Marino if ((POINTER_TYPE_P (lhs_type)
3367e4b17023SJohn Marino && INTEGRAL_TYPE_P (rhs1_type))
3368e4b17023SJohn Marino || (POINTER_TYPE_P (rhs1_type)
3369e4b17023SJohn Marino && INTEGRAL_TYPE_P (lhs_type)
3370e4b17023SJohn Marino && (TYPE_PRECISION (rhs1_type) >= TYPE_PRECISION (lhs_type)
3371e4b17023SJohn Marino || ptrofftype_p (sizetype))))
3372e4b17023SJohn Marino return false;
3373e4b17023SJohn Marino
3374e4b17023SJohn Marino /* Allow conversion from integer to offset type and vice versa. */
3375e4b17023SJohn Marino if ((TREE_CODE (lhs_type) == OFFSET_TYPE
3376e4b17023SJohn Marino && TREE_CODE (rhs1_type) == INTEGER_TYPE)
3377e4b17023SJohn Marino || (TREE_CODE (lhs_type) == INTEGER_TYPE
3378e4b17023SJohn Marino && TREE_CODE (rhs1_type) == OFFSET_TYPE))
3379e4b17023SJohn Marino return false;
3380e4b17023SJohn Marino
3381e4b17023SJohn Marino /* Otherwise assert we are converting between types of the
3382e4b17023SJohn Marino same kind. */
3383e4b17023SJohn Marino if (INTEGRAL_TYPE_P (lhs_type) != INTEGRAL_TYPE_P (rhs1_type))
3384e4b17023SJohn Marino {
3385e4b17023SJohn Marino error ("invalid types in nop conversion");
3386e4b17023SJohn Marino debug_generic_expr (lhs_type);
3387e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3388e4b17023SJohn Marino return true;
3389e4b17023SJohn Marino }
3390e4b17023SJohn Marino
3391e4b17023SJohn Marino return false;
3392e4b17023SJohn Marino }
3393e4b17023SJohn Marino
3394e4b17023SJohn Marino case ADDR_SPACE_CONVERT_EXPR:
3395e4b17023SJohn Marino {
3396e4b17023SJohn Marino if (!POINTER_TYPE_P (rhs1_type) || !POINTER_TYPE_P (lhs_type)
3397e4b17023SJohn Marino || (TYPE_ADDR_SPACE (TREE_TYPE (rhs1_type))
3398e4b17023SJohn Marino == TYPE_ADDR_SPACE (TREE_TYPE (lhs_type))))
3399e4b17023SJohn Marino {
3400e4b17023SJohn Marino error ("invalid types in address space conversion");
3401e4b17023SJohn Marino debug_generic_expr (lhs_type);
3402e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3403e4b17023SJohn Marino return true;
3404e4b17023SJohn Marino }
3405e4b17023SJohn Marino
3406e4b17023SJohn Marino return false;
3407e4b17023SJohn Marino }
3408e4b17023SJohn Marino
3409e4b17023SJohn Marino case FIXED_CONVERT_EXPR:
3410e4b17023SJohn Marino {
3411e4b17023SJohn Marino if (!valid_fixed_convert_types_p (lhs_type, rhs1_type)
3412e4b17023SJohn Marino && !valid_fixed_convert_types_p (rhs1_type, lhs_type))
3413e4b17023SJohn Marino {
3414e4b17023SJohn Marino error ("invalid types in fixed-point conversion");
3415e4b17023SJohn Marino debug_generic_expr (lhs_type);
3416e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3417e4b17023SJohn Marino return true;
3418e4b17023SJohn Marino }
3419e4b17023SJohn Marino
3420e4b17023SJohn Marino return false;
3421e4b17023SJohn Marino }
3422e4b17023SJohn Marino
3423e4b17023SJohn Marino case FLOAT_EXPR:
3424e4b17023SJohn Marino {
3425e4b17023SJohn Marino if ((!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
3426e4b17023SJohn Marino && (!VECTOR_INTEGER_TYPE_P (rhs1_type)
3427e4b17023SJohn Marino || !VECTOR_FLOAT_TYPE_P(lhs_type)))
3428e4b17023SJohn Marino {
3429e4b17023SJohn Marino error ("invalid types in conversion to floating point");
3430e4b17023SJohn Marino debug_generic_expr (lhs_type);
3431e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3432e4b17023SJohn Marino return true;
3433e4b17023SJohn Marino }
3434e4b17023SJohn Marino
3435e4b17023SJohn Marino return false;
3436e4b17023SJohn Marino }
3437e4b17023SJohn Marino
3438e4b17023SJohn Marino case FIX_TRUNC_EXPR:
3439e4b17023SJohn Marino {
3440e4b17023SJohn Marino if ((!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
3441e4b17023SJohn Marino && (!VECTOR_INTEGER_TYPE_P (lhs_type)
3442e4b17023SJohn Marino || !VECTOR_FLOAT_TYPE_P(rhs1_type)))
3443e4b17023SJohn Marino {
3444e4b17023SJohn Marino error ("invalid types in conversion to integer");
3445e4b17023SJohn Marino debug_generic_expr (lhs_type);
3446e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3447e4b17023SJohn Marino return true;
3448e4b17023SJohn Marino }
3449e4b17023SJohn Marino
3450e4b17023SJohn Marino return false;
3451e4b17023SJohn Marino }
3452e4b17023SJohn Marino
3453e4b17023SJohn Marino case VEC_UNPACK_HI_EXPR:
3454e4b17023SJohn Marino case VEC_UNPACK_LO_EXPR:
3455e4b17023SJohn Marino case REDUC_MAX_EXPR:
3456e4b17023SJohn Marino case REDUC_MIN_EXPR:
3457e4b17023SJohn Marino case REDUC_PLUS_EXPR:
3458e4b17023SJohn Marino case VEC_UNPACK_FLOAT_HI_EXPR:
3459e4b17023SJohn Marino case VEC_UNPACK_FLOAT_LO_EXPR:
3460e4b17023SJohn Marino /* FIXME. */
3461e4b17023SJohn Marino return false;
3462e4b17023SJohn Marino
3463e4b17023SJohn Marino case NEGATE_EXPR:
3464e4b17023SJohn Marino case ABS_EXPR:
3465e4b17023SJohn Marino case BIT_NOT_EXPR:
3466e4b17023SJohn Marino case PAREN_EXPR:
3467e4b17023SJohn Marino case NON_LVALUE_EXPR:
3468e4b17023SJohn Marino case CONJ_EXPR:
3469e4b17023SJohn Marino break;
3470e4b17023SJohn Marino
3471e4b17023SJohn Marino default:
3472e4b17023SJohn Marino gcc_unreachable ();
3473e4b17023SJohn Marino }
3474e4b17023SJohn Marino
3475e4b17023SJohn Marino /* For the remaining codes assert there is no conversion involved. */
3476e4b17023SJohn Marino if (!useless_type_conversion_p (lhs_type, rhs1_type))
3477e4b17023SJohn Marino {
3478e4b17023SJohn Marino error ("non-trivial conversion in unary operation");
3479e4b17023SJohn Marino debug_generic_expr (lhs_type);
3480e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3481e4b17023SJohn Marino return true;
3482e4b17023SJohn Marino }
3483e4b17023SJohn Marino
3484e4b17023SJohn Marino return false;
3485e4b17023SJohn Marino }
3486e4b17023SJohn Marino
3487e4b17023SJohn Marino /* Verify a gimple assignment statement STMT with a binary rhs.
3488e4b17023SJohn Marino Returns true if anything is wrong. */
3489e4b17023SJohn Marino
3490e4b17023SJohn Marino static bool
verify_gimple_assign_binary(gimple stmt)3491e4b17023SJohn Marino verify_gimple_assign_binary (gimple stmt)
3492e4b17023SJohn Marino {
3493e4b17023SJohn Marino enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
3494e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt);
3495e4b17023SJohn Marino tree lhs_type = TREE_TYPE (lhs);
3496e4b17023SJohn Marino tree rhs1 = gimple_assign_rhs1 (stmt);
3497e4b17023SJohn Marino tree rhs1_type = TREE_TYPE (rhs1);
3498e4b17023SJohn Marino tree rhs2 = gimple_assign_rhs2 (stmt);
3499e4b17023SJohn Marino tree rhs2_type = TREE_TYPE (rhs2);
3500e4b17023SJohn Marino
3501e4b17023SJohn Marino if (!is_gimple_reg (lhs))
3502e4b17023SJohn Marino {
3503e4b17023SJohn Marino error ("non-register as LHS of binary operation");
3504e4b17023SJohn Marino return true;
3505e4b17023SJohn Marino }
3506e4b17023SJohn Marino
3507e4b17023SJohn Marino if (!is_gimple_val (rhs1)
3508e4b17023SJohn Marino || !is_gimple_val (rhs2))
3509e4b17023SJohn Marino {
3510e4b17023SJohn Marino error ("invalid operands in binary operation");
3511e4b17023SJohn Marino return true;
3512e4b17023SJohn Marino }
3513e4b17023SJohn Marino
3514e4b17023SJohn Marino /* First handle operations that involve different types. */
3515e4b17023SJohn Marino switch (rhs_code)
3516e4b17023SJohn Marino {
3517e4b17023SJohn Marino case COMPLEX_EXPR:
3518e4b17023SJohn Marino {
3519e4b17023SJohn Marino if (TREE_CODE (lhs_type) != COMPLEX_TYPE
3520e4b17023SJohn Marino || !(INTEGRAL_TYPE_P (rhs1_type)
3521e4b17023SJohn Marino || SCALAR_FLOAT_TYPE_P (rhs1_type))
3522e4b17023SJohn Marino || !(INTEGRAL_TYPE_P (rhs2_type)
3523e4b17023SJohn Marino || SCALAR_FLOAT_TYPE_P (rhs2_type)))
3524e4b17023SJohn Marino {
3525e4b17023SJohn Marino error ("type mismatch in complex expression");
3526e4b17023SJohn Marino debug_generic_expr (lhs_type);
3527e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3528e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3529e4b17023SJohn Marino return true;
3530e4b17023SJohn Marino }
3531e4b17023SJohn Marino
3532e4b17023SJohn Marino return false;
3533e4b17023SJohn Marino }
3534e4b17023SJohn Marino
3535e4b17023SJohn Marino case LSHIFT_EXPR:
3536e4b17023SJohn Marino case RSHIFT_EXPR:
3537e4b17023SJohn Marino case LROTATE_EXPR:
3538e4b17023SJohn Marino case RROTATE_EXPR:
3539e4b17023SJohn Marino {
3540e4b17023SJohn Marino /* Shifts and rotates are ok on integral types, fixed point
3541e4b17023SJohn Marino types and integer vector types. */
3542e4b17023SJohn Marino if ((!INTEGRAL_TYPE_P (rhs1_type)
3543e4b17023SJohn Marino && !FIXED_POINT_TYPE_P (rhs1_type)
3544e4b17023SJohn Marino && !(TREE_CODE (rhs1_type) == VECTOR_TYPE
3545e4b17023SJohn Marino && INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))))
3546e4b17023SJohn Marino || (!INTEGRAL_TYPE_P (rhs2_type)
3547e4b17023SJohn Marino /* Vector shifts of vectors are also ok. */
3548e4b17023SJohn Marino && !(TREE_CODE (rhs1_type) == VECTOR_TYPE
3549e4b17023SJohn Marino && INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
3550e4b17023SJohn Marino && TREE_CODE (rhs2_type) == VECTOR_TYPE
3551e4b17023SJohn Marino && INTEGRAL_TYPE_P (TREE_TYPE (rhs2_type))))
3552e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs1_type))
3553e4b17023SJohn Marino {
3554e4b17023SJohn Marino error ("type mismatch in shift expression");
3555e4b17023SJohn Marino debug_generic_expr (lhs_type);
3556e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3557e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3558e4b17023SJohn Marino return true;
3559e4b17023SJohn Marino }
3560e4b17023SJohn Marino
3561e4b17023SJohn Marino return false;
3562e4b17023SJohn Marino }
3563e4b17023SJohn Marino
3564e4b17023SJohn Marino case VEC_LSHIFT_EXPR:
3565e4b17023SJohn Marino case VEC_RSHIFT_EXPR:
3566e4b17023SJohn Marino {
3567e4b17023SJohn Marino if (TREE_CODE (rhs1_type) != VECTOR_TYPE
3568e4b17023SJohn Marino || !(INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
3569e4b17023SJohn Marino || POINTER_TYPE_P (TREE_TYPE (rhs1_type))
3570e4b17023SJohn Marino || FIXED_POINT_TYPE_P (TREE_TYPE (rhs1_type))
3571e4b17023SJohn Marino || SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type)))
3572e4b17023SJohn Marino || (!INTEGRAL_TYPE_P (rhs2_type)
3573e4b17023SJohn Marino && (TREE_CODE (rhs2_type) != VECTOR_TYPE
3574e4b17023SJohn Marino || !INTEGRAL_TYPE_P (TREE_TYPE (rhs2_type))))
3575e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs1_type))
3576e4b17023SJohn Marino {
3577e4b17023SJohn Marino error ("type mismatch in vector shift expression");
3578e4b17023SJohn Marino debug_generic_expr (lhs_type);
3579e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3580e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3581e4b17023SJohn Marino return true;
3582e4b17023SJohn Marino }
3583e4b17023SJohn Marino /* For shifting a vector of non-integral components we
3584e4b17023SJohn Marino only allow shifting by a constant multiple of the element size. */
3585e4b17023SJohn Marino if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
3586e4b17023SJohn Marino && (TREE_CODE (rhs2) != INTEGER_CST
3587e4b17023SJohn Marino || !div_if_zero_remainder (EXACT_DIV_EXPR, rhs2,
3588e4b17023SJohn Marino TYPE_SIZE (TREE_TYPE (rhs1_type)))))
3589e4b17023SJohn Marino {
3590e4b17023SJohn Marino error ("non-element sized vector shift of floating point vector");
3591e4b17023SJohn Marino return true;
3592e4b17023SJohn Marino }
3593e4b17023SJohn Marino
3594e4b17023SJohn Marino return false;
3595e4b17023SJohn Marino }
3596e4b17023SJohn Marino
3597e4b17023SJohn Marino case WIDEN_LSHIFT_EXPR:
3598e4b17023SJohn Marino {
3599e4b17023SJohn Marino if (!INTEGRAL_TYPE_P (lhs_type)
3600e4b17023SJohn Marino || !INTEGRAL_TYPE_P (rhs1_type)
3601e4b17023SJohn Marino || TREE_CODE (rhs2) != INTEGER_CST
3602e4b17023SJohn Marino || (2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)))
3603e4b17023SJohn Marino {
3604e4b17023SJohn Marino error ("type mismatch in widening vector shift expression");
3605e4b17023SJohn Marino debug_generic_expr (lhs_type);
3606e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3607e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3608e4b17023SJohn Marino return true;
3609e4b17023SJohn Marino }
3610e4b17023SJohn Marino
3611e4b17023SJohn Marino return false;
3612e4b17023SJohn Marino }
3613e4b17023SJohn Marino
3614e4b17023SJohn Marino case VEC_WIDEN_LSHIFT_HI_EXPR:
3615e4b17023SJohn Marino case VEC_WIDEN_LSHIFT_LO_EXPR:
3616e4b17023SJohn Marino {
3617e4b17023SJohn Marino if (TREE_CODE (rhs1_type) != VECTOR_TYPE
3618e4b17023SJohn Marino || TREE_CODE (lhs_type) != VECTOR_TYPE
3619e4b17023SJohn Marino || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
3620e4b17023SJohn Marino || !INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))
3621e4b17023SJohn Marino || TREE_CODE (rhs2) != INTEGER_CST
3622e4b17023SJohn Marino || (2 * TYPE_PRECISION (TREE_TYPE (rhs1_type))
3623e4b17023SJohn Marino > TYPE_PRECISION (TREE_TYPE (lhs_type))))
3624e4b17023SJohn Marino {
3625e4b17023SJohn Marino error ("type mismatch in widening vector shift expression");
3626e4b17023SJohn Marino debug_generic_expr (lhs_type);
3627e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3628e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3629e4b17023SJohn Marino return true;
3630e4b17023SJohn Marino }
3631e4b17023SJohn Marino
3632e4b17023SJohn Marino return false;
3633e4b17023SJohn Marino }
3634e4b17023SJohn Marino
3635e4b17023SJohn Marino case PLUS_EXPR:
3636e4b17023SJohn Marino case MINUS_EXPR:
3637e4b17023SJohn Marino {
3638e4b17023SJohn Marino /* We use regular PLUS_EXPR and MINUS_EXPR for vectors.
3639e4b17023SJohn Marino ??? This just makes the checker happy and may not be what is
3640e4b17023SJohn Marino intended. */
3641e4b17023SJohn Marino if (TREE_CODE (lhs_type) == VECTOR_TYPE
3642e4b17023SJohn Marino && POINTER_TYPE_P (TREE_TYPE (lhs_type)))
3643e4b17023SJohn Marino {
3644e4b17023SJohn Marino if (TREE_CODE (rhs1_type) != VECTOR_TYPE
3645e4b17023SJohn Marino || TREE_CODE (rhs2_type) != VECTOR_TYPE)
3646e4b17023SJohn Marino {
3647e4b17023SJohn Marino error ("invalid non-vector operands to vector valued plus");
3648e4b17023SJohn Marino return true;
3649e4b17023SJohn Marino }
3650e4b17023SJohn Marino lhs_type = TREE_TYPE (lhs_type);
3651e4b17023SJohn Marino rhs1_type = TREE_TYPE (rhs1_type);
3652e4b17023SJohn Marino rhs2_type = TREE_TYPE (rhs2_type);
3653e4b17023SJohn Marino /* PLUS_EXPR is commutative, so we might end up canonicalizing
3654e4b17023SJohn Marino the pointer to 2nd place. */
3655e4b17023SJohn Marino if (POINTER_TYPE_P (rhs2_type))
3656e4b17023SJohn Marino {
3657e4b17023SJohn Marino tree tem = rhs1_type;
3658e4b17023SJohn Marino rhs1_type = rhs2_type;
3659e4b17023SJohn Marino rhs2_type = tem;
3660e4b17023SJohn Marino }
3661e4b17023SJohn Marino goto do_pointer_plus_expr_check;
3662e4b17023SJohn Marino }
3663e4b17023SJohn Marino if (POINTER_TYPE_P (lhs_type)
3664e4b17023SJohn Marino || POINTER_TYPE_P (rhs1_type)
3665e4b17023SJohn Marino || POINTER_TYPE_P (rhs2_type))
3666e4b17023SJohn Marino {
3667e4b17023SJohn Marino error ("invalid (pointer) operands to plus/minus");
3668e4b17023SJohn Marino return true;
3669e4b17023SJohn Marino }
3670e4b17023SJohn Marino
3671e4b17023SJohn Marino /* Continue with generic binary expression handling. */
3672e4b17023SJohn Marino break;
3673e4b17023SJohn Marino }
3674e4b17023SJohn Marino
3675e4b17023SJohn Marino case POINTER_PLUS_EXPR:
3676e4b17023SJohn Marino {
3677e4b17023SJohn Marino do_pointer_plus_expr_check:
3678e4b17023SJohn Marino if (!POINTER_TYPE_P (rhs1_type)
3679e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs1_type)
3680e4b17023SJohn Marino || !ptrofftype_p (rhs2_type))
3681e4b17023SJohn Marino {
3682e4b17023SJohn Marino error ("type mismatch in pointer plus expression");
3683e4b17023SJohn Marino debug_generic_stmt (lhs_type);
3684e4b17023SJohn Marino debug_generic_stmt (rhs1_type);
3685e4b17023SJohn Marino debug_generic_stmt (rhs2_type);
3686e4b17023SJohn Marino return true;
3687e4b17023SJohn Marino }
3688e4b17023SJohn Marino
3689e4b17023SJohn Marino return false;
3690e4b17023SJohn Marino }
3691e4b17023SJohn Marino
3692e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
3693e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
3694e4b17023SJohn Marino case TRUTH_AND_EXPR:
3695e4b17023SJohn Marino case TRUTH_OR_EXPR:
3696e4b17023SJohn Marino case TRUTH_XOR_EXPR:
3697e4b17023SJohn Marino
3698e4b17023SJohn Marino gcc_unreachable ();
3699e4b17023SJohn Marino
3700e4b17023SJohn Marino case LT_EXPR:
3701e4b17023SJohn Marino case LE_EXPR:
3702e4b17023SJohn Marino case GT_EXPR:
3703e4b17023SJohn Marino case GE_EXPR:
3704e4b17023SJohn Marino case EQ_EXPR:
3705e4b17023SJohn Marino case NE_EXPR:
3706e4b17023SJohn Marino case UNORDERED_EXPR:
3707e4b17023SJohn Marino case ORDERED_EXPR:
3708e4b17023SJohn Marino case UNLT_EXPR:
3709e4b17023SJohn Marino case UNLE_EXPR:
3710e4b17023SJohn Marino case UNGT_EXPR:
3711e4b17023SJohn Marino case UNGE_EXPR:
3712e4b17023SJohn Marino case UNEQ_EXPR:
3713e4b17023SJohn Marino case LTGT_EXPR:
3714e4b17023SJohn Marino /* Comparisons are also binary, but the result type is not
3715e4b17023SJohn Marino connected to the operand types. */
3716e4b17023SJohn Marino return verify_gimple_comparison (lhs_type, rhs1, rhs2);
3717e4b17023SJohn Marino
3718e4b17023SJohn Marino case WIDEN_MULT_EXPR:
3719e4b17023SJohn Marino if (TREE_CODE (lhs_type) != INTEGER_TYPE)
3720e4b17023SJohn Marino return true;
3721e4b17023SJohn Marino return ((2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type))
3722e4b17023SJohn Marino || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)));
3723e4b17023SJohn Marino
3724e4b17023SJohn Marino case WIDEN_SUM_EXPR:
3725e4b17023SJohn Marino case VEC_WIDEN_MULT_HI_EXPR:
3726e4b17023SJohn Marino case VEC_WIDEN_MULT_LO_EXPR:
3727e4b17023SJohn Marino case VEC_PACK_TRUNC_EXPR:
3728e4b17023SJohn Marino case VEC_PACK_SAT_EXPR:
3729e4b17023SJohn Marino case VEC_PACK_FIX_TRUNC_EXPR:
3730e4b17023SJohn Marino /* FIXME. */
3731e4b17023SJohn Marino return false;
3732e4b17023SJohn Marino
3733e4b17023SJohn Marino case MULT_EXPR:
3734e4b17023SJohn Marino case TRUNC_DIV_EXPR:
3735e4b17023SJohn Marino case CEIL_DIV_EXPR:
3736e4b17023SJohn Marino case FLOOR_DIV_EXPR:
3737e4b17023SJohn Marino case ROUND_DIV_EXPR:
3738e4b17023SJohn Marino case TRUNC_MOD_EXPR:
3739e4b17023SJohn Marino case CEIL_MOD_EXPR:
3740e4b17023SJohn Marino case FLOOR_MOD_EXPR:
3741e4b17023SJohn Marino case ROUND_MOD_EXPR:
3742e4b17023SJohn Marino case RDIV_EXPR:
3743e4b17023SJohn Marino case EXACT_DIV_EXPR:
3744e4b17023SJohn Marino case MIN_EXPR:
3745e4b17023SJohn Marino case MAX_EXPR:
3746e4b17023SJohn Marino case BIT_IOR_EXPR:
3747e4b17023SJohn Marino case BIT_XOR_EXPR:
3748e4b17023SJohn Marino case BIT_AND_EXPR:
3749e4b17023SJohn Marino /* Continue with generic binary expression handling. */
3750e4b17023SJohn Marino break;
3751e4b17023SJohn Marino
3752e4b17023SJohn Marino default:
3753e4b17023SJohn Marino gcc_unreachable ();
3754e4b17023SJohn Marino }
3755e4b17023SJohn Marino
3756e4b17023SJohn Marino if (!useless_type_conversion_p (lhs_type, rhs1_type)
3757e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs2_type))
3758e4b17023SJohn Marino {
3759e4b17023SJohn Marino error ("type mismatch in binary expression");
3760e4b17023SJohn Marino debug_generic_stmt (lhs_type);
3761e4b17023SJohn Marino debug_generic_stmt (rhs1_type);
3762e4b17023SJohn Marino debug_generic_stmt (rhs2_type);
3763e4b17023SJohn Marino return true;
3764e4b17023SJohn Marino }
3765e4b17023SJohn Marino
3766e4b17023SJohn Marino return false;
3767e4b17023SJohn Marino }
3768e4b17023SJohn Marino
3769e4b17023SJohn Marino /* Verify a gimple assignment statement STMT with a ternary rhs.
3770e4b17023SJohn Marino Returns true if anything is wrong. */
3771e4b17023SJohn Marino
3772e4b17023SJohn Marino static bool
verify_gimple_assign_ternary(gimple stmt)3773e4b17023SJohn Marino verify_gimple_assign_ternary (gimple stmt)
3774e4b17023SJohn Marino {
3775e4b17023SJohn Marino enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
3776e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt);
3777e4b17023SJohn Marino tree lhs_type = TREE_TYPE (lhs);
3778e4b17023SJohn Marino tree rhs1 = gimple_assign_rhs1 (stmt);
3779e4b17023SJohn Marino tree rhs1_type = TREE_TYPE (rhs1);
3780e4b17023SJohn Marino tree rhs2 = gimple_assign_rhs2 (stmt);
3781e4b17023SJohn Marino tree rhs2_type = TREE_TYPE (rhs2);
3782e4b17023SJohn Marino tree rhs3 = gimple_assign_rhs3 (stmt);
3783e4b17023SJohn Marino tree rhs3_type = TREE_TYPE (rhs3);
3784e4b17023SJohn Marino
3785e4b17023SJohn Marino if (!is_gimple_reg (lhs))
3786e4b17023SJohn Marino {
3787e4b17023SJohn Marino error ("non-register as LHS of ternary operation");
3788e4b17023SJohn Marino return true;
3789e4b17023SJohn Marino }
3790e4b17023SJohn Marino
3791e4b17023SJohn Marino if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
3792e4b17023SJohn Marino ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
3793e4b17023SJohn Marino || !is_gimple_val (rhs2)
3794e4b17023SJohn Marino || !is_gimple_val (rhs3))
3795e4b17023SJohn Marino {
3796e4b17023SJohn Marino error ("invalid operands in ternary operation");
3797e4b17023SJohn Marino return true;
3798e4b17023SJohn Marino }
3799e4b17023SJohn Marino
3800e4b17023SJohn Marino /* First handle operations that involve different types. */
3801e4b17023SJohn Marino switch (rhs_code)
3802e4b17023SJohn Marino {
3803e4b17023SJohn Marino case WIDEN_MULT_PLUS_EXPR:
3804e4b17023SJohn Marino case WIDEN_MULT_MINUS_EXPR:
3805e4b17023SJohn Marino if ((!INTEGRAL_TYPE_P (rhs1_type)
3806e4b17023SJohn Marino && !FIXED_POINT_TYPE_P (rhs1_type))
3807e4b17023SJohn Marino || !useless_type_conversion_p (rhs1_type, rhs2_type)
3808e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs3_type)
3809e4b17023SJohn Marino || 2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)
3810e4b17023SJohn Marino || TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))
3811e4b17023SJohn Marino {
3812e4b17023SJohn Marino error ("type mismatch in widening multiply-accumulate expression");
3813e4b17023SJohn Marino debug_generic_expr (lhs_type);
3814e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3815e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3816e4b17023SJohn Marino debug_generic_expr (rhs3_type);
3817e4b17023SJohn Marino return true;
3818e4b17023SJohn Marino }
3819e4b17023SJohn Marino break;
3820e4b17023SJohn Marino
3821e4b17023SJohn Marino case FMA_EXPR:
3822e4b17023SJohn Marino if (!useless_type_conversion_p (lhs_type, rhs1_type)
3823e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs2_type)
3824e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs3_type))
3825e4b17023SJohn Marino {
3826e4b17023SJohn Marino error ("type mismatch in fused multiply-add expression");
3827e4b17023SJohn Marino debug_generic_expr (lhs_type);
3828e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3829e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3830e4b17023SJohn Marino debug_generic_expr (rhs3_type);
3831e4b17023SJohn Marino return true;
3832e4b17023SJohn Marino }
3833e4b17023SJohn Marino break;
3834e4b17023SJohn Marino
3835e4b17023SJohn Marino case COND_EXPR:
3836e4b17023SJohn Marino case VEC_COND_EXPR:
3837e4b17023SJohn Marino if (!useless_type_conversion_p (lhs_type, rhs2_type)
3838e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs3_type))
3839e4b17023SJohn Marino {
3840e4b17023SJohn Marino error ("type mismatch in conditional expression");
3841e4b17023SJohn Marino debug_generic_expr (lhs_type);
3842e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3843e4b17023SJohn Marino debug_generic_expr (rhs3_type);
3844e4b17023SJohn Marino return true;
3845e4b17023SJohn Marino }
3846e4b17023SJohn Marino break;
3847e4b17023SJohn Marino
3848e4b17023SJohn Marino case VEC_PERM_EXPR:
3849e4b17023SJohn Marino if (!useless_type_conversion_p (lhs_type, rhs1_type)
3850e4b17023SJohn Marino || !useless_type_conversion_p (lhs_type, rhs2_type))
3851e4b17023SJohn Marino {
3852e4b17023SJohn Marino error ("type mismatch in vector permute expression");
3853e4b17023SJohn Marino debug_generic_expr (lhs_type);
3854e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3855e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3856e4b17023SJohn Marino debug_generic_expr (rhs3_type);
3857e4b17023SJohn Marino return true;
3858e4b17023SJohn Marino }
3859e4b17023SJohn Marino
3860e4b17023SJohn Marino if (TREE_CODE (rhs1_type) != VECTOR_TYPE
3861e4b17023SJohn Marino || TREE_CODE (rhs2_type) != VECTOR_TYPE
3862e4b17023SJohn Marino || TREE_CODE (rhs3_type) != VECTOR_TYPE)
3863e4b17023SJohn Marino {
3864e4b17023SJohn Marino error ("vector types expected in vector permute expression");
3865e4b17023SJohn Marino debug_generic_expr (lhs_type);
3866e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3867e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3868e4b17023SJohn Marino debug_generic_expr (rhs3_type);
3869e4b17023SJohn Marino return true;
3870e4b17023SJohn Marino }
3871e4b17023SJohn Marino
3872e4b17023SJohn Marino if (TYPE_VECTOR_SUBPARTS (rhs1_type) != TYPE_VECTOR_SUBPARTS (rhs2_type)
3873e4b17023SJohn Marino || TYPE_VECTOR_SUBPARTS (rhs2_type)
3874e4b17023SJohn Marino != TYPE_VECTOR_SUBPARTS (rhs3_type)
3875e4b17023SJohn Marino || TYPE_VECTOR_SUBPARTS (rhs3_type)
3876e4b17023SJohn Marino != TYPE_VECTOR_SUBPARTS (lhs_type))
3877e4b17023SJohn Marino {
3878e4b17023SJohn Marino error ("vectors with different element number found "
3879e4b17023SJohn Marino "in vector permute expression");
3880e4b17023SJohn Marino debug_generic_expr (lhs_type);
3881e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3882e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3883e4b17023SJohn Marino debug_generic_expr (rhs3_type);
3884e4b17023SJohn Marino return true;
3885e4b17023SJohn Marino }
3886e4b17023SJohn Marino
3887e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (rhs3_type)) != INTEGER_TYPE
3888e4b17023SJohn Marino || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs3_type)))
3889e4b17023SJohn Marino != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type))))
3890e4b17023SJohn Marino {
3891e4b17023SJohn Marino error ("invalid mask type in vector permute expression");
3892e4b17023SJohn Marino debug_generic_expr (lhs_type);
3893e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3894e4b17023SJohn Marino debug_generic_expr (rhs2_type);
3895e4b17023SJohn Marino debug_generic_expr (rhs3_type);
3896e4b17023SJohn Marino return true;
3897e4b17023SJohn Marino }
3898e4b17023SJohn Marino
3899e4b17023SJohn Marino return false;
3900e4b17023SJohn Marino
3901e4b17023SJohn Marino case DOT_PROD_EXPR:
3902e4b17023SJohn Marino case REALIGN_LOAD_EXPR:
3903e4b17023SJohn Marino /* FIXME. */
3904e4b17023SJohn Marino return false;
3905e4b17023SJohn Marino
3906e4b17023SJohn Marino default:
3907e4b17023SJohn Marino gcc_unreachable ();
3908e4b17023SJohn Marino }
3909e4b17023SJohn Marino return false;
3910e4b17023SJohn Marino }
3911e4b17023SJohn Marino
3912e4b17023SJohn Marino /* Verify a gimple assignment statement STMT with a single rhs.
3913e4b17023SJohn Marino Returns true if anything is wrong. */
3914e4b17023SJohn Marino
3915e4b17023SJohn Marino static bool
verify_gimple_assign_single(gimple stmt)3916e4b17023SJohn Marino verify_gimple_assign_single (gimple stmt)
3917e4b17023SJohn Marino {
3918e4b17023SJohn Marino enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
3919e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt);
3920e4b17023SJohn Marino tree lhs_type = TREE_TYPE (lhs);
3921e4b17023SJohn Marino tree rhs1 = gimple_assign_rhs1 (stmt);
3922e4b17023SJohn Marino tree rhs1_type = TREE_TYPE (rhs1);
3923e4b17023SJohn Marino bool res = false;
3924e4b17023SJohn Marino
3925e4b17023SJohn Marino if (!useless_type_conversion_p (lhs_type, rhs1_type))
3926e4b17023SJohn Marino {
3927e4b17023SJohn Marino error ("non-trivial conversion at assignment");
3928e4b17023SJohn Marino debug_generic_expr (lhs_type);
3929e4b17023SJohn Marino debug_generic_expr (rhs1_type);
3930e4b17023SJohn Marino return true;
3931e4b17023SJohn Marino }
3932e4b17023SJohn Marino
3933e4b17023SJohn Marino if (handled_component_p (lhs))
3934e4b17023SJohn Marino res |= verify_types_in_gimple_reference (lhs, true);
3935e4b17023SJohn Marino
3936e4b17023SJohn Marino /* Special codes we cannot handle via their class. */
3937e4b17023SJohn Marino switch (rhs_code)
3938e4b17023SJohn Marino {
3939e4b17023SJohn Marino case ADDR_EXPR:
3940e4b17023SJohn Marino {
3941e4b17023SJohn Marino tree op = TREE_OPERAND (rhs1, 0);
3942e4b17023SJohn Marino if (!is_gimple_addressable (op))
3943e4b17023SJohn Marino {
3944e4b17023SJohn Marino error ("invalid operand in unary expression");
3945e4b17023SJohn Marino return true;
3946e4b17023SJohn Marino }
3947e4b17023SJohn Marino
3948e4b17023SJohn Marino /* Technically there is no longer a need for matching types, but
3949e4b17023SJohn Marino gimple hygiene asks for this check. In LTO we can end up
3950e4b17023SJohn Marino combining incompatible units and thus end up with addresses
3951e4b17023SJohn Marino of globals that change their type to a common one. */
3952e4b17023SJohn Marino if (!in_lto_p
3953e4b17023SJohn Marino && !types_compatible_p (TREE_TYPE (op),
3954e4b17023SJohn Marino TREE_TYPE (TREE_TYPE (rhs1)))
3955e4b17023SJohn Marino && !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
3956e4b17023SJohn Marino TREE_TYPE (op)))
3957e4b17023SJohn Marino {
3958e4b17023SJohn Marino error ("type mismatch in address expression");
3959e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (rhs1));
3960e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (op));
3961e4b17023SJohn Marino return true;
3962e4b17023SJohn Marino }
3963e4b17023SJohn Marino
3964e4b17023SJohn Marino return verify_types_in_gimple_reference (op, true);
3965e4b17023SJohn Marino }
3966e4b17023SJohn Marino
3967e4b17023SJohn Marino /* tcc_reference */
3968e4b17023SJohn Marino case INDIRECT_REF:
3969e4b17023SJohn Marino error ("INDIRECT_REF in gimple IL");
3970e4b17023SJohn Marino return true;
3971e4b17023SJohn Marino
3972e4b17023SJohn Marino case COMPONENT_REF:
3973e4b17023SJohn Marino case BIT_FIELD_REF:
3974e4b17023SJohn Marino case ARRAY_REF:
3975e4b17023SJohn Marino case ARRAY_RANGE_REF:
3976e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
3977e4b17023SJohn Marino case REALPART_EXPR:
3978e4b17023SJohn Marino case IMAGPART_EXPR:
3979e4b17023SJohn Marino case TARGET_MEM_REF:
3980e4b17023SJohn Marino case MEM_REF:
3981e4b17023SJohn Marino if (!is_gimple_reg (lhs)
3982e4b17023SJohn Marino && is_gimple_reg_type (TREE_TYPE (lhs)))
3983e4b17023SJohn Marino {
3984e4b17023SJohn Marino error ("invalid rhs for gimple memory store");
3985e4b17023SJohn Marino debug_generic_stmt (lhs);
3986e4b17023SJohn Marino debug_generic_stmt (rhs1);
3987e4b17023SJohn Marino return true;
3988e4b17023SJohn Marino }
3989e4b17023SJohn Marino return res || verify_types_in_gimple_reference (rhs1, false);
3990e4b17023SJohn Marino
3991e4b17023SJohn Marino /* tcc_constant */
3992e4b17023SJohn Marino case SSA_NAME:
3993e4b17023SJohn Marino case INTEGER_CST:
3994e4b17023SJohn Marino case REAL_CST:
3995e4b17023SJohn Marino case FIXED_CST:
3996e4b17023SJohn Marino case COMPLEX_CST:
3997e4b17023SJohn Marino case VECTOR_CST:
3998e4b17023SJohn Marino case STRING_CST:
3999e4b17023SJohn Marino return res;
4000e4b17023SJohn Marino
4001e4b17023SJohn Marino /* tcc_declaration */
4002e4b17023SJohn Marino case CONST_DECL:
4003e4b17023SJohn Marino return res;
4004e4b17023SJohn Marino case VAR_DECL:
4005e4b17023SJohn Marino case PARM_DECL:
4006e4b17023SJohn Marino if (!is_gimple_reg (lhs)
4007e4b17023SJohn Marino && !is_gimple_reg (rhs1)
4008e4b17023SJohn Marino && is_gimple_reg_type (TREE_TYPE (lhs)))
4009e4b17023SJohn Marino {
4010e4b17023SJohn Marino error ("invalid rhs for gimple memory store");
4011e4b17023SJohn Marino debug_generic_stmt (lhs);
4012e4b17023SJohn Marino debug_generic_stmt (rhs1);
4013e4b17023SJohn Marino return true;
4014e4b17023SJohn Marino }
4015e4b17023SJohn Marino return res;
4016e4b17023SJohn Marino
4017e4b17023SJohn Marino case CONSTRUCTOR:
4018e4b17023SJohn Marino case OBJ_TYPE_REF:
4019e4b17023SJohn Marino case ASSERT_EXPR:
4020e4b17023SJohn Marino case WITH_SIZE_EXPR:
4021e4b17023SJohn Marino /* FIXME. */
4022e4b17023SJohn Marino return res;
4023e4b17023SJohn Marino
4024e4b17023SJohn Marino default:;
4025e4b17023SJohn Marino }
4026e4b17023SJohn Marino
4027e4b17023SJohn Marino return res;
4028e4b17023SJohn Marino }
4029e4b17023SJohn Marino
4030e4b17023SJohn Marino /* Verify the contents of a GIMPLE_ASSIGN STMT. Returns true when there
4031e4b17023SJohn Marino is a problem, otherwise false. */
4032e4b17023SJohn Marino
4033e4b17023SJohn Marino static bool
verify_gimple_assign(gimple stmt)4034e4b17023SJohn Marino verify_gimple_assign (gimple stmt)
4035e4b17023SJohn Marino {
4036e4b17023SJohn Marino switch (gimple_assign_rhs_class (stmt))
4037e4b17023SJohn Marino {
4038e4b17023SJohn Marino case GIMPLE_SINGLE_RHS:
4039e4b17023SJohn Marino return verify_gimple_assign_single (stmt);
4040e4b17023SJohn Marino
4041e4b17023SJohn Marino case GIMPLE_UNARY_RHS:
4042e4b17023SJohn Marino return verify_gimple_assign_unary (stmt);
4043e4b17023SJohn Marino
4044e4b17023SJohn Marino case GIMPLE_BINARY_RHS:
4045e4b17023SJohn Marino return verify_gimple_assign_binary (stmt);
4046e4b17023SJohn Marino
4047e4b17023SJohn Marino case GIMPLE_TERNARY_RHS:
4048e4b17023SJohn Marino return verify_gimple_assign_ternary (stmt);
4049e4b17023SJohn Marino
4050e4b17023SJohn Marino default:
4051e4b17023SJohn Marino gcc_unreachable ();
4052e4b17023SJohn Marino }
4053e4b17023SJohn Marino }
4054e4b17023SJohn Marino
4055e4b17023SJohn Marino /* Verify the contents of a GIMPLE_RETURN STMT. Returns true when there
4056e4b17023SJohn Marino is a problem, otherwise false. */
4057e4b17023SJohn Marino
4058e4b17023SJohn Marino static bool
verify_gimple_return(gimple stmt)4059e4b17023SJohn Marino verify_gimple_return (gimple stmt)
4060e4b17023SJohn Marino {
4061e4b17023SJohn Marino tree op = gimple_return_retval (stmt);
4062e4b17023SJohn Marino tree restype = TREE_TYPE (TREE_TYPE (cfun->decl));
4063e4b17023SJohn Marino
4064e4b17023SJohn Marino /* We cannot test for present return values as we do not fix up missing
4065e4b17023SJohn Marino return values from the original source. */
4066e4b17023SJohn Marino if (op == NULL)
4067e4b17023SJohn Marino return false;
4068e4b17023SJohn Marino
4069e4b17023SJohn Marino if (!is_gimple_val (op)
4070e4b17023SJohn Marino && TREE_CODE (op) != RESULT_DECL)
4071e4b17023SJohn Marino {
4072e4b17023SJohn Marino error ("invalid operand in return statement");
4073e4b17023SJohn Marino debug_generic_stmt (op);
4074e4b17023SJohn Marino return true;
4075e4b17023SJohn Marino }
4076e4b17023SJohn Marino
4077e4b17023SJohn Marino if ((TREE_CODE (op) == RESULT_DECL
4078e4b17023SJohn Marino && DECL_BY_REFERENCE (op))
4079e4b17023SJohn Marino || (TREE_CODE (op) == SSA_NAME
4080e4b17023SJohn Marino && TREE_CODE (SSA_NAME_VAR (op)) == RESULT_DECL
4081e4b17023SJohn Marino && DECL_BY_REFERENCE (SSA_NAME_VAR (op))))
4082e4b17023SJohn Marino op = TREE_TYPE (op);
4083e4b17023SJohn Marino
4084e4b17023SJohn Marino if (!useless_type_conversion_p (restype, TREE_TYPE (op)))
4085e4b17023SJohn Marino {
4086e4b17023SJohn Marino error ("invalid conversion in return statement");
4087e4b17023SJohn Marino debug_generic_stmt (restype);
4088e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (op));
4089e4b17023SJohn Marino return true;
4090e4b17023SJohn Marino }
4091e4b17023SJohn Marino
4092e4b17023SJohn Marino return false;
4093e4b17023SJohn Marino }
4094e4b17023SJohn Marino
4095e4b17023SJohn Marino
4096e4b17023SJohn Marino /* Verify the contents of a GIMPLE_GOTO STMT. Returns true when there
4097e4b17023SJohn Marino is a problem, otherwise false. */
4098e4b17023SJohn Marino
4099e4b17023SJohn Marino static bool
verify_gimple_goto(gimple stmt)4100e4b17023SJohn Marino verify_gimple_goto (gimple stmt)
4101e4b17023SJohn Marino {
4102e4b17023SJohn Marino tree dest = gimple_goto_dest (stmt);
4103e4b17023SJohn Marino
4104e4b17023SJohn Marino /* ??? We have two canonical forms of direct goto destinations, a
4105e4b17023SJohn Marino bare LABEL_DECL and an ADDR_EXPR of a LABEL_DECL. */
4106e4b17023SJohn Marino if (TREE_CODE (dest) != LABEL_DECL
4107e4b17023SJohn Marino && (!is_gimple_val (dest)
4108e4b17023SJohn Marino || !POINTER_TYPE_P (TREE_TYPE (dest))))
4109e4b17023SJohn Marino {
4110e4b17023SJohn Marino error ("goto destination is neither a label nor a pointer");
4111e4b17023SJohn Marino return true;
4112e4b17023SJohn Marino }
4113e4b17023SJohn Marino
4114e4b17023SJohn Marino return false;
4115e4b17023SJohn Marino }
4116e4b17023SJohn Marino
4117e4b17023SJohn Marino /* Verify the contents of a GIMPLE_SWITCH STMT. Returns true when there
4118e4b17023SJohn Marino is a problem, otherwise false. */
4119e4b17023SJohn Marino
4120e4b17023SJohn Marino static bool
verify_gimple_switch(gimple stmt)4121e4b17023SJohn Marino verify_gimple_switch (gimple stmt)
4122e4b17023SJohn Marino {
4123e4b17023SJohn Marino if (!is_gimple_val (gimple_switch_index (stmt)))
4124e4b17023SJohn Marino {
4125e4b17023SJohn Marino error ("invalid operand to switch statement");
4126e4b17023SJohn Marino debug_generic_stmt (gimple_switch_index (stmt));
4127e4b17023SJohn Marino return true;
4128e4b17023SJohn Marino }
4129e4b17023SJohn Marino
4130e4b17023SJohn Marino return false;
4131e4b17023SJohn Marino }
4132e4b17023SJohn Marino
4133e4b17023SJohn Marino /* Verify a gimple debug statement STMT.
4134e4b17023SJohn Marino Returns true if anything is wrong. */
4135e4b17023SJohn Marino
4136e4b17023SJohn Marino static bool
verify_gimple_debug(gimple stmt ATTRIBUTE_UNUSED)4137e4b17023SJohn Marino verify_gimple_debug (gimple stmt ATTRIBUTE_UNUSED)
4138e4b17023SJohn Marino {
4139e4b17023SJohn Marino /* There isn't much that could be wrong in a gimple debug stmt. A
4140e4b17023SJohn Marino gimple debug bind stmt, for example, maps a tree, that's usually
4141e4b17023SJohn Marino a VAR_DECL or a PARM_DECL, but that could also be some scalarized
4142e4b17023SJohn Marino component or member of an aggregate type, to another tree, that
4143e4b17023SJohn Marino can be an arbitrary expression. These stmts expand into debug
4144e4b17023SJohn Marino insns, and are converted to debug notes by var-tracking.c. */
4145e4b17023SJohn Marino return false;
4146e4b17023SJohn Marino }
4147e4b17023SJohn Marino
4148e4b17023SJohn Marino /* Verify a gimple label statement STMT.
4149e4b17023SJohn Marino Returns true if anything is wrong. */
4150e4b17023SJohn Marino
4151e4b17023SJohn Marino static bool
verify_gimple_label(gimple stmt)4152e4b17023SJohn Marino verify_gimple_label (gimple stmt)
4153e4b17023SJohn Marino {
4154e4b17023SJohn Marino tree decl = gimple_label_label (stmt);
4155e4b17023SJohn Marino int uid;
4156e4b17023SJohn Marino bool err = false;
4157e4b17023SJohn Marino
4158e4b17023SJohn Marino if (TREE_CODE (decl) != LABEL_DECL)
4159e4b17023SJohn Marino return true;
4160e4b17023SJohn Marino
4161e4b17023SJohn Marino uid = LABEL_DECL_UID (decl);
4162e4b17023SJohn Marino if (cfun->cfg
4163e4b17023SJohn Marino && (uid == -1
4164e4b17023SJohn Marino || VEC_index (basic_block,
4165e4b17023SJohn Marino label_to_block_map, uid) != gimple_bb (stmt)))
4166e4b17023SJohn Marino {
4167e4b17023SJohn Marino error ("incorrect entry in label_to_block_map");
4168e4b17023SJohn Marino err |= true;
4169e4b17023SJohn Marino }
4170e4b17023SJohn Marino
4171e4b17023SJohn Marino uid = EH_LANDING_PAD_NR (decl);
4172e4b17023SJohn Marino if (uid)
4173e4b17023SJohn Marino {
4174e4b17023SJohn Marino eh_landing_pad lp = get_eh_landing_pad_from_number (uid);
4175e4b17023SJohn Marino if (decl != lp->post_landing_pad)
4176e4b17023SJohn Marino {
4177e4b17023SJohn Marino error ("incorrect setting of landing pad number");
4178e4b17023SJohn Marino err |= true;
4179e4b17023SJohn Marino }
4180e4b17023SJohn Marino }
4181e4b17023SJohn Marino
4182e4b17023SJohn Marino return err;
4183e4b17023SJohn Marino }
4184e4b17023SJohn Marino
4185e4b17023SJohn Marino /* Verify the GIMPLE statement STMT. Returns true if there is an
4186e4b17023SJohn Marino error, otherwise false. */
4187e4b17023SJohn Marino
4188e4b17023SJohn Marino static bool
verify_gimple_stmt(gimple stmt)4189e4b17023SJohn Marino verify_gimple_stmt (gimple stmt)
4190e4b17023SJohn Marino {
4191e4b17023SJohn Marino switch (gimple_code (stmt))
4192e4b17023SJohn Marino {
4193e4b17023SJohn Marino case GIMPLE_ASSIGN:
4194e4b17023SJohn Marino return verify_gimple_assign (stmt);
4195e4b17023SJohn Marino
4196e4b17023SJohn Marino case GIMPLE_LABEL:
4197e4b17023SJohn Marino return verify_gimple_label (stmt);
4198e4b17023SJohn Marino
4199e4b17023SJohn Marino case GIMPLE_CALL:
4200e4b17023SJohn Marino return verify_gimple_call (stmt);
4201e4b17023SJohn Marino
4202e4b17023SJohn Marino case GIMPLE_COND:
4203e4b17023SJohn Marino if (TREE_CODE_CLASS (gimple_cond_code (stmt)) != tcc_comparison)
4204e4b17023SJohn Marino {
4205e4b17023SJohn Marino error ("invalid comparison code in gimple cond");
4206e4b17023SJohn Marino return true;
4207e4b17023SJohn Marino }
4208e4b17023SJohn Marino if (!(!gimple_cond_true_label (stmt)
4209e4b17023SJohn Marino || TREE_CODE (gimple_cond_true_label (stmt)) == LABEL_DECL)
4210e4b17023SJohn Marino || !(!gimple_cond_false_label (stmt)
4211e4b17023SJohn Marino || TREE_CODE (gimple_cond_false_label (stmt)) == LABEL_DECL))
4212e4b17023SJohn Marino {
4213e4b17023SJohn Marino error ("invalid labels in gimple cond");
4214e4b17023SJohn Marino return true;
4215e4b17023SJohn Marino }
4216e4b17023SJohn Marino
4217e4b17023SJohn Marino return verify_gimple_comparison (boolean_type_node,
4218e4b17023SJohn Marino gimple_cond_lhs (stmt),
4219e4b17023SJohn Marino gimple_cond_rhs (stmt));
4220e4b17023SJohn Marino
4221e4b17023SJohn Marino case GIMPLE_GOTO:
4222e4b17023SJohn Marino return verify_gimple_goto (stmt);
4223e4b17023SJohn Marino
4224e4b17023SJohn Marino case GIMPLE_SWITCH:
4225e4b17023SJohn Marino return verify_gimple_switch (stmt);
4226e4b17023SJohn Marino
4227e4b17023SJohn Marino case GIMPLE_RETURN:
4228e4b17023SJohn Marino return verify_gimple_return (stmt);
4229e4b17023SJohn Marino
4230e4b17023SJohn Marino case GIMPLE_ASM:
4231e4b17023SJohn Marino return false;
4232e4b17023SJohn Marino
4233e4b17023SJohn Marino case GIMPLE_TRANSACTION:
4234e4b17023SJohn Marino return verify_gimple_transaction (stmt);
4235e4b17023SJohn Marino
4236e4b17023SJohn Marino /* Tuples that do not have tree operands. */
4237e4b17023SJohn Marino case GIMPLE_NOP:
4238e4b17023SJohn Marino case GIMPLE_PREDICT:
4239e4b17023SJohn Marino case GIMPLE_RESX:
4240e4b17023SJohn Marino case GIMPLE_EH_DISPATCH:
4241e4b17023SJohn Marino case GIMPLE_EH_MUST_NOT_THROW:
4242e4b17023SJohn Marino return false;
4243e4b17023SJohn Marino
4244e4b17023SJohn Marino CASE_GIMPLE_OMP:
4245e4b17023SJohn Marino /* OpenMP directives are validated by the FE and never operated
4246e4b17023SJohn Marino on by the optimizers. Furthermore, GIMPLE_OMP_FOR may contain
4247e4b17023SJohn Marino non-gimple expressions when the main index variable has had
4248e4b17023SJohn Marino its address taken. This does not affect the loop itself
4249e4b17023SJohn Marino because the header of an GIMPLE_OMP_FOR is merely used to determine
4250e4b17023SJohn Marino how to setup the parallel iteration. */
4251e4b17023SJohn Marino return false;
4252e4b17023SJohn Marino
4253e4b17023SJohn Marino case GIMPLE_DEBUG:
4254e4b17023SJohn Marino return verify_gimple_debug (stmt);
4255e4b17023SJohn Marino
4256e4b17023SJohn Marino default:
4257e4b17023SJohn Marino gcc_unreachable ();
4258e4b17023SJohn Marino }
4259e4b17023SJohn Marino }
4260e4b17023SJohn Marino
4261e4b17023SJohn Marino /* Verify the contents of a GIMPLE_PHI. Returns true if there is a problem,
4262e4b17023SJohn Marino and false otherwise. */
4263e4b17023SJohn Marino
4264e4b17023SJohn Marino static bool
verify_gimple_phi(gimple phi)4265e4b17023SJohn Marino verify_gimple_phi (gimple phi)
4266e4b17023SJohn Marino {
4267e4b17023SJohn Marino bool err = false;
4268e4b17023SJohn Marino unsigned i;
4269e4b17023SJohn Marino tree phi_result = gimple_phi_result (phi);
4270e4b17023SJohn Marino bool virtual_p;
4271e4b17023SJohn Marino
4272e4b17023SJohn Marino if (!phi_result)
4273e4b17023SJohn Marino {
4274e4b17023SJohn Marino error ("invalid PHI result");
4275e4b17023SJohn Marino return true;
4276e4b17023SJohn Marino }
4277e4b17023SJohn Marino
4278e4b17023SJohn Marino virtual_p = !is_gimple_reg (phi_result);
4279e4b17023SJohn Marino if (TREE_CODE (phi_result) != SSA_NAME
4280e4b17023SJohn Marino || (virtual_p
4281e4b17023SJohn Marino && SSA_NAME_VAR (phi_result) != gimple_vop (cfun)))
4282e4b17023SJohn Marino {
4283e4b17023SJohn Marino error ("invalid PHI result");
4284e4b17023SJohn Marino err = true;
4285e4b17023SJohn Marino }
4286e4b17023SJohn Marino
4287e4b17023SJohn Marino for (i = 0; i < gimple_phi_num_args (phi); i++)
4288e4b17023SJohn Marino {
4289e4b17023SJohn Marino tree t = gimple_phi_arg_def (phi, i);
4290e4b17023SJohn Marino
4291e4b17023SJohn Marino if (!t)
4292e4b17023SJohn Marino {
4293e4b17023SJohn Marino error ("missing PHI def");
4294e4b17023SJohn Marino err |= true;
4295e4b17023SJohn Marino continue;
4296e4b17023SJohn Marino }
4297e4b17023SJohn Marino /* Addressable variables do have SSA_NAMEs but they
4298e4b17023SJohn Marino are not considered gimple values. */
4299e4b17023SJohn Marino else if ((TREE_CODE (t) == SSA_NAME
4300e4b17023SJohn Marino && virtual_p != !is_gimple_reg (t))
4301e4b17023SJohn Marino || (virtual_p
4302e4b17023SJohn Marino && (TREE_CODE (t) != SSA_NAME
4303e4b17023SJohn Marino || SSA_NAME_VAR (t) != gimple_vop (cfun)))
4304e4b17023SJohn Marino || (!virtual_p
4305e4b17023SJohn Marino && !is_gimple_val (t)))
4306e4b17023SJohn Marino {
4307e4b17023SJohn Marino error ("invalid PHI argument");
4308e4b17023SJohn Marino debug_generic_expr (t);
4309e4b17023SJohn Marino err |= true;
4310e4b17023SJohn Marino }
4311e4b17023SJohn Marino #ifdef ENABLE_TYPES_CHECKING
4312e4b17023SJohn Marino if (!useless_type_conversion_p (TREE_TYPE (phi_result), TREE_TYPE (t)))
4313e4b17023SJohn Marino {
4314e4b17023SJohn Marino error ("incompatible types in PHI argument %u", i);
4315e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (phi_result));
4316e4b17023SJohn Marino debug_generic_stmt (TREE_TYPE (t));
4317e4b17023SJohn Marino err |= true;
4318e4b17023SJohn Marino }
4319e4b17023SJohn Marino #endif
4320e4b17023SJohn Marino }
4321e4b17023SJohn Marino
4322e4b17023SJohn Marino return err;
4323e4b17023SJohn Marino }
4324e4b17023SJohn Marino
4325e4b17023SJohn Marino /* Verify the GIMPLE statements inside the sequence STMTS. */
4326e4b17023SJohn Marino
4327e4b17023SJohn Marino static bool
verify_gimple_in_seq_2(gimple_seq stmts)4328e4b17023SJohn Marino verify_gimple_in_seq_2 (gimple_seq stmts)
4329e4b17023SJohn Marino {
4330e4b17023SJohn Marino gimple_stmt_iterator ittr;
4331e4b17023SJohn Marino bool err = false;
4332e4b17023SJohn Marino
4333e4b17023SJohn Marino for (ittr = gsi_start (stmts); !gsi_end_p (ittr); gsi_next (&ittr))
4334e4b17023SJohn Marino {
4335e4b17023SJohn Marino gimple stmt = gsi_stmt (ittr);
4336e4b17023SJohn Marino
4337e4b17023SJohn Marino switch (gimple_code (stmt))
4338e4b17023SJohn Marino {
4339e4b17023SJohn Marino case GIMPLE_BIND:
4340e4b17023SJohn Marino err |= verify_gimple_in_seq_2 (gimple_bind_body (stmt));
4341e4b17023SJohn Marino break;
4342e4b17023SJohn Marino
4343e4b17023SJohn Marino case GIMPLE_TRY:
4344e4b17023SJohn Marino err |= verify_gimple_in_seq_2 (gimple_try_eval (stmt));
4345e4b17023SJohn Marino err |= verify_gimple_in_seq_2 (gimple_try_cleanup (stmt));
4346e4b17023SJohn Marino break;
4347e4b17023SJohn Marino
4348e4b17023SJohn Marino case GIMPLE_EH_FILTER:
4349e4b17023SJohn Marino err |= verify_gimple_in_seq_2 (gimple_eh_filter_failure (stmt));
4350e4b17023SJohn Marino break;
4351e4b17023SJohn Marino
4352e4b17023SJohn Marino case GIMPLE_EH_ELSE:
4353e4b17023SJohn Marino err |= verify_gimple_in_seq_2 (gimple_eh_else_n_body (stmt));
4354e4b17023SJohn Marino err |= verify_gimple_in_seq_2 (gimple_eh_else_e_body (stmt));
4355e4b17023SJohn Marino break;
4356e4b17023SJohn Marino
4357e4b17023SJohn Marino case GIMPLE_CATCH:
4358e4b17023SJohn Marino err |= verify_gimple_in_seq_2 (gimple_catch_handler (stmt));
4359e4b17023SJohn Marino break;
4360e4b17023SJohn Marino
4361e4b17023SJohn Marino case GIMPLE_TRANSACTION:
4362e4b17023SJohn Marino err |= verify_gimple_transaction (stmt);
4363e4b17023SJohn Marino break;
4364e4b17023SJohn Marino
4365e4b17023SJohn Marino default:
4366e4b17023SJohn Marino {
4367e4b17023SJohn Marino bool err2 = verify_gimple_stmt (stmt);
4368e4b17023SJohn Marino if (err2)
4369e4b17023SJohn Marino debug_gimple_stmt (stmt);
4370e4b17023SJohn Marino err |= err2;
4371e4b17023SJohn Marino }
4372e4b17023SJohn Marino }
4373e4b17023SJohn Marino }
4374e4b17023SJohn Marino
4375e4b17023SJohn Marino return err;
4376e4b17023SJohn Marino }
4377e4b17023SJohn Marino
4378e4b17023SJohn Marino /* Verify the contents of a GIMPLE_TRANSACTION. Returns true if there
4379e4b17023SJohn Marino is a problem, otherwise false. */
4380e4b17023SJohn Marino
4381e4b17023SJohn Marino static bool
verify_gimple_transaction(gimple stmt)4382e4b17023SJohn Marino verify_gimple_transaction (gimple stmt)
4383e4b17023SJohn Marino {
4384e4b17023SJohn Marino tree lab = gimple_transaction_label (stmt);
4385e4b17023SJohn Marino if (lab != NULL && TREE_CODE (lab) != LABEL_DECL)
4386e4b17023SJohn Marino return true;
4387e4b17023SJohn Marino return verify_gimple_in_seq_2 (gimple_transaction_body (stmt));
4388e4b17023SJohn Marino }
4389e4b17023SJohn Marino
4390e4b17023SJohn Marino
4391e4b17023SJohn Marino /* Verify the GIMPLE statements inside the statement list STMTS. */
4392e4b17023SJohn Marino
4393e4b17023SJohn Marino DEBUG_FUNCTION void
verify_gimple_in_seq(gimple_seq stmts)4394e4b17023SJohn Marino verify_gimple_in_seq (gimple_seq stmts)
4395e4b17023SJohn Marino {
4396e4b17023SJohn Marino timevar_push (TV_TREE_STMT_VERIFY);
4397e4b17023SJohn Marino if (verify_gimple_in_seq_2 (stmts))
4398e4b17023SJohn Marino internal_error ("verify_gimple failed");
4399e4b17023SJohn Marino timevar_pop (TV_TREE_STMT_VERIFY);
4400e4b17023SJohn Marino }
4401e4b17023SJohn Marino
4402e4b17023SJohn Marino /* Return true when the T can be shared. */
4403e4b17023SJohn Marino
4404e4b17023SJohn Marino bool
tree_node_can_be_shared(tree t)4405e4b17023SJohn Marino tree_node_can_be_shared (tree t)
4406e4b17023SJohn Marino {
4407e4b17023SJohn Marino if (IS_TYPE_OR_DECL_P (t)
4408e4b17023SJohn Marino || is_gimple_min_invariant (t)
4409e4b17023SJohn Marino || TREE_CODE (t) == SSA_NAME
4410e4b17023SJohn Marino || t == error_mark_node
4411e4b17023SJohn Marino || TREE_CODE (t) == IDENTIFIER_NODE)
4412e4b17023SJohn Marino return true;
4413e4b17023SJohn Marino
4414e4b17023SJohn Marino if (TREE_CODE (t) == CASE_LABEL_EXPR)
4415e4b17023SJohn Marino return true;
4416e4b17023SJohn Marino
4417e4b17023SJohn Marino while (((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
4418e4b17023SJohn Marino && is_gimple_min_invariant (TREE_OPERAND (t, 1)))
4419e4b17023SJohn Marino || TREE_CODE (t) == COMPONENT_REF
4420e4b17023SJohn Marino || TREE_CODE (t) == REALPART_EXPR
4421e4b17023SJohn Marino || TREE_CODE (t) == IMAGPART_EXPR)
4422e4b17023SJohn Marino t = TREE_OPERAND (t, 0);
4423e4b17023SJohn Marino
4424e4b17023SJohn Marino if (DECL_P (t))
4425e4b17023SJohn Marino return true;
4426e4b17023SJohn Marino
4427e4b17023SJohn Marino return false;
4428e4b17023SJohn Marino }
4429e4b17023SJohn Marino
4430e4b17023SJohn Marino /* Called via walk_gimple_stmt. Verify tree sharing. */
4431e4b17023SJohn Marino
4432e4b17023SJohn Marino static tree
verify_node_sharing(tree * tp,int * walk_subtrees,void * data)4433e4b17023SJohn Marino verify_node_sharing (tree *tp, int *walk_subtrees, void *data)
4434e4b17023SJohn Marino {
4435e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
4436e4b17023SJohn Marino struct pointer_set_t *visited = (struct pointer_set_t *) wi->info;
4437e4b17023SJohn Marino
4438e4b17023SJohn Marino if (tree_node_can_be_shared (*tp))
4439e4b17023SJohn Marino {
4440e4b17023SJohn Marino *walk_subtrees = false;
4441e4b17023SJohn Marino return NULL;
4442e4b17023SJohn Marino }
4443e4b17023SJohn Marino
4444e4b17023SJohn Marino if (pointer_set_insert (visited, *tp))
4445e4b17023SJohn Marino return *tp;
4446e4b17023SJohn Marino
4447e4b17023SJohn Marino return NULL;
4448e4b17023SJohn Marino }
4449e4b17023SJohn Marino
4450e4b17023SJohn Marino static bool eh_error_found;
4451e4b17023SJohn Marino static int
verify_eh_throw_stmt_node(void ** slot,void * data)4452e4b17023SJohn Marino verify_eh_throw_stmt_node (void **slot, void *data)
4453e4b17023SJohn Marino {
4454e4b17023SJohn Marino struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
4455e4b17023SJohn Marino struct pointer_set_t *visited = (struct pointer_set_t *) data;
4456e4b17023SJohn Marino
4457e4b17023SJohn Marino if (!pointer_set_contains (visited, node->stmt))
4458e4b17023SJohn Marino {
4459e4b17023SJohn Marino error ("dead STMT in EH table");
4460e4b17023SJohn Marino debug_gimple_stmt (node->stmt);
4461e4b17023SJohn Marino eh_error_found = true;
4462e4b17023SJohn Marino }
4463e4b17023SJohn Marino return 1;
4464e4b17023SJohn Marino }
4465e4b17023SJohn Marino
4466e4b17023SJohn Marino /* Verify the GIMPLE statements in the CFG of FN. */
4467e4b17023SJohn Marino
4468e4b17023SJohn Marino DEBUG_FUNCTION void
verify_gimple_in_cfg(struct function * fn)4469e4b17023SJohn Marino verify_gimple_in_cfg (struct function *fn)
4470e4b17023SJohn Marino {
4471e4b17023SJohn Marino basic_block bb;
4472e4b17023SJohn Marino bool err = false;
4473e4b17023SJohn Marino struct pointer_set_t *visited, *visited_stmts;
4474e4b17023SJohn Marino
4475e4b17023SJohn Marino timevar_push (TV_TREE_STMT_VERIFY);
4476e4b17023SJohn Marino visited = pointer_set_create ();
4477e4b17023SJohn Marino visited_stmts = pointer_set_create ();
4478e4b17023SJohn Marino
4479e4b17023SJohn Marino FOR_EACH_BB_FN (bb, fn)
4480e4b17023SJohn Marino {
4481e4b17023SJohn Marino gimple_stmt_iterator gsi;
4482e4b17023SJohn Marino
4483e4b17023SJohn Marino for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4484e4b17023SJohn Marino {
4485e4b17023SJohn Marino gimple phi = gsi_stmt (gsi);
4486e4b17023SJohn Marino bool err2 = false;
4487e4b17023SJohn Marino unsigned i;
4488e4b17023SJohn Marino
4489e4b17023SJohn Marino pointer_set_insert (visited_stmts, phi);
4490e4b17023SJohn Marino
4491e4b17023SJohn Marino if (gimple_bb (phi) != bb)
4492e4b17023SJohn Marino {
4493e4b17023SJohn Marino error ("gimple_bb (phi) is set to a wrong basic block");
4494e4b17023SJohn Marino err2 = true;
4495e4b17023SJohn Marino }
4496e4b17023SJohn Marino
4497e4b17023SJohn Marino err2 |= verify_gimple_phi (phi);
4498e4b17023SJohn Marino
4499e4b17023SJohn Marino for (i = 0; i < gimple_phi_num_args (phi); i++)
4500e4b17023SJohn Marino {
4501e4b17023SJohn Marino tree arg = gimple_phi_arg_def (phi, i);
4502e4b17023SJohn Marino tree addr = walk_tree (&arg, verify_node_sharing, visited, NULL);
4503e4b17023SJohn Marino if (addr)
4504e4b17023SJohn Marino {
4505e4b17023SJohn Marino error ("incorrect sharing of tree nodes");
4506e4b17023SJohn Marino debug_generic_expr (addr);
4507e4b17023SJohn Marino err2 |= true;
4508e4b17023SJohn Marino }
4509e4b17023SJohn Marino }
4510e4b17023SJohn Marino
4511e4b17023SJohn Marino if (err2)
4512e4b17023SJohn Marino debug_gimple_stmt (phi);
4513e4b17023SJohn Marino err |= err2;
4514e4b17023SJohn Marino }
4515e4b17023SJohn Marino
4516e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4517e4b17023SJohn Marino {
4518e4b17023SJohn Marino gimple stmt = gsi_stmt (gsi);
4519e4b17023SJohn Marino bool err2 = false;
4520e4b17023SJohn Marino struct walk_stmt_info wi;
4521e4b17023SJohn Marino tree addr;
4522e4b17023SJohn Marino int lp_nr;
4523e4b17023SJohn Marino
4524e4b17023SJohn Marino pointer_set_insert (visited_stmts, stmt);
4525e4b17023SJohn Marino
4526e4b17023SJohn Marino if (gimple_bb (stmt) != bb)
4527e4b17023SJohn Marino {
4528e4b17023SJohn Marino error ("gimple_bb (stmt) is set to a wrong basic block");
4529e4b17023SJohn Marino err2 = true;
4530e4b17023SJohn Marino }
4531e4b17023SJohn Marino
4532e4b17023SJohn Marino err2 |= verify_gimple_stmt (stmt);
4533e4b17023SJohn Marino
4534e4b17023SJohn Marino memset (&wi, 0, sizeof (wi));
4535e4b17023SJohn Marino wi.info = (void *) visited;
4536e4b17023SJohn Marino addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
4537e4b17023SJohn Marino if (addr)
4538e4b17023SJohn Marino {
4539e4b17023SJohn Marino error ("incorrect sharing of tree nodes");
4540e4b17023SJohn Marino debug_generic_expr (addr);
4541e4b17023SJohn Marino err2 |= true;
4542e4b17023SJohn Marino }
4543e4b17023SJohn Marino
4544e4b17023SJohn Marino /* ??? Instead of not checking these stmts at all the walker
4545e4b17023SJohn Marino should know its context via wi. */
4546e4b17023SJohn Marino if (!is_gimple_debug (stmt)
4547e4b17023SJohn Marino && !is_gimple_omp (stmt))
4548e4b17023SJohn Marino {
4549e4b17023SJohn Marino memset (&wi, 0, sizeof (wi));
4550e4b17023SJohn Marino addr = walk_gimple_op (stmt, verify_expr, &wi);
4551e4b17023SJohn Marino if (addr)
4552e4b17023SJohn Marino {
4553e4b17023SJohn Marino debug_generic_expr (addr);
4554e4b17023SJohn Marino inform (gimple_location (stmt), "in statement");
4555e4b17023SJohn Marino err2 |= true;
4556e4b17023SJohn Marino }
4557e4b17023SJohn Marino }
4558e4b17023SJohn Marino
4559e4b17023SJohn Marino /* If the statement is marked as part of an EH region, then it is
4560e4b17023SJohn Marino expected that the statement could throw. Verify that when we
4561e4b17023SJohn Marino have optimizations that simplify statements such that we prove
4562e4b17023SJohn Marino that they cannot throw, that we update other data structures
4563e4b17023SJohn Marino to match. */
4564e4b17023SJohn Marino lp_nr = lookup_stmt_eh_lp (stmt);
4565e4b17023SJohn Marino if (lp_nr != 0)
4566e4b17023SJohn Marino {
4567e4b17023SJohn Marino if (!stmt_could_throw_p (stmt))
4568e4b17023SJohn Marino {
4569e4b17023SJohn Marino error ("statement marked for throw, but doesn%'t");
4570e4b17023SJohn Marino err2 |= true;
4571e4b17023SJohn Marino }
4572e4b17023SJohn Marino else if (lp_nr > 0
4573e4b17023SJohn Marino && !gsi_one_before_end_p (gsi)
4574e4b17023SJohn Marino && stmt_can_throw_internal (stmt))
4575e4b17023SJohn Marino {
4576e4b17023SJohn Marino error ("statement marked for throw in middle of block");
4577e4b17023SJohn Marino err2 |= true;
4578e4b17023SJohn Marino }
4579e4b17023SJohn Marino }
4580e4b17023SJohn Marino
4581e4b17023SJohn Marino if (err2)
4582e4b17023SJohn Marino debug_gimple_stmt (stmt);
4583e4b17023SJohn Marino err |= err2;
4584e4b17023SJohn Marino }
4585e4b17023SJohn Marino }
4586e4b17023SJohn Marino
4587e4b17023SJohn Marino eh_error_found = false;
4588e4b17023SJohn Marino if (get_eh_throw_stmt_table (cfun))
4589e4b17023SJohn Marino htab_traverse (get_eh_throw_stmt_table (cfun),
4590e4b17023SJohn Marino verify_eh_throw_stmt_node,
4591e4b17023SJohn Marino visited_stmts);
4592e4b17023SJohn Marino
4593e4b17023SJohn Marino if (err || eh_error_found)
4594e4b17023SJohn Marino internal_error ("verify_gimple failed");
4595e4b17023SJohn Marino
4596e4b17023SJohn Marino pointer_set_destroy (visited);
4597e4b17023SJohn Marino pointer_set_destroy (visited_stmts);
4598e4b17023SJohn Marino verify_histograms ();
4599e4b17023SJohn Marino timevar_pop (TV_TREE_STMT_VERIFY);
4600e4b17023SJohn Marino }
4601e4b17023SJohn Marino
4602e4b17023SJohn Marino
4603e4b17023SJohn Marino /* Verifies that the flow information is OK. */
4604e4b17023SJohn Marino
4605e4b17023SJohn Marino static int
gimple_verify_flow_info(void)4606e4b17023SJohn Marino gimple_verify_flow_info (void)
4607e4b17023SJohn Marino {
4608e4b17023SJohn Marino int err = 0;
4609e4b17023SJohn Marino basic_block bb;
4610e4b17023SJohn Marino gimple_stmt_iterator gsi;
4611e4b17023SJohn Marino gimple stmt;
4612e4b17023SJohn Marino edge e;
4613e4b17023SJohn Marino edge_iterator ei;
4614e4b17023SJohn Marino
4615e4b17023SJohn Marino if (ENTRY_BLOCK_PTR->il.gimple)
4616e4b17023SJohn Marino {
4617e4b17023SJohn Marino error ("ENTRY_BLOCK has IL associated with it");
4618e4b17023SJohn Marino err = 1;
4619e4b17023SJohn Marino }
4620e4b17023SJohn Marino
4621e4b17023SJohn Marino if (EXIT_BLOCK_PTR->il.gimple)
4622e4b17023SJohn Marino {
4623e4b17023SJohn Marino error ("EXIT_BLOCK has IL associated with it");
4624e4b17023SJohn Marino err = 1;
4625e4b17023SJohn Marino }
4626e4b17023SJohn Marino
4627e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
4628e4b17023SJohn Marino if (e->flags & EDGE_FALLTHRU)
4629e4b17023SJohn Marino {
4630e4b17023SJohn Marino error ("fallthru to exit from bb %d", e->src->index);
4631e4b17023SJohn Marino err = 1;
4632e4b17023SJohn Marino }
4633e4b17023SJohn Marino
4634e4b17023SJohn Marino FOR_EACH_BB (bb)
4635e4b17023SJohn Marino {
4636e4b17023SJohn Marino bool found_ctrl_stmt = false;
4637e4b17023SJohn Marino
4638e4b17023SJohn Marino stmt = NULL;
4639e4b17023SJohn Marino
4640e4b17023SJohn Marino /* Skip labels on the start of basic block. */
4641e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
4642e4b17023SJohn Marino {
4643e4b17023SJohn Marino tree label;
4644e4b17023SJohn Marino gimple prev_stmt = stmt;
4645e4b17023SJohn Marino
4646e4b17023SJohn Marino stmt = gsi_stmt (gsi);
4647e4b17023SJohn Marino
4648e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_LABEL)
4649e4b17023SJohn Marino break;
4650e4b17023SJohn Marino
4651e4b17023SJohn Marino label = gimple_label_label (stmt);
4652e4b17023SJohn Marino if (prev_stmt && DECL_NONLOCAL (label))
4653e4b17023SJohn Marino {
4654e4b17023SJohn Marino error ("nonlocal label ");
4655e4b17023SJohn Marino print_generic_expr (stderr, label, 0);
4656e4b17023SJohn Marino fprintf (stderr, " is not first in a sequence of labels in bb %d",
4657e4b17023SJohn Marino bb->index);
4658e4b17023SJohn Marino err = 1;
4659e4b17023SJohn Marino }
4660e4b17023SJohn Marino
4661e4b17023SJohn Marino if (prev_stmt && EH_LANDING_PAD_NR (label) != 0)
4662e4b17023SJohn Marino {
4663e4b17023SJohn Marino error ("EH landing pad label ");
4664e4b17023SJohn Marino print_generic_expr (stderr, label, 0);
4665e4b17023SJohn Marino fprintf (stderr, " is not first in a sequence of labels in bb %d",
4666e4b17023SJohn Marino bb->index);
4667e4b17023SJohn Marino err = 1;
4668e4b17023SJohn Marino }
4669e4b17023SJohn Marino
4670e4b17023SJohn Marino if (label_to_block (label) != bb)
4671e4b17023SJohn Marino {
4672e4b17023SJohn Marino error ("label ");
4673e4b17023SJohn Marino print_generic_expr (stderr, label, 0);
4674e4b17023SJohn Marino fprintf (stderr, " to block does not match in bb %d",
4675e4b17023SJohn Marino bb->index);
4676e4b17023SJohn Marino err = 1;
4677e4b17023SJohn Marino }
4678e4b17023SJohn Marino
4679e4b17023SJohn Marino if (decl_function_context (label) != current_function_decl)
4680e4b17023SJohn Marino {
4681e4b17023SJohn Marino error ("label ");
4682e4b17023SJohn Marino print_generic_expr (stderr, label, 0);
4683e4b17023SJohn Marino fprintf (stderr, " has incorrect context in bb %d",
4684e4b17023SJohn Marino bb->index);
4685e4b17023SJohn Marino err = 1;
4686e4b17023SJohn Marino }
4687e4b17023SJohn Marino }
4688e4b17023SJohn Marino
4689e4b17023SJohn Marino /* Verify that body of basic block BB is free of control flow. */
4690e4b17023SJohn Marino for (; !gsi_end_p (gsi); gsi_next (&gsi))
4691e4b17023SJohn Marino {
4692e4b17023SJohn Marino gimple stmt = gsi_stmt (gsi);
4693e4b17023SJohn Marino
4694e4b17023SJohn Marino if (found_ctrl_stmt)
4695e4b17023SJohn Marino {
4696e4b17023SJohn Marino error ("control flow in the middle of basic block %d",
4697e4b17023SJohn Marino bb->index);
4698e4b17023SJohn Marino err = 1;
4699e4b17023SJohn Marino }
4700e4b17023SJohn Marino
4701e4b17023SJohn Marino if (stmt_ends_bb_p (stmt))
4702e4b17023SJohn Marino found_ctrl_stmt = true;
4703e4b17023SJohn Marino
4704e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL)
4705e4b17023SJohn Marino {
4706e4b17023SJohn Marino error ("label ");
4707e4b17023SJohn Marino print_generic_expr (stderr, gimple_label_label (stmt), 0);
4708e4b17023SJohn Marino fprintf (stderr, " in the middle of basic block %d", bb->index);
4709e4b17023SJohn Marino err = 1;
4710e4b17023SJohn Marino }
4711e4b17023SJohn Marino }
4712e4b17023SJohn Marino
4713e4b17023SJohn Marino gsi = gsi_last_bb (bb);
4714e4b17023SJohn Marino if (gsi_end_p (gsi))
4715e4b17023SJohn Marino continue;
4716e4b17023SJohn Marino
4717e4b17023SJohn Marino stmt = gsi_stmt (gsi);
4718e4b17023SJohn Marino
4719e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL)
4720e4b17023SJohn Marino continue;
4721e4b17023SJohn Marino
4722e4b17023SJohn Marino err |= verify_eh_edges (stmt);
4723e4b17023SJohn Marino
4724e4b17023SJohn Marino if (is_ctrl_stmt (stmt))
4725e4b17023SJohn Marino {
4726e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
4727e4b17023SJohn Marino if (e->flags & EDGE_FALLTHRU)
4728e4b17023SJohn Marino {
4729e4b17023SJohn Marino error ("fallthru edge after a control statement in bb %d",
4730e4b17023SJohn Marino bb->index);
4731e4b17023SJohn Marino err = 1;
4732e4b17023SJohn Marino }
4733e4b17023SJohn Marino }
4734e4b17023SJohn Marino
4735e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_COND)
4736e4b17023SJohn Marino {
4737e4b17023SJohn Marino /* Verify that there are no edges with EDGE_TRUE/FALSE_FLAG set
4738e4b17023SJohn Marino after anything else but if statement. */
4739e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
4740e4b17023SJohn Marino if (e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))
4741e4b17023SJohn Marino {
4742e4b17023SJohn Marino error ("true/false edge after a non-GIMPLE_COND in bb %d",
4743e4b17023SJohn Marino bb->index);
4744e4b17023SJohn Marino err = 1;
4745e4b17023SJohn Marino }
4746e4b17023SJohn Marino }
4747e4b17023SJohn Marino
4748e4b17023SJohn Marino switch (gimple_code (stmt))
4749e4b17023SJohn Marino {
4750e4b17023SJohn Marino case GIMPLE_COND:
4751e4b17023SJohn Marino {
4752e4b17023SJohn Marino edge true_edge;
4753e4b17023SJohn Marino edge false_edge;
4754e4b17023SJohn Marino
4755e4b17023SJohn Marino extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
4756e4b17023SJohn Marino
4757e4b17023SJohn Marino if (!true_edge
4758e4b17023SJohn Marino || !false_edge
4759e4b17023SJohn Marino || !(true_edge->flags & EDGE_TRUE_VALUE)
4760e4b17023SJohn Marino || !(false_edge->flags & EDGE_FALSE_VALUE)
4761e4b17023SJohn Marino || (true_edge->flags & (EDGE_FALLTHRU | EDGE_ABNORMAL))
4762e4b17023SJohn Marino || (false_edge->flags & (EDGE_FALLTHRU | EDGE_ABNORMAL))
4763e4b17023SJohn Marino || EDGE_COUNT (bb->succs) >= 3)
4764e4b17023SJohn Marino {
4765e4b17023SJohn Marino error ("wrong outgoing edge flags at end of bb %d",
4766e4b17023SJohn Marino bb->index);
4767e4b17023SJohn Marino err = 1;
4768e4b17023SJohn Marino }
4769e4b17023SJohn Marino }
4770e4b17023SJohn Marino break;
4771e4b17023SJohn Marino
4772e4b17023SJohn Marino case GIMPLE_GOTO:
4773e4b17023SJohn Marino if (simple_goto_p (stmt))
4774e4b17023SJohn Marino {
4775e4b17023SJohn Marino error ("explicit goto at end of bb %d", bb->index);
4776e4b17023SJohn Marino err = 1;
4777e4b17023SJohn Marino }
4778e4b17023SJohn Marino else
4779e4b17023SJohn Marino {
4780e4b17023SJohn Marino /* FIXME. We should double check that the labels in the
4781e4b17023SJohn Marino destination blocks have their address taken. */
4782e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
4783e4b17023SJohn Marino if ((e->flags & (EDGE_FALLTHRU | EDGE_TRUE_VALUE
4784e4b17023SJohn Marino | EDGE_FALSE_VALUE))
4785e4b17023SJohn Marino || !(e->flags & EDGE_ABNORMAL))
4786e4b17023SJohn Marino {
4787e4b17023SJohn Marino error ("wrong outgoing edge flags at end of bb %d",
4788e4b17023SJohn Marino bb->index);
4789e4b17023SJohn Marino err = 1;
4790e4b17023SJohn Marino }
4791e4b17023SJohn Marino }
4792e4b17023SJohn Marino break;
4793e4b17023SJohn Marino
4794e4b17023SJohn Marino case GIMPLE_CALL:
4795e4b17023SJohn Marino if (!gimple_call_builtin_p (stmt, BUILT_IN_RETURN))
4796e4b17023SJohn Marino break;
4797e4b17023SJohn Marino /* ... fallthru ... */
4798e4b17023SJohn Marino case GIMPLE_RETURN:
4799e4b17023SJohn Marino if (!single_succ_p (bb)
4800e4b17023SJohn Marino || (single_succ_edge (bb)->flags
4801e4b17023SJohn Marino & (EDGE_FALLTHRU | EDGE_ABNORMAL
4802e4b17023SJohn Marino | EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
4803e4b17023SJohn Marino {
4804e4b17023SJohn Marino error ("wrong outgoing edge flags at end of bb %d", bb->index);
4805e4b17023SJohn Marino err = 1;
4806e4b17023SJohn Marino }
4807e4b17023SJohn Marino if (single_succ (bb) != EXIT_BLOCK_PTR)
4808e4b17023SJohn Marino {
4809e4b17023SJohn Marino error ("return edge does not point to exit in bb %d",
4810e4b17023SJohn Marino bb->index);
4811e4b17023SJohn Marino err = 1;
4812e4b17023SJohn Marino }
4813e4b17023SJohn Marino break;
4814e4b17023SJohn Marino
4815e4b17023SJohn Marino case GIMPLE_SWITCH:
4816e4b17023SJohn Marino {
4817e4b17023SJohn Marino tree prev;
4818e4b17023SJohn Marino edge e;
4819e4b17023SJohn Marino size_t i, n;
4820e4b17023SJohn Marino
4821e4b17023SJohn Marino n = gimple_switch_num_labels (stmt);
4822e4b17023SJohn Marino
4823e4b17023SJohn Marino /* Mark all the destination basic blocks. */
4824e4b17023SJohn Marino for (i = 0; i < n; ++i)
4825e4b17023SJohn Marino {
4826e4b17023SJohn Marino tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
4827e4b17023SJohn Marino basic_block label_bb = label_to_block (lab);
4828e4b17023SJohn Marino gcc_assert (!label_bb->aux || label_bb->aux == (void *)1);
4829e4b17023SJohn Marino label_bb->aux = (void *)1;
4830e4b17023SJohn Marino }
4831e4b17023SJohn Marino
4832e4b17023SJohn Marino /* Verify that the case labels are sorted. */
4833e4b17023SJohn Marino prev = gimple_switch_label (stmt, 0);
4834e4b17023SJohn Marino for (i = 1; i < n; ++i)
4835e4b17023SJohn Marino {
4836e4b17023SJohn Marino tree c = gimple_switch_label (stmt, i);
4837e4b17023SJohn Marino if (!CASE_LOW (c))
4838e4b17023SJohn Marino {
4839e4b17023SJohn Marino error ("found default case not at the start of "
4840e4b17023SJohn Marino "case vector");
4841e4b17023SJohn Marino err = 1;
4842e4b17023SJohn Marino continue;
4843e4b17023SJohn Marino }
4844e4b17023SJohn Marino if (CASE_LOW (prev)
4845e4b17023SJohn Marino && !tree_int_cst_lt (CASE_LOW (prev), CASE_LOW (c)))
4846e4b17023SJohn Marino {
4847e4b17023SJohn Marino error ("case labels not sorted: ");
4848e4b17023SJohn Marino print_generic_expr (stderr, prev, 0);
4849e4b17023SJohn Marino fprintf (stderr," is greater than ");
4850e4b17023SJohn Marino print_generic_expr (stderr, c, 0);
4851e4b17023SJohn Marino fprintf (stderr," but comes before it.\n");
4852e4b17023SJohn Marino err = 1;
4853e4b17023SJohn Marino }
4854e4b17023SJohn Marino prev = c;
4855e4b17023SJohn Marino }
4856e4b17023SJohn Marino /* VRP will remove the default case if it can prove it will
4857e4b17023SJohn Marino never be executed. So do not verify there always exists
4858e4b17023SJohn Marino a default case here. */
4859e4b17023SJohn Marino
4860e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
4861e4b17023SJohn Marino {
4862e4b17023SJohn Marino if (!e->dest->aux)
4863e4b17023SJohn Marino {
4864e4b17023SJohn Marino error ("extra outgoing edge %d->%d",
4865e4b17023SJohn Marino bb->index, e->dest->index);
4866e4b17023SJohn Marino err = 1;
4867e4b17023SJohn Marino }
4868e4b17023SJohn Marino
4869e4b17023SJohn Marino e->dest->aux = (void *)2;
4870e4b17023SJohn Marino if ((e->flags & (EDGE_FALLTHRU | EDGE_ABNORMAL
4871e4b17023SJohn Marino | EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
4872e4b17023SJohn Marino {
4873e4b17023SJohn Marino error ("wrong outgoing edge flags at end of bb %d",
4874e4b17023SJohn Marino bb->index);
4875e4b17023SJohn Marino err = 1;
4876e4b17023SJohn Marino }
4877e4b17023SJohn Marino }
4878e4b17023SJohn Marino
4879e4b17023SJohn Marino /* Check that we have all of them. */
4880e4b17023SJohn Marino for (i = 0; i < n; ++i)
4881e4b17023SJohn Marino {
4882e4b17023SJohn Marino tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
4883e4b17023SJohn Marino basic_block label_bb = label_to_block (lab);
4884e4b17023SJohn Marino
4885e4b17023SJohn Marino if (label_bb->aux != (void *)2)
4886e4b17023SJohn Marino {
4887e4b17023SJohn Marino error ("missing edge %i->%i", bb->index, label_bb->index);
4888e4b17023SJohn Marino err = 1;
4889e4b17023SJohn Marino }
4890e4b17023SJohn Marino }
4891e4b17023SJohn Marino
4892e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
4893e4b17023SJohn Marino e->dest->aux = (void *)0;
4894e4b17023SJohn Marino }
4895e4b17023SJohn Marino break;
4896e4b17023SJohn Marino
4897e4b17023SJohn Marino case GIMPLE_EH_DISPATCH:
4898e4b17023SJohn Marino err |= verify_eh_dispatch_edge (stmt);
4899e4b17023SJohn Marino break;
4900e4b17023SJohn Marino
4901e4b17023SJohn Marino default:
4902e4b17023SJohn Marino break;
4903e4b17023SJohn Marino }
4904e4b17023SJohn Marino }
4905e4b17023SJohn Marino
4906e4b17023SJohn Marino if (dom_info_state (CDI_DOMINATORS) >= DOM_NO_FAST_QUERY)
4907e4b17023SJohn Marino verify_dominators (CDI_DOMINATORS);
4908e4b17023SJohn Marino
4909e4b17023SJohn Marino return err;
4910e4b17023SJohn Marino }
4911e4b17023SJohn Marino
4912e4b17023SJohn Marino
4913e4b17023SJohn Marino /* Updates phi nodes after creating a forwarder block joined
4914e4b17023SJohn Marino by edge FALLTHRU. */
4915e4b17023SJohn Marino
4916e4b17023SJohn Marino static void
gimple_make_forwarder_block(edge fallthru)4917e4b17023SJohn Marino gimple_make_forwarder_block (edge fallthru)
4918e4b17023SJohn Marino {
4919e4b17023SJohn Marino edge e;
4920e4b17023SJohn Marino edge_iterator ei;
4921e4b17023SJohn Marino basic_block dummy, bb;
4922e4b17023SJohn Marino tree var;
4923e4b17023SJohn Marino gimple_stmt_iterator gsi;
4924e4b17023SJohn Marino
4925e4b17023SJohn Marino dummy = fallthru->src;
4926e4b17023SJohn Marino bb = fallthru->dest;
4927e4b17023SJohn Marino
4928e4b17023SJohn Marino if (single_pred_p (bb))
4929e4b17023SJohn Marino return;
4930e4b17023SJohn Marino
4931e4b17023SJohn Marino /* If we redirected a branch we must create new PHI nodes at the
4932e4b17023SJohn Marino start of BB. */
4933e4b17023SJohn Marino for (gsi = gsi_start_phis (dummy); !gsi_end_p (gsi); gsi_next (&gsi))
4934e4b17023SJohn Marino {
4935e4b17023SJohn Marino gimple phi, new_phi;
4936e4b17023SJohn Marino
4937e4b17023SJohn Marino phi = gsi_stmt (gsi);
4938e4b17023SJohn Marino var = gimple_phi_result (phi);
4939e4b17023SJohn Marino new_phi = create_phi_node (var, bb);
4940e4b17023SJohn Marino SSA_NAME_DEF_STMT (var) = new_phi;
4941e4b17023SJohn Marino gimple_phi_set_result (phi, make_ssa_name (SSA_NAME_VAR (var), phi));
4942e4b17023SJohn Marino add_phi_arg (new_phi, gimple_phi_result (phi), fallthru,
4943e4b17023SJohn Marino UNKNOWN_LOCATION);
4944e4b17023SJohn Marino }
4945e4b17023SJohn Marino
4946e4b17023SJohn Marino /* Add the arguments we have stored on edges. */
4947e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds)
4948e4b17023SJohn Marino {
4949e4b17023SJohn Marino if (e == fallthru)
4950e4b17023SJohn Marino continue;
4951e4b17023SJohn Marino
4952e4b17023SJohn Marino flush_pending_stmts (e);
4953e4b17023SJohn Marino }
4954e4b17023SJohn Marino }
4955e4b17023SJohn Marino
4956e4b17023SJohn Marino
4957e4b17023SJohn Marino /* Return a non-special label in the head of basic block BLOCK.
4958e4b17023SJohn Marino Create one if it doesn't exist. */
4959e4b17023SJohn Marino
4960e4b17023SJohn Marino tree
gimple_block_label(basic_block bb)4961e4b17023SJohn Marino gimple_block_label (basic_block bb)
4962e4b17023SJohn Marino {
4963e4b17023SJohn Marino gimple_stmt_iterator i, s = gsi_start_bb (bb);
4964e4b17023SJohn Marino bool first = true;
4965e4b17023SJohn Marino tree label;
4966e4b17023SJohn Marino gimple stmt;
4967e4b17023SJohn Marino
4968e4b17023SJohn Marino for (i = s; !gsi_end_p (i); first = false, gsi_next (&i))
4969e4b17023SJohn Marino {
4970e4b17023SJohn Marino stmt = gsi_stmt (i);
4971e4b17023SJohn Marino if (gimple_code (stmt) != GIMPLE_LABEL)
4972e4b17023SJohn Marino break;
4973e4b17023SJohn Marino label = gimple_label_label (stmt);
4974e4b17023SJohn Marino if (!DECL_NONLOCAL (label))
4975e4b17023SJohn Marino {
4976e4b17023SJohn Marino if (!first)
4977e4b17023SJohn Marino gsi_move_before (&i, &s);
4978e4b17023SJohn Marino return label;
4979e4b17023SJohn Marino }
4980e4b17023SJohn Marino }
4981e4b17023SJohn Marino
4982e4b17023SJohn Marino label = create_artificial_label (UNKNOWN_LOCATION);
4983e4b17023SJohn Marino stmt = gimple_build_label (label);
4984e4b17023SJohn Marino gsi_insert_before (&s, stmt, GSI_NEW_STMT);
4985e4b17023SJohn Marino return label;
4986e4b17023SJohn Marino }
4987e4b17023SJohn Marino
4988e4b17023SJohn Marino
4989e4b17023SJohn Marino /* Attempt to perform edge redirection by replacing a possibly complex
4990e4b17023SJohn Marino jump instruction by a goto or by removing the jump completely.
4991e4b17023SJohn Marino This can apply only if all edges now point to the same block. The
4992e4b17023SJohn Marino parameters and return values are equivalent to
4993e4b17023SJohn Marino redirect_edge_and_branch. */
4994e4b17023SJohn Marino
4995e4b17023SJohn Marino static edge
gimple_try_redirect_by_replacing_jump(edge e,basic_block target)4996e4b17023SJohn Marino gimple_try_redirect_by_replacing_jump (edge e, basic_block target)
4997e4b17023SJohn Marino {
4998e4b17023SJohn Marino basic_block src = e->src;
4999e4b17023SJohn Marino gimple_stmt_iterator i;
5000e4b17023SJohn Marino gimple stmt;
5001e4b17023SJohn Marino
5002e4b17023SJohn Marino /* We can replace or remove a complex jump only when we have exactly
5003e4b17023SJohn Marino two edges. */
5004e4b17023SJohn Marino if (EDGE_COUNT (src->succs) != 2
5005e4b17023SJohn Marino /* Verify that all targets will be TARGET. Specifically, the
5006e4b17023SJohn Marino edge that is not E must also go to TARGET. */
5007e4b17023SJohn Marino || EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest != target)
5008e4b17023SJohn Marino return NULL;
5009e4b17023SJohn Marino
5010e4b17023SJohn Marino i = gsi_last_bb (src);
5011e4b17023SJohn Marino if (gsi_end_p (i))
5012e4b17023SJohn Marino return NULL;
5013e4b17023SJohn Marino
5014e4b17023SJohn Marino stmt = gsi_stmt (i);
5015e4b17023SJohn Marino
5016e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_COND || gimple_code (stmt) == GIMPLE_SWITCH)
5017e4b17023SJohn Marino {
5018e4b17023SJohn Marino gsi_remove (&i, true);
5019e4b17023SJohn Marino e = ssa_redirect_edge (e, target);
5020e4b17023SJohn Marino e->flags = EDGE_FALLTHRU;
5021e4b17023SJohn Marino return e;
5022e4b17023SJohn Marino }
5023e4b17023SJohn Marino
5024e4b17023SJohn Marino return NULL;
5025e4b17023SJohn Marino }
5026e4b17023SJohn Marino
5027e4b17023SJohn Marino
5028e4b17023SJohn Marino /* Redirect E to DEST. Return NULL on failure. Otherwise, return the
5029e4b17023SJohn Marino edge representing the redirected branch. */
5030e4b17023SJohn Marino
5031e4b17023SJohn Marino static edge
gimple_redirect_edge_and_branch(edge e,basic_block dest)5032e4b17023SJohn Marino gimple_redirect_edge_and_branch (edge e, basic_block dest)
5033e4b17023SJohn Marino {
5034e4b17023SJohn Marino basic_block bb = e->src;
5035e4b17023SJohn Marino gimple_stmt_iterator gsi;
5036e4b17023SJohn Marino edge ret;
5037e4b17023SJohn Marino gimple stmt;
5038e4b17023SJohn Marino
5039e4b17023SJohn Marino if (e->flags & EDGE_ABNORMAL)
5040e4b17023SJohn Marino return NULL;
5041e4b17023SJohn Marino
5042e4b17023SJohn Marino if (e->dest == dest)
5043e4b17023SJohn Marino return NULL;
5044e4b17023SJohn Marino
5045e4b17023SJohn Marino if (e->flags & EDGE_EH)
5046e4b17023SJohn Marino return redirect_eh_edge (e, dest);
5047e4b17023SJohn Marino
5048e4b17023SJohn Marino if (e->src != ENTRY_BLOCK_PTR)
5049e4b17023SJohn Marino {
5050e4b17023SJohn Marino ret = gimple_try_redirect_by_replacing_jump (e, dest);
5051e4b17023SJohn Marino if (ret)
5052e4b17023SJohn Marino return ret;
5053e4b17023SJohn Marino }
5054e4b17023SJohn Marino
5055e4b17023SJohn Marino gsi = gsi_last_bb (bb);
5056e4b17023SJohn Marino stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);
5057e4b17023SJohn Marino
5058e4b17023SJohn Marino switch (stmt ? gimple_code (stmt) : GIMPLE_ERROR_MARK)
5059e4b17023SJohn Marino {
5060e4b17023SJohn Marino case GIMPLE_COND:
5061e4b17023SJohn Marino /* For COND_EXPR, we only need to redirect the edge. */
5062e4b17023SJohn Marino break;
5063e4b17023SJohn Marino
5064e4b17023SJohn Marino case GIMPLE_GOTO:
5065e4b17023SJohn Marino /* No non-abnormal edges should lead from a non-simple goto, and
5066e4b17023SJohn Marino simple ones should be represented implicitly. */
5067e4b17023SJohn Marino gcc_unreachable ();
5068e4b17023SJohn Marino
5069e4b17023SJohn Marino case GIMPLE_SWITCH:
5070e4b17023SJohn Marino {
5071e4b17023SJohn Marino tree label = gimple_block_label (dest);
5072e4b17023SJohn Marino tree cases = get_cases_for_edge (e, stmt);
5073e4b17023SJohn Marino
5074e4b17023SJohn Marino /* If we have a list of cases associated with E, then use it
5075e4b17023SJohn Marino as it's a lot faster than walking the entire case vector. */
5076e4b17023SJohn Marino if (cases)
5077e4b17023SJohn Marino {
5078e4b17023SJohn Marino edge e2 = find_edge (e->src, dest);
5079e4b17023SJohn Marino tree last, first;
5080e4b17023SJohn Marino
5081e4b17023SJohn Marino first = cases;
5082e4b17023SJohn Marino while (cases)
5083e4b17023SJohn Marino {
5084e4b17023SJohn Marino last = cases;
5085e4b17023SJohn Marino CASE_LABEL (cases) = label;
5086e4b17023SJohn Marino cases = CASE_CHAIN (cases);
5087e4b17023SJohn Marino }
5088e4b17023SJohn Marino
5089e4b17023SJohn Marino /* If there was already an edge in the CFG, then we need
5090e4b17023SJohn Marino to move all the cases associated with E to E2. */
5091e4b17023SJohn Marino if (e2)
5092e4b17023SJohn Marino {
5093e4b17023SJohn Marino tree cases2 = get_cases_for_edge (e2, stmt);
5094e4b17023SJohn Marino
5095e4b17023SJohn Marino CASE_CHAIN (last) = CASE_CHAIN (cases2);
5096e4b17023SJohn Marino CASE_CHAIN (cases2) = first;
5097e4b17023SJohn Marino }
5098e4b17023SJohn Marino bitmap_set_bit (touched_switch_bbs, gimple_bb (stmt)->index);
5099e4b17023SJohn Marino }
5100e4b17023SJohn Marino else
5101e4b17023SJohn Marino {
5102e4b17023SJohn Marino size_t i, n = gimple_switch_num_labels (stmt);
5103e4b17023SJohn Marino
5104e4b17023SJohn Marino for (i = 0; i < n; i++)
5105e4b17023SJohn Marino {
5106e4b17023SJohn Marino tree elt = gimple_switch_label (stmt, i);
5107e4b17023SJohn Marino if (label_to_block (CASE_LABEL (elt)) == e->dest)
5108e4b17023SJohn Marino CASE_LABEL (elt) = label;
5109e4b17023SJohn Marino }
5110e4b17023SJohn Marino }
5111e4b17023SJohn Marino }
5112e4b17023SJohn Marino break;
5113e4b17023SJohn Marino
5114e4b17023SJohn Marino case GIMPLE_ASM:
5115e4b17023SJohn Marino {
5116e4b17023SJohn Marino int i, n = gimple_asm_nlabels (stmt);
5117e4b17023SJohn Marino tree label = NULL;
5118e4b17023SJohn Marino
5119e4b17023SJohn Marino for (i = 0; i < n; ++i)
5120e4b17023SJohn Marino {
5121e4b17023SJohn Marino tree cons = gimple_asm_label_op (stmt, i);
5122e4b17023SJohn Marino if (label_to_block (TREE_VALUE (cons)) == e->dest)
5123e4b17023SJohn Marino {
5124e4b17023SJohn Marino if (!label)
5125e4b17023SJohn Marino label = gimple_block_label (dest);
5126e4b17023SJohn Marino TREE_VALUE (cons) = label;
5127e4b17023SJohn Marino }
5128e4b17023SJohn Marino }
5129e4b17023SJohn Marino
5130e4b17023SJohn Marino /* If we didn't find any label matching the former edge in the
5131e4b17023SJohn Marino asm labels, we must be redirecting the fallthrough
5132e4b17023SJohn Marino edge. */
5133e4b17023SJohn Marino gcc_assert (label || (e->flags & EDGE_FALLTHRU));
5134e4b17023SJohn Marino }
5135e4b17023SJohn Marino break;
5136e4b17023SJohn Marino
5137e4b17023SJohn Marino case GIMPLE_RETURN:
5138e4b17023SJohn Marino gsi_remove (&gsi, true);
5139e4b17023SJohn Marino e->flags |= EDGE_FALLTHRU;
5140e4b17023SJohn Marino break;
5141e4b17023SJohn Marino
5142e4b17023SJohn Marino case GIMPLE_OMP_RETURN:
5143e4b17023SJohn Marino case GIMPLE_OMP_CONTINUE:
5144e4b17023SJohn Marino case GIMPLE_OMP_SECTIONS_SWITCH:
5145e4b17023SJohn Marino case GIMPLE_OMP_FOR:
5146e4b17023SJohn Marino /* The edges from OMP constructs can be simply redirected. */
5147e4b17023SJohn Marino break;
5148e4b17023SJohn Marino
5149e4b17023SJohn Marino case GIMPLE_EH_DISPATCH:
5150e4b17023SJohn Marino if (!(e->flags & EDGE_FALLTHRU))
5151e4b17023SJohn Marino redirect_eh_dispatch_edge (stmt, e, dest);
5152e4b17023SJohn Marino break;
5153e4b17023SJohn Marino
5154e4b17023SJohn Marino case GIMPLE_TRANSACTION:
5155e4b17023SJohn Marino /* The ABORT edge has a stored label associated with it, otherwise
5156e4b17023SJohn Marino the edges are simply redirectable. */
5157e4b17023SJohn Marino if (e->flags == 0)
5158e4b17023SJohn Marino gimple_transaction_set_label (stmt, gimple_block_label (dest));
5159e4b17023SJohn Marino break;
5160e4b17023SJohn Marino
5161e4b17023SJohn Marino default:
5162e4b17023SJohn Marino /* Otherwise it must be a fallthru edge, and we don't need to
5163e4b17023SJohn Marino do anything besides redirecting it. */
5164e4b17023SJohn Marino gcc_assert (e->flags & EDGE_FALLTHRU);
5165e4b17023SJohn Marino break;
5166e4b17023SJohn Marino }
5167e4b17023SJohn Marino
5168e4b17023SJohn Marino /* Update/insert PHI nodes as necessary. */
5169e4b17023SJohn Marino
5170e4b17023SJohn Marino /* Now update the edges in the CFG. */
5171e4b17023SJohn Marino e = ssa_redirect_edge (e, dest);
5172e4b17023SJohn Marino
5173e4b17023SJohn Marino return e;
5174e4b17023SJohn Marino }
5175e4b17023SJohn Marino
5176e4b17023SJohn Marino /* Returns true if it is possible to remove edge E by redirecting
5177e4b17023SJohn Marino it to the destination of the other edge from E->src. */
5178e4b17023SJohn Marino
5179e4b17023SJohn Marino static bool
gimple_can_remove_branch_p(const_edge e)5180e4b17023SJohn Marino gimple_can_remove_branch_p (const_edge e)
5181e4b17023SJohn Marino {
5182e4b17023SJohn Marino if (e->flags & (EDGE_ABNORMAL | EDGE_EH))
5183e4b17023SJohn Marino return false;
5184e4b17023SJohn Marino
5185e4b17023SJohn Marino return true;
5186e4b17023SJohn Marino }
5187e4b17023SJohn Marino
5188e4b17023SJohn Marino /* Simple wrapper, as we can always redirect fallthru edges. */
5189e4b17023SJohn Marino
5190e4b17023SJohn Marino static basic_block
gimple_redirect_edge_and_branch_force(edge e,basic_block dest)5191e4b17023SJohn Marino gimple_redirect_edge_and_branch_force (edge e, basic_block dest)
5192e4b17023SJohn Marino {
5193e4b17023SJohn Marino e = gimple_redirect_edge_and_branch (e, dest);
5194e4b17023SJohn Marino gcc_assert (e);
5195e4b17023SJohn Marino
5196e4b17023SJohn Marino return NULL;
5197e4b17023SJohn Marino }
5198e4b17023SJohn Marino
5199e4b17023SJohn Marino
5200e4b17023SJohn Marino /* Splits basic block BB after statement STMT (but at least after the
5201e4b17023SJohn Marino labels). If STMT is NULL, BB is split just after the labels. */
5202e4b17023SJohn Marino
5203e4b17023SJohn Marino static basic_block
gimple_split_block(basic_block bb,void * stmt)5204e4b17023SJohn Marino gimple_split_block (basic_block bb, void *stmt)
5205e4b17023SJohn Marino {
5206e4b17023SJohn Marino gimple_stmt_iterator gsi;
5207e4b17023SJohn Marino gimple_stmt_iterator gsi_tgt;
5208e4b17023SJohn Marino gimple act;
5209e4b17023SJohn Marino gimple_seq list;
5210e4b17023SJohn Marino basic_block new_bb;
5211e4b17023SJohn Marino edge e;
5212e4b17023SJohn Marino edge_iterator ei;
5213e4b17023SJohn Marino
5214e4b17023SJohn Marino new_bb = create_empty_bb (bb);
5215e4b17023SJohn Marino
5216e4b17023SJohn Marino /* Redirect the outgoing edges. */
5217e4b17023SJohn Marino new_bb->succs = bb->succs;
5218e4b17023SJohn Marino bb->succs = NULL;
5219e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, new_bb->succs)
5220e4b17023SJohn Marino e->src = new_bb;
5221e4b17023SJohn Marino
5222e4b17023SJohn Marino if (stmt && gimple_code ((gimple) stmt) == GIMPLE_LABEL)
5223e4b17023SJohn Marino stmt = NULL;
5224e4b17023SJohn Marino
5225e4b17023SJohn Marino /* Move everything from GSI to the new basic block. */
5226e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5227e4b17023SJohn Marino {
5228e4b17023SJohn Marino act = gsi_stmt (gsi);
5229e4b17023SJohn Marino if (gimple_code (act) == GIMPLE_LABEL)
5230e4b17023SJohn Marino continue;
5231e4b17023SJohn Marino
5232e4b17023SJohn Marino if (!stmt)
5233e4b17023SJohn Marino break;
5234e4b17023SJohn Marino
5235e4b17023SJohn Marino if (stmt == act)
5236e4b17023SJohn Marino {
5237e4b17023SJohn Marino gsi_next (&gsi);
5238e4b17023SJohn Marino break;
5239e4b17023SJohn Marino }
5240e4b17023SJohn Marino }
5241e4b17023SJohn Marino
5242e4b17023SJohn Marino if (gsi_end_p (gsi))
5243e4b17023SJohn Marino return new_bb;
5244e4b17023SJohn Marino
5245e4b17023SJohn Marino /* Split the statement list - avoid re-creating new containers as this
5246e4b17023SJohn Marino brings ugly quadratic memory consumption in the inliner.
5247e4b17023SJohn Marino (We are still quadratic since we need to update stmt BB pointers,
5248e4b17023SJohn Marino sadly.) */
5249e4b17023SJohn Marino list = gsi_split_seq_before (&gsi);
5250e4b17023SJohn Marino set_bb_seq (new_bb, list);
5251e4b17023SJohn Marino for (gsi_tgt = gsi_start (list);
5252e4b17023SJohn Marino !gsi_end_p (gsi_tgt); gsi_next (&gsi_tgt))
5253e4b17023SJohn Marino gimple_set_bb (gsi_stmt (gsi_tgt), new_bb);
5254e4b17023SJohn Marino
5255e4b17023SJohn Marino return new_bb;
5256e4b17023SJohn Marino }
5257e4b17023SJohn Marino
5258e4b17023SJohn Marino
5259e4b17023SJohn Marino /* Moves basic block BB after block AFTER. */
5260e4b17023SJohn Marino
5261e4b17023SJohn Marino static bool
gimple_move_block_after(basic_block bb,basic_block after)5262e4b17023SJohn Marino gimple_move_block_after (basic_block bb, basic_block after)
5263e4b17023SJohn Marino {
5264e4b17023SJohn Marino if (bb->prev_bb == after)
5265e4b17023SJohn Marino return true;
5266e4b17023SJohn Marino
5267e4b17023SJohn Marino unlink_block (bb);
5268e4b17023SJohn Marino link_block (bb, after);
5269e4b17023SJohn Marino
5270e4b17023SJohn Marino return true;
5271e4b17023SJohn Marino }
5272e4b17023SJohn Marino
5273e4b17023SJohn Marino
5274e4b17023SJohn Marino /* Return true if basic_block can be duplicated. */
5275e4b17023SJohn Marino
5276e4b17023SJohn Marino static bool
gimple_can_duplicate_bb_p(const_basic_block bb ATTRIBUTE_UNUSED)5277e4b17023SJohn Marino gimple_can_duplicate_bb_p (const_basic_block bb ATTRIBUTE_UNUSED)
5278e4b17023SJohn Marino {
5279e4b17023SJohn Marino return true;
5280e4b17023SJohn Marino }
5281e4b17023SJohn Marino
5282e4b17023SJohn Marino /* Create a duplicate of the basic block BB. NOTE: This does not
5283e4b17023SJohn Marino preserve SSA form. */
5284e4b17023SJohn Marino
5285e4b17023SJohn Marino static basic_block
gimple_duplicate_bb(basic_block bb)5286e4b17023SJohn Marino gimple_duplicate_bb (basic_block bb)
5287e4b17023SJohn Marino {
5288e4b17023SJohn Marino basic_block new_bb;
5289e4b17023SJohn Marino gimple_stmt_iterator gsi, gsi_tgt;
5290e4b17023SJohn Marino gimple_seq phis = phi_nodes (bb);
5291e4b17023SJohn Marino gimple phi, stmt, copy;
5292e4b17023SJohn Marino
5293e4b17023SJohn Marino new_bb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
5294e4b17023SJohn Marino
5295e4b17023SJohn Marino /* Copy the PHI nodes. We ignore PHI node arguments here because
5296e4b17023SJohn Marino the incoming edges have not been setup yet. */
5297e4b17023SJohn Marino for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5298e4b17023SJohn Marino {
5299e4b17023SJohn Marino phi = gsi_stmt (gsi);
5300e4b17023SJohn Marino copy = create_phi_node (gimple_phi_result (phi), new_bb);
5301e4b17023SJohn Marino create_new_def_for (gimple_phi_result (copy), copy,
5302e4b17023SJohn Marino gimple_phi_result_ptr (copy));
5303e4b17023SJohn Marino }
5304e4b17023SJohn Marino
5305e4b17023SJohn Marino gsi_tgt = gsi_start_bb (new_bb);
5306e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5307e4b17023SJohn Marino {
5308e4b17023SJohn Marino def_operand_p def_p;
5309e4b17023SJohn Marino ssa_op_iter op_iter;
5310e4b17023SJohn Marino tree lhs;
5311e4b17023SJohn Marino
5312e4b17023SJohn Marino stmt = gsi_stmt (gsi);
5313e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL)
5314e4b17023SJohn Marino continue;
5315e4b17023SJohn Marino
5316e4b17023SJohn Marino /* Don't duplicate label debug stmts. */
5317e4b17023SJohn Marino if (gimple_debug_bind_p (stmt)
5318e4b17023SJohn Marino && TREE_CODE (gimple_debug_bind_get_var (stmt))
5319e4b17023SJohn Marino == LABEL_DECL)
5320e4b17023SJohn Marino continue;
5321e4b17023SJohn Marino
5322e4b17023SJohn Marino /* Create a new copy of STMT and duplicate STMT's virtual
5323e4b17023SJohn Marino operands. */
5324e4b17023SJohn Marino copy = gimple_copy (stmt);
5325e4b17023SJohn Marino gsi_insert_after (&gsi_tgt, copy, GSI_NEW_STMT);
5326e4b17023SJohn Marino
5327e4b17023SJohn Marino maybe_duplicate_eh_stmt (copy, stmt);
5328e4b17023SJohn Marino gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
5329e4b17023SJohn Marino
5330e4b17023SJohn Marino /* When copying around a stmt writing into a local non-user
5331e4b17023SJohn Marino aggregate, make sure it won't share stack slot with other
5332e4b17023SJohn Marino vars. */
5333e4b17023SJohn Marino lhs = gimple_get_lhs (stmt);
5334e4b17023SJohn Marino if (lhs && TREE_CODE (lhs) != SSA_NAME)
5335e4b17023SJohn Marino {
5336e4b17023SJohn Marino tree base = get_base_address (lhs);
5337e4b17023SJohn Marino if (base
5338e4b17023SJohn Marino && (TREE_CODE (base) == VAR_DECL
5339e4b17023SJohn Marino || TREE_CODE (base) == RESULT_DECL)
5340e4b17023SJohn Marino && DECL_IGNORED_P (base)
5341e4b17023SJohn Marino && !TREE_STATIC (base)
5342e4b17023SJohn Marino && !DECL_EXTERNAL (base)
5343e4b17023SJohn Marino && (TREE_CODE (base) != VAR_DECL
5344e4b17023SJohn Marino || !DECL_HAS_VALUE_EXPR_P (base)))
5345e4b17023SJohn Marino DECL_NONSHAREABLE (base) = 1;
5346e4b17023SJohn Marino }
5347e4b17023SJohn Marino
5348e4b17023SJohn Marino /* Create new names for all the definitions created by COPY and
5349e4b17023SJohn Marino add replacement mappings for each new name. */
5350e4b17023SJohn Marino FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_ALL_DEFS)
5351e4b17023SJohn Marino create_new_def_for (DEF_FROM_PTR (def_p), copy, def_p);
5352e4b17023SJohn Marino }
5353e4b17023SJohn Marino
5354e4b17023SJohn Marino return new_bb;
5355e4b17023SJohn Marino }
5356e4b17023SJohn Marino
5357e4b17023SJohn Marino /* Adds phi node arguments for edge E_COPY after basic block duplication. */
5358e4b17023SJohn Marino
5359e4b17023SJohn Marino static void
add_phi_args_after_copy_edge(edge e_copy)5360e4b17023SJohn Marino add_phi_args_after_copy_edge (edge e_copy)
5361e4b17023SJohn Marino {
5362e4b17023SJohn Marino basic_block bb, bb_copy = e_copy->src, dest;
5363e4b17023SJohn Marino edge e;
5364e4b17023SJohn Marino edge_iterator ei;
5365e4b17023SJohn Marino gimple phi, phi_copy;
5366e4b17023SJohn Marino tree def;
5367e4b17023SJohn Marino gimple_stmt_iterator psi, psi_copy;
5368e4b17023SJohn Marino
5369e4b17023SJohn Marino if (gimple_seq_empty_p (phi_nodes (e_copy->dest)))
5370e4b17023SJohn Marino return;
5371e4b17023SJohn Marino
5372e4b17023SJohn Marino bb = bb_copy->flags & BB_DUPLICATED ? get_bb_original (bb_copy) : bb_copy;
5373e4b17023SJohn Marino
5374e4b17023SJohn Marino if (e_copy->dest->flags & BB_DUPLICATED)
5375e4b17023SJohn Marino dest = get_bb_original (e_copy->dest);
5376e4b17023SJohn Marino else
5377e4b17023SJohn Marino dest = e_copy->dest;
5378e4b17023SJohn Marino
5379e4b17023SJohn Marino e = find_edge (bb, dest);
5380e4b17023SJohn Marino if (!e)
5381e4b17023SJohn Marino {
5382e4b17023SJohn Marino /* During loop unrolling the target of the latch edge is copied.
5383e4b17023SJohn Marino In this case we are not looking for edge to dest, but to
5384e4b17023SJohn Marino duplicated block whose original was dest. */
5385e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
5386e4b17023SJohn Marino {
5387e4b17023SJohn Marino if ((e->dest->flags & BB_DUPLICATED)
5388e4b17023SJohn Marino && get_bb_original (e->dest) == dest)
5389e4b17023SJohn Marino break;
5390e4b17023SJohn Marino }
5391e4b17023SJohn Marino
5392e4b17023SJohn Marino gcc_assert (e != NULL);
5393e4b17023SJohn Marino }
5394e4b17023SJohn Marino
5395e4b17023SJohn Marino for (psi = gsi_start_phis (e->dest),
5396e4b17023SJohn Marino psi_copy = gsi_start_phis (e_copy->dest);
5397e4b17023SJohn Marino !gsi_end_p (psi);
5398e4b17023SJohn Marino gsi_next (&psi), gsi_next (&psi_copy))
5399e4b17023SJohn Marino {
5400e4b17023SJohn Marino phi = gsi_stmt (psi);
5401e4b17023SJohn Marino phi_copy = gsi_stmt (psi_copy);
5402e4b17023SJohn Marino def = PHI_ARG_DEF_FROM_EDGE (phi, e);
5403e4b17023SJohn Marino add_phi_arg (phi_copy, def, e_copy,
5404e4b17023SJohn Marino gimple_phi_arg_location_from_edge (phi, e));
5405e4b17023SJohn Marino }
5406e4b17023SJohn Marino }
5407e4b17023SJohn Marino
5408e4b17023SJohn Marino
5409e4b17023SJohn Marino /* Basic block BB_COPY was created by code duplication. Add phi node
5410e4b17023SJohn Marino arguments for edges going out of BB_COPY. The blocks that were
5411e4b17023SJohn Marino duplicated have BB_DUPLICATED set. */
5412e4b17023SJohn Marino
5413e4b17023SJohn Marino void
add_phi_args_after_copy_bb(basic_block bb_copy)5414e4b17023SJohn Marino add_phi_args_after_copy_bb (basic_block bb_copy)
5415e4b17023SJohn Marino {
5416e4b17023SJohn Marino edge e_copy;
5417e4b17023SJohn Marino edge_iterator ei;
5418e4b17023SJohn Marino
5419e4b17023SJohn Marino FOR_EACH_EDGE (e_copy, ei, bb_copy->succs)
5420e4b17023SJohn Marino {
5421e4b17023SJohn Marino add_phi_args_after_copy_edge (e_copy);
5422e4b17023SJohn Marino }
5423e4b17023SJohn Marino }
5424e4b17023SJohn Marino
5425e4b17023SJohn Marino /* Blocks in REGION_COPY array of length N_REGION were created by
5426e4b17023SJohn Marino duplication of basic blocks. Add phi node arguments for edges
5427e4b17023SJohn Marino going from these blocks. If E_COPY is not NULL, also add
5428e4b17023SJohn Marino phi node arguments for its destination.*/
5429e4b17023SJohn Marino
5430e4b17023SJohn Marino void
add_phi_args_after_copy(basic_block * region_copy,unsigned n_region,edge e_copy)5431e4b17023SJohn Marino add_phi_args_after_copy (basic_block *region_copy, unsigned n_region,
5432e4b17023SJohn Marino edge e_copy)
5433e4b17023SJohn Marino {
5434e4b17023SJohn Marino unsigned i;
5435e4b17023SJohn Marino
5436e4b17023SJohn Marino for (i = 0; i < n_region; i++)
5437e4b17023SJohn Marino region_copy[i]->flags |= BB_DUPLICATED;
5438e4b17023SJohn Marino
5439e4b17023SJohn Marino for (i = 0; i < n_region; i++)
5440e4b17023SJohn Marino add_phi_args_after_copy_bb (region_copy[i]);
5441e4b17023SJohn Marino if (e_copy)
5442e4b17023SJohn Marino add_phi_args_after_copy_edge (e_copy);
5443e4b17023SJohn Marino
5444e4b17023SJohn Marino for (i = 0; i < n_region; i++)
5445e4b17023SJohn Marino region_copy[i]->flags &= ~BB_DUPLICATED;
5446e4b17023SJohn Marino }
5447e4b17023SJohn Marino
5448e4b17023SJohn Marino /* Duplicates a REGION (set of N_REGION basic blocks) with just a single
5449e4b17023SJohn Marino important exit edge EXIT. By important we mean that no SSA name defined
5450e4b17023SJohn Marino inside region is live over the other exit edges of the region. All entry
5451e4b17023SJohn Marino edges to the region must go to ENTRY->dest. The edge ENTRY is redirected
5452e4b17023SJohn Marino to the duplicate of the region. SSA form, dominance and loop information
5453e4b17023SJohn Marino is updated. The new basic blocks are stored to REGION_COPY in the same
5454e4b17023SJohn Marino order as they had in REGION, provided that REGION_COPY is not NULL.
5455e4b17023SJohn Marino The function returns false if it is unable to copy the region,
5456e4b17023SJohn Marino true otherwise. */
5457e4b17023SJohn Marino
5458e4b17023SJohn Marino bool
gimple_duplicate_sese_region(edge entry,edge exit,basic_block * region,unsigned n_region,basic_block * region_copy)5459e4b17023SJohn Marino gimple_duplicate_sese_region (edge entry, edge exit,
5460e4b17023SJohn Marino basic_block *region, unsigned n_region,
5461e4b17023SJohn Marino basic_block *region_copy)
5462e4b17023SJohn Marino {
5463e4b17023SJohn Marino unsigned i;
5464e4b17023SJohn Marino bool free_region_copy = false, copying_header = false;
5465e4b17023SJohn Marino struct loop *loop = entry->dest->loop_father;
5466e4b17023SJohn Marino edge exit_copy;
5467e4b17023SJohn Marino VEC (basic_block, heap) *doms;
5468e4b17023SJohn Marino edge redirected;
5469e4b17023SJohn Marino int total_freq = 0, entry_freq = 0;
5470e4b17023SJohn Marino gcov_type total_count = 0, entry_count = 0;
5471e4b17023SJohn Marino
5472e4b17023SJohn Marino if (!can_copy_bbs_p (region, n_region))
5473e4b17023SJohn Marino return false;
5474e4b17023SJohn Marino
5475e4b17023SJohn Marino /* Some sanity checking. Note that we do not check for all possible
5476e4b17023SJohn Marino missuses of the functions. I.e. if you ask to copy something weird,
5477e4b17023SJohn Marino it will work, but the state of structures probably will not be
5478e4b17023SJohn Marino correct. */
5479e4b17023SJohn Marino for (i = 0; i < n_region; i++)
5480e4b17023SJohn Marino {
5481e4b17023SJohn Marino /* We do not handle subloops, i.e. all the blocks must belong to the
5482e4b17023SJohn Marino same loop. */
5483e4b17023SJohn Marino if (region[i]->loop_father != loop)
5484e4b17023SJohn Marino return false;
5485e4b17023SJohn Marino
5486e4b17023SJohn Marino if (region[i] != entry->dest
5487e4b17023SJohn Marino && region[i] == loop->header)
5488e4b17023SJohn Marino return false;
5489e4b17023SJohn Marino }
5490e4b17023SJohn Marino
5491e4b17023SJohn Marino set_loop_copy (loop, loop);
5492e4b17023SJohn Marino
5493e4b17023SJohn Marino /* In case the function is used for loop header copying (which is the primary
5494e4b17023SJohn Marino use), ensure that EXIT and its copy will be new latch and entry edges. */
5495e4b17023SJohn Marino if (loop->header == entry->dest)
5496e4b17023SJohn Marino {
5497e4b17023SJohn Marino copying_header = true;
5498e4b17023SJohn Marino set_loop_copy (loop, loop_outer (loop));
5499e4b17023SJohn Marino
5500e4b17023SJohn Marino if (!dominated_by_p (CDI_DOMINATORS, loop->latch, exit->src))
5501e4b17023SJohn Marino return false;
5502e4b17023SJohn Marino
5503e4b17023SJohn Marino for (i = 0; i < n_region; i++)
5504e4b17023SJohn Marino if (region[i] != exit->src
5505e4b17023SJohn Marino && dominated_by_p (CDI_DOMINATORS, region[i], exit->src))
5506e4b17023SJohn Marino return false;
5507e4b17023SJohn Marino }
5508e4b17023SJohn Marino
5509e4b17023SJohn Marino if (!region_copy)
5510e4b17023SJohn Marino {
5511e4b17023SJohn Marino region_copy = XNEWVEC (basic_block, n_region);
5512e4b17023SJohn Marino free_region_copy = true;
5513e4b17023SJohn Marino }
5514e4b17023SJohn Marino
5515e4b17023SJohn Marino gcc_assert (!need_ssa_update_p (cfun));
5516e4b17023SJohn Marino
5517e4b17023SJohn Marino /* Record blocks outside the region that are dominated by something
5518e4b17023SJohn Marino inside. */
5519e4b17023SJohn Marino doms = NULL;
5520e4b17023SJohn Marino initialize_original_copy_tables ();
5521e4b17023SJohn Marino
5522e4b17023SJohn Marino doms = get_dominated_by_region (CDI_DOMINATORS, region, n_region);
5523e4b17023SJohn Marino
5524e4b17023SJohn Marino if (entry->dest->count)
5525e4b17023SJohn Marino {
5526e4b17023SJohn Marino total_count = entry->dest->count;
5527e4b17023SJohn Marino entry_count = entry->count;
5528e4b17023SJohn Marino /* Fix up corner cases, to avoid division by zero or creation of negative
5529e4b17023SJohn Marino frequencies. */
5530e4b17023SJohn Marino if (entry_count > total_count)
5531e4b17023SJohn Marino entry_count = total_count;
5532e4b17023SJohn Marino }
5533e4b17023SJohn Marino else
5534e4b17023SJohn Marino {
5535e4b17023SJohn Marino total_freq = entry->dest->frequency;
5536e4b17023SJohn Marino entry_freq = EDGE_FREQUENCY (entry);
5537e4b17023SJohn Marino /* Fix up corner cases, to avoid division by zero or creation of negative
5538e4b17023SJohn Marino frequencies. */
5539e4b17023SJohn Marino if (total_freq == 0)
5540e4b17023SJohn Marino total_freq = 1;
5541e4b17023SJohn Marino else if (entry_freq > total_freq)
5542e4b17023SJohn Marino entry_freq = total_freq;
5543e4b17023SJohn Marino }
5544e4b17023SJohn Marino
5545e4b17023SJohn Marino copy_bbs (region, n_region, region_copy, &exit, 1, &exit_copy, loop,
5546e4b17023SJohn Marino split_edge_bb_loc (entry));
5547e4b17023SJohn Marino if (total_count)
5548e4b17023SJohn Marino {
5549e4b17023SJohn Marino scale_bbs_frequencies_gcov_type (region, n_region,
5550e4b17023SJohn Marino total_count - entry_count,
5551e4b17023SJohn Marino total_count);
5552e4b17023SJohn Marino scale_bbs_frequencies_gcov_type (region_copy, n_region, entry_count,
5553e4b17023SJohn Marino total_count);
5554e4b17023SJohn Marino }
5555e4b17023SJohn Marino else
5556e4b17023SJohn Marino {
5557e4b17023SJohn Marino scale_bbs_frequencies_int (region, n_region, total_freq - entry_freq,
5558e4b17023SJohn Marino total_freq);
5559e4b17023SJohn Marino scale_bbs_frequencies_int (region_copy, n_region, entry_freq, total_freq);
5560e4b17023SJohn Marino }
5561e4b17023SJohn Marino
5562e4b17023SJohn Marino if (copying_header)
5563e4b17023SJohn Marino {
5564e4b17023SJohn Marino loop->header = exit->dest;
5565e4b17023SJohn Marino loop->latch = exit->src;
5566e4b17023SJohn Marino }
5567e4b17023SJohn Marino
5568e4b17023SJohn Marino /* Redirect the entry and add the phi node arguments. */
5569e4b17023SJohn Marino redirected = redirect_edge_and_branch (entry, get_bb_copy (entry->dest));
5570e4b17023SJohn Marino gcc_assert (redirected != NULL);
5571e4b17023SJohn Marino flush_pending_stmts (entry);
5572e4b17023SJohn Marino
5573e4b17023SJohn Marino /* Concerning updating of dominators: We must recount dominators
5574e4b17023SJohn Marino for entry block and its copy. Anything that is outside of the
5575e4b17023SJohn Marino region, but was dominated by something inside needs recounting as
5576e4b17023SJohn Marino well. */
5577e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, entry->dest, entry->src);
5578e4b17023SJohn Marino VEC_safe_push (basic_block, heap, doms, get_bb_original (entry->dest));
5579e4b17023SJohn Marino iterate_fix_dominators (CDI_DOMINATORS, doms, false);
5580e4b17023SJohn Marino VEC_free (basic_block, heap, doms);
5581e4b17023SJohn Marino
5582e4b17023SJohn Marino /* Add the other PHI node arguments. */
5583e4b17023SJohn Marino add_phi_args_after_copy (region_copy, n_region, NULL);
5584e4b17023SJohn Marino
5585e4b17023SJohn Marino /* Update the SSA web. */
5586e4b17023SJohn Marino update_ssa (TODO_update_ssa);
5587e4b17023SJohn Marino
5588e4b17023SJohn Marino if (free_region_copy)
5589e4b17023SJohn Marino free (region_copy);
5590e4b17023SJohn Marino
5591e4b17023SJohn Marino free_original_copy_tables ();
5592e4b17023SJohn Marino return true;
5593e4b17023SJohn Marino }
5594e4b17023SJohn Marino
5595e4b17023SJohn Marino /* Duplicates REGION consisting of N_REGION blocks. The new blocks
5596e4b17023SJohn Marino are stored to REGION_COPY in the same order in that they appear
5597e4b17023SJohn Marino in REGION, if REGION_COPY is not NULL. ENTRY is the entry to
5598e4b17023SJohn Marino the region, EXIT an exit from it. The condition guarding EXIT
5599e4b17023SJohn Marino is moved to ENTRY. Returns true if duplication succeeds, false
5600e4b17023SJohn Marino otherwise.
5601e4b17023SJohn Marino
5602e4b17023SJohn Marino For example,
5603e4b17023SJohn Marino
5604e4b17023SJohn Marino some_code;
5605e4b17023SJohn Marino if (cond)
5606e4b17023SJohn Marino A;
5607e4b17023SJohn Marino else
5608e4b17023SJohn Marino B;
5609e4b17023SJohn Marino
5610e4b17023SJohn Marino is transformed to
5611e4b17023SJohn Marino
5612e4b17023SJohn Marino if (cond)
5613e4b17023SJohn Marino {
5614e4b17023SJohn Marino some_code;
5615e4b17023SJohn Marino A;
5616e4b17023SJohn Marino }
5617e4b17023SJohn Marino else
5618e4b17023SJohn Marino {
5619e4b17023SJohn Marino some_code;
5620e4b17023SJohn Marino B;
5621e4b17023SJohn Marino }
5622e4b17023SJohn Marino */
5623e4b17023SJohn Marino
5624e4b17023SJohn Marino bool
gimple_duplicate_sese_tail(edge entry ATTRIBUTE_UNUSED,edge exit ATTRIBUTE_UNUSED,basic_block * region ATTRIBUTE_UNUSED,unsigned n_region ATTRIBUTE_UNUSED,basic_block * region_copy ATTRIBUTE_UNUSED)5625e4b17023SJohn Marino gimple_duplicate_sese_tail (edge entry ATTRIBUTE_UNUSED, edge exit ATTRIBUTE_UNUSED,
5626e4b17023SJohn Marino basic_block *region ATTRIBUTE_UNUSED, unsigned n_region ATTRIBUTE_UNUSED,
5627e4b17023SJohn Marino basic_block *region_copy ATTRIBUTE_UNUSED)
5628e4b17023SJohn Marino {
5629e4b17023SJohn Marino unsigned i;
5630e4b17023SJohn Marino bool free_region_copy = false;
5631e4b17023SJohn Marino struct loop *loop = exit->dest->loop_father;
5632e4b17023SJohn Marino struct loop *orig_loop = entry->dest->loop_father;
5633e4b17023SJohn Marino basic_block switch_bb, entry_bb, nentry_bb;
5634e4b17023SJohn Marino VEC (basic_block, heap) *doms;
5635e4b17023SJohn Marino int total_freq = 0, exit_freq = 0;
5636e4b17023SJohn Marino gcov_type total_count = 0, exit_count = 0;
5637e4b17023SJohn Marino edge exits[2], nexits[2], e;
5638e4b17023SJohn Marino gimple_stmt_iterator gsi;
5639e4b17023SJohn Marino gimple cond_stmt;
5640e4b17023SJohn Marino edge sorig, snew;
5641e4b17023SJohn Marino basic_block exit_bb;
5642e4b17023SJohn Marino gimple_stmt_iterator psi;
5643e4b17023SJohn Marino gimple phi;
5644e4b17023SJohn Marino tree def;
5645e4b17023SJohn Marino
5646e4b17023SJohn Marino gcc_assert (EDGE_COUNT (exit->src->succs) == 2);
5647e4b17023SJohn Marino exits[0] = exit;
5648e4b17023SJohn Marino exits[1] = EDGE_SUCC (exit->src, EDGE_SUCC (exit->src, 0) == exit);
5649e4b17023SJohn Marino
5650e4b17023SJohn Marino if (!can_copy_bbs_p (region, n_region))
5651e4b17023SJohn Marino return false;
5652e4b17023SJohn Marino
5653e4b17023SJohn Marino initialize_original_copy_tables ();
5654e4b17023SJohn Marino set_loop_copy (orig_loop, loop);
5655e4b17023SJohn Marino duplicate_subloops (orig_loop, loop);
5656e4b17023SJohn Marino
5657e4b17023SJohn Marino if (!region_copy)
5658e4b17023SJohn Marino {
5659e4b17023SJohn Marino region_copy = XNEWVEC (basic_block, n_region);
5660e4b17023SJohn Marino free_region_copy = true;
5661e4b17023SJohn Marino }
5662e4b17023SJohn Marino
5663e4b17023SJohn Marino gcc_assert (!need_ssa_update_p (cfun));
5664e4b17023SJohn Marino
5665e4b17023SJohn Marino /* Record blocks outside the region that are dominated by something
5666e4b17023SJohn Marino inside. */
5667e4b17023SJohn Marino doms = get_dominated_by_region (CDI_DOMINATORS, region, n_region);
5668e4b17023SJohn Marino
5669e4b17023SJohn Marino if (exit->src->count)
5670e4b17023SJohn Marino {
5671e4b17023SJohn Marino total_count = exit->src->count;
5672e4b17023SJohn Marino exit_count = exit->count;
5673e4b17023SJohn Marino /* Fix up corner cases, to avoid division by zero or creation of negative
5674e4b17023SJohn Marino frequencies. */
5675e4b17023SJohn Marino if (exit_count > total_count)
5676e4b17023SJohn Marino exit_count = total_count;
5677e4b17023SJohn Marino }
5678e4b17023SJohn Marino else
5679e4b17023SJohn Marino {
5680e4b17023SJohn Marino total_freq = exit->src->frequency;
5681e4b17023SJohn Marino exit_freq = EDGE_FREQUENCY (exit);
5682e4b17023SJohn Marino /* Fix up corner cases, to avoid division by zero or creation of negative
5683e4b17023SJohn Marino frequencies. */
5684e4b17023SJohn Marino if (total_freq == 0)
5685e4b17023SJohn Marino total_freq = 1;
5686e4b17023SJohn Marino if (exit_freq > total_freq)
5687e4b17023SJohn Marino exit_freq = total_freq;
5688e4b17023SJohn Marino }
5689e4b17023SJohn Marino
5690e4b17023SJohn Marino copy_bbs (region, n_region, region_copy, exits, 2, nexits, orig_loop,
5691e4b17023SJohn Marino split_edge_bb_loc (exit));
5692e4b17023SJohn Marino if (total_count)
5693e4b17023SJohn Marino {
5694e4b17023SJohn Marino scale_bbs_frequencies_gcov_type (region, n_region,
5695e4b17023SJohn Marino total_count - exit_count,
5696e4b17023SJohn Marino total_count);
5697e4b17023SJohn Marino scale_bbs_frequencies_gcov_type (region_copy, n_region, exit_count,
5698e4b17023SJohn Marino total_count);
5699e4b17023SJohn Marino }
5700e4b17023SJohn Marino else
5701e4b17023SJohn Marino {
5702e4b17023SJohn Marino scale_bbs_frequencies_int (region, n_region, total_freq - exit_freq,
5703e4b17023SJohn Marino total_freq);
5704e4b17023SJohn Marino scale_bbs_frequencies_int (region_copy, n_region, exit_freq, total_freq);
5705e4b17023SJohn Marino }
5706e4b17023SJohn Marino
5707e4b17023SJohn Marino /* Create the switch block, and put the exit condition to it. */
5708e4b17023SJohn Marino entry_bb = entry->dest;
5709e4b17023SJohn Marino nentry_bb = get_bb_copy (entry_bb);
5710e4b17023SJohn Marino if (!last_stmt (entry->src)
5711e4b17023SJohn Marino || !stmt_ends_bb_p (last_stmt (entry->src)))
5712e4b17023SJohn Marino switch_bb = entry->src;
5713e4b17023SJohn Marino else
5714e4b17023SJohn Marino switch_bb = split_edge (entry);
5715e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, nentry_bb, switch_bb);
5716e4b17023SJohn Marino
5717e4b17023SJohn Marino gsi = gsi_last_bb (switch_bb);
5718e4b17023SJohn Marino cond_stmt = last_stmt (exit->src);
5719e4b17023SJohn Marino gcc_assert (gimple_code (cond_stmt) == GIMPLE_COND);
5720e4b17023SJohn Marino cond_stmt = gimple_copy (cond_stmt);
5721e4b17023SJohn Marino
5722e4b17023SJohn Marino gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
5723e4b17023SJohn Marino
5724e4b17023SJohn Marino sorig = single_succ_edge (switch_bb);
5725e4b17023SJohn Marino sorig->flags = exits[1]->flags;
5726e4b17023SJohn Marino snew = make_edge (switch_bb, nentry_bb, exits[0]->flags);
5727e4b17023SJohn Marino
5728e4b17023SJohn Marino /* Register the new edge from SWITCH_BB in loop exit lists. */
5729e4b17023SJohn Marino rescan_loop_exit (snew, true, false);
5730e4b17023SJohn Marino
5731e4b17023SJohn Marino /* Add the PHI node arguments. */
5732e4b17023SJohn Marino add_phi_args_after_copy (region_copy, n_region, snew);
5733e4b17023SJohn Marino
5734e4b17023SJohn Marino /* Get rid of now superfluous conditions and associated edges (and phi node
5735e4b17023SJohn Marino arguments). */
5736e4b17023SJohn Marino exit_bb = exit->dest;
5737e4b17023SJohn Marino
5738e4b17023SJohn Marino e = redirect_edge_and_branch (exits[0], exits[1]->dest);
5739e4b17023SJohn Marino PENDING_STMT (e) = NULL;
5740e4b17023SJohn Marino
5741e4b17023SJohn Marino /* The latch of ORIG_LOOP was copied, and so was the backedge
5742e4b17023SJohn Marino to the original header. We redirect this backedge to EXIT_BB. */
5743e4b17023SJohn Marino for (i = 0; i < n_region; i++)
5744e4b17023SJohn Marino if (get_bb_original (region_copy[i]) == orig_loop->latch)
5745e4b17023SJohn Marino {
5746e4b17023SJohn Marino gcc_assert (single_succ_edge (region_copy[i]));
5747e4b17023SJohn Marino e = redirect_edge_and_branch (single_succ_edge (region_copy[i]), exit_bb);
5748e4b17023SJohn Marino PENDING_STMT (e) = NULL;
5749e4b17023SJohn Marino for (psi = gsi_start_phis (exit_bb);
5750e4b17023SJohn Marino !gsi_end_p (psi);
5751e4b17023SJohn Marino gsi_next (&psi))
5752e4b17023SJohn Marino {
5753e4b17023SJohn Marino phi = gsi_stmt (psi);
5754e4b17023SJohn Marino def = PHI_ARG_DEF (phi, nexits[0]->dest_idx);
5755e4b17023SJohn Marino add_phi_arg (phi, def, e, gimple_phi_arg_location_from_edge (phi, e));
5756e4b17023SJohn Marino }
5757e4b17023SJohn Marino }
5758e4b17023SJohn Marino e = redirect_edge_and_branch (nexits[0], nexits[1]->dest);
5759e4b17023SJohn Marino PENDING_STMT (e) = NULL;
5760e4b17023SJohn Marino
5761e4b17023SJohn Marino /* Anything that is outside of the region, but was dominated by something
5762e4b17023SJohn Marino inside needs to update dominance info. */
5763e4b17023SJohn Marino iterate_fix_dominators (CDI_DOMINATORS, doms, false);
5764e4b17023SJohn Marino VEC_free (basic_block, heap, doms);
5765e4b17023SJohn Marino /* Update the SSA web. */
5766e4b17023SJohn Marino update_ssa (TODO_update_ssa);
5767e4b17023SJohn Marino
5768e4b17023SJohn Marino if (free_region_copy)
5769e4b17023SJohn Marino free (region_copy);
5770e4b17023SJohn Marino
5771e4b17023SJohn Marino free_original_copy_tables ();
5772e4b17023SJohn Marino return true;
5773e4b17023SJohn Marino }
5774e4b17023SJohn Marino
5775e4b17023SJohn Marino /* Add all the blocks dominated by ENTRY to the array BBS_P. Stop
5776e4b17023SJohn Marino adding blocks when the dominator traversal reaches EXIT. This
5777e4b17023SJohn Marino function silently assumes that ENTRY strictly dominates EXIT. */
5778e4b17023SJohn Marino
5779e4b17023SJohn Marino void
gather_blocks_in_sese_region(basic_block entry,basic_block exit,VEC (basic_block,heap)** bbs_p)5780e4b17023SJohn Marino gather_blocks_in_sese_region (basic_block entry, basic_block exit,
5781e4b17023SJohn Marino VEC(basic_block,heap) **bbs_p)
5782e4b17023SJohn Marino {
5783e4b17023SJohn Marino basic_block son;
5784e4b17023SJohn Marino
5785e4b17023SJohn Marino for (son = first_dom_son (CDI_DOMINATORS, entry);
5786e4b17023SJohn Marino son;
5787e4b17023SJohn Marino son = next_dom_son (CDI_DOMINATORS, son))
5788e4b17023SJohn Marino {
5789e4b17023SJohn Marino VEC_safe_push (basic_block, heap, *bbs_p, son);
5790e4b17023SJohn Marino if (son != exit)
5791e4b17023SJohn Marino gather_blocks_in_sese_region (son, exit, bbs_p);
5792e4b17023SJohn Marino }
5793e4b17023SJohn Marino }
5794e4b17023SJohn Marino
5795e4b17023SJohn Marino /* Replaces *TP with a duplicate (belonging to function TO_CONTEXT).
5796e4b17023SJohn Marino The duplicates are recorded in VARS_MAP. */
5797e4b17023SJohn Marino
5798e4b17023SJohn Marino static void
replace_by_duplicate_decl(tree * tp,struct pointer_map_t * vars_map,tree to_context)5799e4b17023SJohn Marino replace_by_duplicate_decl (tree *tp, struct pointer_map_t *vars_map,
5800e4b17023SJohn Marino tree to_context)
5801e4b17023SJohn Marino {
5802e4b17023SJohn Marino tree t = *tp, new_t;
5803e4b17023SJohn Marino struct function *f = DECL_STRUCT_FUNCTION (to_context);
5804e4b17023SJohn Marino void **loc;
5805e4b17023SJohn Marino
5806e4b17023SJohn Marino if (DECL_CONTEXT (t) == to_context)
5807e4b17023SJohn Marino return;
5808e4b17023SJohn Marino
5809e4b17023SJohn Marino loc = pointer_map_contains (vars_map, t);
5810e4b17023SJohn Marino
5811e4b17023SJohn Marino if (!loc)
5812e4b17023SJohn Marino {
5813e4b17023SJohn Marino loc = pointer_map_insert (vars_map, t);
5814e4b17023SJohn Marino
5815e4b17023SJohn Marino if (SSA_VAR_P (t))
5816e4b17023SJohn Marino {
5817e4b17023SJohn Marino new_t = copy_var_decl (t, DECL_NAME (t), TREE_TYPE (t));
5818e4b17023SJohn Marino add_local_decl (f, new_t);
5819e4b17023SJohn Marino }
5820e4b17023SJohn Marino else
5821e4b17023SJohn Marino {
5822e4b17023SJohn Marino gcc_assert (TREE_CODE (t) == CONST_DECL);
5823e4b17023SJohn Marino new_t = copy_node (t);
5824e4b17023SJohn Marino }
5825e4b17023SJohn Marino DECL_CONTEXT (new_t) = to_context;
5826e4b17023SJohn Marino
5827e4b17023SJohn Marino *loc = new_t;
5828e4b17023SJohn Marino }
5829e4b17023SJohn Marino else
5830e4b17023SJohn Marino new_t = (tree) *loc;
5831e4b17023SJohn Marino
5832e4b17023SJohn Marino *tp = new_t;
5833e4b17023SJohn Marino }
5834e4b17023SJohn Marino
5835e4b17023SJohn Marino
5836e4b17023SJohn Marino /* Creates an ssa name in TO_CONTEXT equivalent to NAME.
5837e4b17023SJohn Marino VARS_MAP maps old ssa names and var_decls to the new ones. */
5838e4b17023SJohn Marino
5839e4b17023SJohn Marino static tree
replace_ssa_name(tree name,struct pointer_map_t * vars_map,tree to_context)5840e4b17023SJohn Marino replace_ssa_name (tree name, struct pointer_map_t *vars_map,
5841e4b17023SJohn Marino tree to_context)
5842e4b17023SJohn Marino {
5843e4b17023SJohn Marino void **loc;
5844e4b17023SJohn Marino tree new_name, decl = SSA_NAME_VAR (name);
5845e4b17023SJohn Marino
5846e4b17023SJohn Marino gcc_assert (is_gimple_reg (name));
5847e4b17023SJohn Marino
5848e4b17023SJohn Marino loc = pointer_map_contains (vars_map, name);
5849e4b17023SJohn Marino
5850e4b17023SJohn Marino if (!loc)
5851e4b17023SJohn Marino {
5852e4b17023SJohn Marino replace_by_duplicate_decl (&decl, vars_map, to_context);
5853e4b17023SJohn Marino
5854e4b17023SJohn Marino push_cfun (DECL_STRUCT_FUNCTION (to_context));
5855e4b17023SJohn Marino if (gimple_in_ssa_p (cfun))
5856e4b17023SJohn Marino add_referenced_var (decl);
5857e4b17023SJohn Marino
5858e4b17023SJohn Marino new_name = make_ssa_name (decl, SSA_NAME_DEF_STMT (name));
5859e4b17023SJohn Marino if (SSA_NAME_IS_DEFAULT_DEF (name))
5860e4b17023SJohn Marino set_default_def (decl, new_name);
5861e4b17023SJohn Marino pop_cfun ();
5862e4b17023SJohn Marino
5863e4b17023SJohn Marino loc = pointer_map_insert (vars_map, name);
5864e4b17023SJohn Marino *loc = new_name;
5865e4b17023SJohn Marino }
5866e4b17023SJohn Marino else
5867e4b17023SJohn Marino new_name = (tree) *loc;
5868e4b17023SJohn Marino
5869e4b17023SJohn Marino return new_name;
5870e4b17023SJohn Marino }
5871e4b17023SJohn Marino
5872e4b17023SJohn Marino struct move_stmt_d
5873e4b17023SJohn Marino {
5874e4b17023SJohn Marino tree orig_block;
5875e4b17023SJohn Marino tree new_block;
5876e4b17023SJohn Marino tree from_context;
5877e4b17023SJohn Marino tree to_context;
5878e4b17023SJohn Marino struct pointer_map_t *vars_map;
5879e4b17023SJohn Marino htab_t new_label_map;
5880e4b17023SJohn Marino struct pointer_map_t *eh_map;
5881e4b17023SJohn Marino bool remap_decls_p;
5882e4b17023SJohn Marino };
5883e4b17023SJohn Marino
5884e4b17023SJohn Marino /* Helper for move_block_to_fn. Set TREE_BLOCK in every expression
5885e4b17023SJohn Marino contained in *TP if it has been ORIG_BLOCK previously and change the
5886e4b17023SJohn Marino DECL_CONTEXT of every local variable referenced in *TP. */
5887e4b17023SJohn Marino
5888e4b17023SJohn Marino static tree
move_stmt_op(tree * tp,int * walk_subtrees,void * data)5889e4b17023SJohn Marino move_stmt_op (tree *tp, int *walk_subtrees, void *data)
5890e4b17023SJohn Marino {
5891e4b17023SJohn Marino struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
5892e4b17023SJohn Marino struct move_stmt_d *p = (struct move_stmt_d *) wi->info;
5893e4b17023SJohn Marino tree t = *tp;
5894e4b17023SJohn Marino
5895e4b17023SJohn Marino if (EXPR_P (t))
5896e4b17023SJohn Marino /* We should never have TREE_BLOCK set on non-statements. */
5897e4b17023SJohn Marino gcc_assert (!TREE_BLOCK (t));
5898e4b17023SJohn Marino
5899e4b17023SJohn Marino else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
5900e4b17023SJohn Marino {
5901e4b17023SJohn Marino if (TREE_CODE (t) == SSA_NAME)
5902e4b17023SJohn Marino *tp = replace_ssa_name (t, p->vars_map, p->to_context);
5903e4b17023SJohn Marino else if (TREE_CODE (t) == LABEL_DECL)
5904e4b17023SJohn Marino {
5905e4b17023SJohn Marino if (p->new_label_map)
5906e4b17023SJohn Marino {
5907e4b17023SJohn Marino struct tree_map in, *out;
5908e4b17023SJohn Marino in.base.from = t;
5909e4b17023SJohn Marino out = (struct tree_map *)
5910e4b17023SJohn Marino htab_find_with_hash (p->new_label_map, &in, DECL_UID (t));
5911e4b17023SJohn Marino if (out)
5912e4b17023SJohn Marino *tp = t = out->to;
5913e4b17023SJohn Marino }
5914e4b17023SJohn Marino
5915e4b17023SJohn Marino DECL_CONTEXT (t) = p->to_context;
5916e4b17023SJohn Marino }
5917e4b17023SJohn Marino else if (p->remap_decls_p)
5918e4b17023SJohn Marino {
5919e4b17023SJohn Marino /* Replace T with its duplicate. T should no longer appear in the
5920e4b17023SJohn Marino parent function, so this looks wasteful; however, it may appear
5921e4b17023SJohn Marino in referenced_vars, and more importantly, as virtual operands of
5922e4b17023SJohn Marino statements, and in alias lists of other variables. It would be
5923e4b17023SJohn Marino quite difficult to expunge it from all those places. ??? It might
5924e4b17023SJohn Marino suffice to do this for addressable variables. */
5925e4b17023SJohn Marino if ((TREE_CODE (t) == VAR_DECL
5926e4b17023SJohn Marino && !is_global_var (t))
5927e4b17023SJohn Marino || TREE_CODE (t) == CONST_DECL)
5928e4b17023SJohn Marino replace_by_duplicate_decl (tp, p->vars_map, p->to_context);
5929e4b17023SJohn Marino
5930e4b17023SJohn Marino if (SSA_VAR_P (t)
5931e4b17023SJohn Marino && gimple_in_ssa_p (cfun))
5932e4b17023SJohn Marino {
5933e4b17023SJohn Marino push_cfun (DECL_STRUCT_FUNCTION (p->to_context));
5934e4b17023SJohn Marino add_referenced_var (*tp);
5935e4b17023SJohn Marino pop_cfun ();
5936e4b17023SJohn Marino }
5937e4b17023SJohn Marino }
5938e4b17023SJohn Marino *walk_subtrees = 0;
5939e4b17023SJohn Marino }
5940e4b17023SJohn Marino else if (TYPE_P (t))
5941e4b17023SJohn Marino *walk_subtrees = 0;
5942e4b17023SJohn Marino
5943e4b17023SJohn Marino return NULL_TREE;
5944e4b17023SJohn Marino }
5945e4b17023SJohn Marino
5946e4b17023SJohn Marino /* Helper for move_stmt_r. Given an EH region number for the source
5947e4b17023SJohn Marino function, map that to the duplicate EH regio number in the dest. */
5948e4b17023SJohn Marino
5949e4b17023SJohn Marino static int
move_stmt_eh_region_nr(int old_nr,struct move_stmt_d * p)5950e4b17023SJohn Marino move_stmt_eh_region_nr (int old_nr, struct move_stmt_d *p)
5951e4b17023SJohn Marino {
5952e4b17023SJohn Marino eh_region old_r, new_r;
5953e4b17023SJohn Marino void **slot;
5954e4b17023SJohn Marino
5955e4b17023SJohn Marino old_r = get_eh_region_from_number (old_nr);
5956e4b17023SJohn Marino slot = pointer_map_contains (p->eh_map, old_r);
5957e4b17023SJohn Marino new_r = (eh_region) *slot;
5958e4b17023SJohn Marino
5959e4b17023SJohn Marino return new_r->index;
5960e4b17023SJohn Marino }
5961e4b17023SJohn Marino
5962e4b17023SJohn Marino /* Similar, but operate on INTEGER_CSTs. */
5963e4b17023SJohn Marino
5964e4b17023SJohn Marino static tree
move_stmt_eh_region_tree_nr(tree old_t_nr,struct move_stmt_d * p)5965e4b17023SJohn Marino move_stmt_eh_region_tree_nr (tree old_t_nr, struct move_stmt_d *p)
5966e4b17023SJohn Marino {
5967e4b17023SJohn Marino int old_nr, new_nr;
5968e4b17023SJohn Marino
5969e4b17023SJohn Marino old_nr = tree_low_cst (old_t_nr, 0);
5970e4b17023SJohn Marino new_nr = move_stmt_eh_region_nr (old_nr, p);
5971e4b17023SJohn Marino
5972e4b17023SJohn Marino return build_int_cst (integer_type_node, new_nr);
5973e4b17023SJohn Marino }
5974e4b17023SJohn Marino
5975e4b17023SJohn Marino /* Like move_stmt_op, but for gimple statements.
5976e4b17023SJohn Marino
5977e4b17023SJohn Marino Helper for move_block_to_fn. Set GIMPLE_BLOCK in every expression
5978e4b17023SJohn Marino contained in the current statement in *GSI_P and change the
5979e4b17023SJohn Marino DECL_CONTEXT of every local variable referenced in the current
5980e4b17023SJohn Marino statement. */
5981e4b17023SJohn Marino
5982e4b17023SJohn Marino static tree
move_stmt_r(gimple_stmt_iterator * gsi_p,bool * handled_ops_p,struct walk_stmt_info * wi)5983e4b17023SJohn Marino move_stmt_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
5984e4b17023SJohn Marino struct walk_stmt_info *wi)
5985e4b17023SJohn Marino {
5986e4b17023SJohn Marino struct move_stmt_d *p = (struct move_stmt_d *) wi->info;
5987e4b17023SJohn Marino gimple stmt = gsi_stmt (*gsi_p);
5988e4b17023SJohn Marino tree block = gimple_block (stmt);
5989e4b17023SJohn Marino
5990e4b17023SJohn Marino if (p->orig_block == NULL_TREE
5991e4b17023SJohn Marino || block == p->orig_block
5992e4b17023SJohn Marino || block == NULL_TREE)
5993e4b17023SJohn Marino gimple_set_block (stmt, p->new_block);
5994e4b17023SJohn Marino #ifdef ENABLE_CHECKING
5995e4b17023SJohn Marino else if (block != p->new_block)
5996e4b17023SJohn Marino {
5997e4b17023SJohn Marino while (block && block != p->orig_block)
5998e4b17023SJohn Marino block = BLOCK_SUPERCONTEXT (block);
5999e4b17023SJohn Marino gcc_assert (block);
6000e4b17023SJohn Marino }
6001e4b17023SJohn Marino #endif
6002e4b17023SJohn Marino
6003e4b17023SJohn Marino switch (gimple_code (stmt))
6004e4b17023SJohn Marino {
6005e4b17023SJohn Marino case GIMPLE_CALL:
6006e4b17023SJohn Marino /* Remap the region numbers for __builtin_eh_{pointer,filter}. */
6007e4b17023SJohn Marino {
6008e4b17023SJohn Marino tree r, fndecl = gimple_call_fndecl (stmt);
6009e4b17023SJohn Marino if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
6010e4b17023SJohn Marino switch (DECL_FUNCTION_CODE (fndecl))
6011e4b17023SJohn Marino {
6012e4b17023SJohn Marino case BUILT_IN_EH_COPY_VALUES:
6013e4b17023SJohn Marino r = gimple_call_arg (stmt, 1);
6014e4b17023SJohn Marino r = move_stmt_eh_region_tree_nr (r, p);
6015e4b17023SJohn Marino gimple_call_set_arg (stmt, 1, r);
6016e4b17023SJohn Marino /* FALLTHRU */
6017e4b17023SJohn Marino
6018e4b17023SJohn Marino case BUILT_IN_EH_POINTER:
6019e4b17023SJohn Marino case BUILT_IN_EH_FILTER:
6020e4b17023SJohn Marino r = gimple_call_arg (stmt, 0);
6021e4b17023SJohn Marino r = move_stmt_eh_region_tree_nr (r, p);
6022e4b17023SJohn Marino gimple_call_set_arg (stmt, 0, r);
6023e4b17023SJohn Marino break;
6024e4b17023SJohn Marino
6025e4b17023SJohn Marino default:
6026e4b17023SJohn Marino break;
6027e4b17023SJohn Marino }
6028e4b17023SJohn Marino }
6029e4b17023SJohn Marino break;
6030e4b17023SJohn Marino
6031e4b17023SJohn Marino case GIMPLE_RESX:
6032e4b17023SJohn Marino {
6033e4b17023SJohn Marino int r = gimple_resx_region (stmt);
6034e4b17023SJohn Marino r = move_stmt_eh_region_nr (r, p);
6035e4b17023SJohn Marino gimple_resx_set_region (stmt, r);
6036e4b17023SJohn Marino }
6037e4b17023SJohn Marino break;
6038e4b17023SJohn Marino
6039e4b17023SJohn Marino case GIMPLE_EH_DISPATCH:
6040e4b17023SJohn Marino {
6041e4b17023SJohn Marino int r = gimple_eh_dispatch_region (stmt);
6042e4b17023SJohn Marino r = move_stmt_eh_region_nr (r, p);
6043e4b17023SJohn Marino gimple_eh_dispatch_set_region (stmt, r);
6044e4b17023SJohn Marino }
6045e4b17023SJohn Marino break;
6046e4b17023SJohn Marino
6047e4b17023SJohn Marino case GIMPLE_OMP_RETURN:
6048e4b17023SJohn Marino case GIMPLE_OMP_CONTINUE:
6049e4b17023SJohn Marino break;
6050e4b17023SJohn Marino default:
6051e4b17023SJohn Marino if (is_gimple_omp (stmt))
6052e4b17023SJohn Marino {
6053e4b17023SJohn Marino /* Do not remap variables inside OMP directives. Variables
6054e4b17023SJohn Marino referenced in clauses and directive header belong to the
6055e4b17023SJohn Marino parent function and should not be moved into the child
6056e4b17023SJohn Marino function. */
6057e4b17023SJohn Marino bool save_remap_decls_p = p->remap_decls_p;
6058e4b17023SJohn Marino p->remap_decls_p = false;
6059e4b17023SJohn Marino *handled_ops_p = true;
6060e4b17023SJohn Marino
6061e4b17023SJohn Marino walk_gimple_seq (gimple_omp_body (stmt), move_stmt_r,
6062e4b17023SJohn Marino move_stmt_op, wi);
6063e4b17023SJohn Marino
6064e4b17023SJohn Marino p->remap_decls_p = save_remap_decls_p;
6065e4b17023SJohn Marino }
6066e4b17023SJohn Marino break;
6067e4b17023SJohn Marino }
6068e4b17023SJohn Marino
6069e4b17023SJohn Marino return NULL_TREE;
6070e4b17023SJohn Marino }
6071e4b17023SJohn Marino
6072e4b17023SJohn Marino /* Move basic block BB from function CFUN to function DEST_FN. The
6073e4b17023SJohn Marino block is moved out of the original linked list and placed after
6074e4b17023SJohn Marino block AFTER in the new list. Also, the block is removed from the
6075e4b17023SJohn Marino original array of blocks and placed in DEST_FN's array of blocks.
6076e4b17023SJohn Marino If UPDATE_EDGE_COUNT_P is true, the edge counts on both CFGs is
6077e4b17023SJohn Marino updated to reflect the moved edges.
6078e4b17023SJohn Marino
6079e4b17023SJohn Marino The local variables are remapped to new instances, VARS_MAP is used
6080e4b17023SJohn Marino to record the mapping. */
6081e4b17023SJohn Marino
6082e4b17023SJohn Marino static void
move_block_to_fn(struct function * dest_cfun,basic_block bb,basic_block after,bool update_edge_count_p,struct move_stmt_d * d)6083e4b17023SJohn Marino move_block_to_fn (struct function *dest_cfun, basic_block bb,
6084e4b17023SJohn Marino basic_block after, bool update_edge_count_p,
6085e4b17023SJohn Marino struct move_stmt_d *d)
6086e4b17023SJohn Marino {
6087e4b17023SJohn Marino struct control_flow_graph *cfg;
6088e4b17023SJohn Marino edge_iterator ei;
6089e4b17023SJohn Marino edge e;
6090e4b17023SJohn Marino gimple_stmt_iterator si;
6091e4b17023SJohn Marino unsigned old_len, new_len;
6092e4b17023SJohn Marino
6093e4b17023SJohn Marino /* Remove BB from dominance structures. */
6094e4b17023SJohn Marino delete_from_dominance_info (CDI_DOMINATORS, bb);
6095e4b17023SJohn Marino if (current_loops)
6096e4b17023SJohn Marino remove_bb_from_loops (bb);
6097e4b17023SJohn Marino
6098e4b17023SJohn Marino /* Link BB to the new linked list. */
6099e4b17023SJohn Marino move_block_after (bb, after);
6100e4b17023SJohn Marino
6101e4b17023SJohn Marino /* Update the edge count in the corresponding flowgraphs. */
6102e4b17023SJohn Marino if (update_edge_count_p)
6103e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
6104e4b17023SJohn Marino {
6105e4b17023SJohn Marino cfun->cfg->x_n_edges--;
6106e4b17023SJohn Marino dest_cfun->cfg->x_n_edges++;
6107e4b17023SJohn Marino }
6108e4b17023SJohn Marino
6109e4b17023SJohn Marino /* Remove BB from the original basic block array. */
6110e4b17023SJohn Marino VEC_replace (basic_block, cfun->cfg->x_basic_block_info, bb->index, NULL);
6111e4b17023SJohn Marino cfun->cfg->x_n_basic_blocks--;
6112e4b17023SJohn Marino
6113e4b17023SJohn Marino /* Grow DEST_CFUN's basic block array if needed. */
6114e4b17023SJohn Marino cfg = dest_cfun->cfg;
6115e4b17023SJohn Marino cfg->x_n_basic_blocks++;
6116e4b17023SJohn Marino if (bb->index >= cfg->x_last_basic_block)
6117e4b17023SJohn Marino cfg->x_last_basic_block = bb->index + 1;
6118e4b17023SJohn Marino
6119e4b17023SJohn Marino old_len = VEC_length (basic_block, cfg->x_basic_block_info);
6120e4b17023SJohn Marino if ((unsigned) cfg->x_last_basic_block >= old_len)
6121e4b17023SJohn Marino {
6122e4b17023SJohn Marino new_len = cfg->x_last_basic_block + (cfg->x_last_basic_block + 3) / 4;
6123e4b17023SJohn Marino VEC_safe_grow_cleared (basic_block, gc, cfg->x_basic_block_info,
6124e4b17023SJohn Marino new_len);
6125e4b17023SJohn Marino }
6126e4b17023SJohn Marino
6127e4b17023SJohn Marino VEC_replace (basic_block, cfg->x_basic_block_info,
6128e4b17023SJohn Marino bb->index, bb);
6129e4b17023SJohn Marino
6130e4b17023SJohn Marino /* Remap the variables in phi nodes. */
6131e4b17023SJohn Marino for (si = gsi_start_phis (bb); !gsi_end_p (si); )
6132e4b17023SJohn Marino {
6133e4b17023SJohn Marino gimple phi = gsi_stmt (si);
6134e4b17023SJohn Marino use_operand_p use;
6135e4b17023SJohn Marino tree op = PHI_RESULT (phi);
6136e4b17023SJohn Marino ssa_op_iter oi;
6137e4b17023SJohn Marino
6138e4b17023SJohn Marino if (!is_gimple_reg (op))
6139e4b17023SJohn Marino {
6140e4b17023SJohn Marino /* Remove the phi nodes for virtual operands (alias analysis will be
6141e4b17023SJohn Marino run for the new function, anyway). */
6142e4b17023SJohn Marino remove_phi_node (&si, true);
6143e4b17023SJohn Marino continue;
6144e4b17023SJohn Marino }
6145e4b17023SJohn Marino
6146e4b17023SJohn Marino SET_PHI_RESULT (phi,
6147e4b17023SJohn Marino replace_ssa_name (op, d->vars_map, dest_cfun->decl));
6148e4b17023SJohn Marino FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE)
6149e4b17023SJohn Marino {
6150e4b17023SJohn Marino op = USE_FROM_PTR (use);
6151e4b17023SJohn Marino if (TREE_CODE (op) == SSA_NAME)
6152e4b17023SJohn Marino SET_USE (use, replace_ssa_name (op, d->vars_map, dest_cfun->decl));
6153e4b17023SJohn Marino }
6154e4b17023SJohn Marino
6155e4b17023SJohn Marino gsi_next (&si);
6156e4b17023SJohn Marino }
6157e4b17023SJohn Marino
6158e4b17023SJohn Marino for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
6159e4b17023SJohn Marino {
6160e4b17023SJohn Marino gimple stmt = gsi_stmt (si);
6161e4b17023SJohn Marino struct walk_stmt_info wi;
6162e4b17023SJohn Marino
6163e4b17023SJohn Marino memset (&wi, 0, sizeof (wi));
6164e4b17023SJohn Marino wi.info = d;
6165e4b17023SJohn Marino walk_gimple_stmt (&si, move_stmt_r, move_stmt_op, &wi);
6166e4b17023SJohn Marino
6167e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_LABEL)
6168e4b17023SJohn Marino {
6169e4b17023SJohn Marino tree label = gimple_label_label (stmt);
6170e4b17023SJohn Marino int uid = LABEL_DECL_UID (label);
6171e4b17023SJohn Marino
6172e4b17023SJohn Marino gcc_assert (uid > -1);
6173e4b17023SJohn Marino
6174e4b17023SJohn Marino old_len = VEC_length (basic_block, cfg->x_label_to_block_map);
6175e4b17023SJohn Marino if (old_len <= (unsigned) uid)
6176e4b17023SJohn Marino {
6177e4b17023SJohn Marino new_len = 3 * uid / 2 + 1;
6178e4b17023SJohn Marino VEC_safe_grow_cleared (basic_block, gc,
6179e4b17023SJohn Marino cfg->x_label_to_block_map, new_len);
6180e4b17023SJohn Marino }
6181e4b17023SJohn Marino
6182e4b17023SJohn Marino VEC_replace (basic_block, cfg->x_label_to_block_map, uid, bb);
6183e4b17023SJohn Marino VEC_replace (basic_block, cfun->cfg->x_label_to_block_map, uid, NULL);
6184e4b17023SJohn Marino
6185e4b17023SJohn Marino gcc_assert (DECL_CONTEXT (label) == dest_cfun->decl);
6186e4b17023SJohn Marino
6187e4b17023SJohn Marino if (uid >= dest_cfun->cfg->last_label_uid)
6188e4b17023SJohn Marino dest_cfun->cfg->last_label_uid = uid + 1;
6189e4b17023SJohn Marino }
6190e4b17023SJohn Marino
6191e4b17023SJohn Marino maybe_duplicate_eh_stmt_fn (dest_cfun, stmt, cfun, stmt, d->eh_map, 0);
6192e4b17023SJohn Marino remove_stmt_from_eh_lp_fn (cfun, stmt);
6193e4b17023SJohn Marino
6194e4b17023SJohn Marino gimple_duplicate_stmt_histograms (dest_cfun, stmt, cfun, stmt);
6195e4b17023SJohn Marino gimple_remove_stmt_histograms (cfun, stmt);
6196e4b17023SJohn Marino
6197e4b17023SJohn Marino /* We cannot leave any operands allocated from the operand caches of
6198e4b17023SJohn Marino the current function. */
6199e4b17023SJohn Marino free_stmt_operands (stmt);
6200e4b17023SJohn Marino push_cfun (dest_cfun);
6201e4b17023SJohn Marino update_stmt (stmt);
6202e4b17023SJohn Marino pop_cfun ();
6203e4b17023SJohn Marino }
6204e4b17023SJohn Marino
6205e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
6206e4b17023SJohn Marino if (e->goto_locus)
6207e4b17023SJohn Marino {
6208e4b17023SJohn Marino tree block = e->goto_block;
6209e4b17023SJohn Marino if (d->orig_block == NULL_TREE
6210e4b17023SJohn Marino || block == d->orig_block)
6211e4b17023SJohn Marino e->goto_block = d->new_block;
6212e4b17023SJohn Marino #ifdef ENABLE_CHECKING
6213e4b17023SJohn Marino else if (block != d->new_block)
6214e4b17023SJohn Marino {
6215e4b17023SJohn Marino while (block && block != d->orig_block)
6216e4b17023SJohn Marino block = BLOCK_SUPERCONTEXT (block);
6217e4b17023SJohn Marino gcc_assert (block);
6218e4b17023SJohn Marino }
6219e4b17023SJohn Marino #endif
6220e4b17023SJohn Marino }
6221e4b17023SJohn Marino }
6222e4b17023SJohn Marino
6223e4b17023SJohn Marino /* Examine the statements in BB (which is in SRC_CFUN); find and return
6224e4b17023SJohn Marino the outermost EH region. Use REGION as the incoming base EH region. */
6225e4b17023SJohn Marino
6226e4b17023SJohn Marino static eh_region
find_outermost_region_in_block(struct function * src_cfun,basic_block bb,eh_region region)6227e4b17023SJohn Marino find_outermost_region_in_block (struct function *src_cfun,
6228e4b17023SJohn Marino basic_block bb, eh_region region)
6229e4b17023SJohn Marino {
6230e4b17023SJohn Marino gimple_stmt_iterator si;
6231e4b17023SJohn Marino
6232e4b17023SJohn Marino for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
6233e4b17023SJohn Marino {
6234e4b17023SJohn Marino gimple stmt = gsi_stmt (si);
6235e4b17023SJohn Marino eh_region stmt_region;
6236e4b17023SJohn Marino int lp_nr;
6237e4b17023SJohn Marino
6238e4b17023SJohn Marino lp_nr = lookup_stmt_eh_lp_fn (src_cfun, stmt);
6239e4b17023SJohn Marino stmt_region = get_eh_region_from_lp_number_fn (src_cfun, lp_nr);
6240e4b17023SJohn Marino if (stmt_region)
6241e4b17023SJohn Marino {
6242e4b17023SJohn Marino if (region == NULL)
6243e4b17023SJohn Marino region = stmt_region;
6244e4b17023SJohn Marino else if (stmt_region != region)
6245e4b17023SJohn Marino {
6246e4b17023SJohn Marino region = eh_region_outermost (src_cfun, stmt_region, region);
6247e4b17023SJohn Marino gcc_assert (region != NULL);
6248e4b17023SJohn Marino }
6249e4b17023SJohn Marino }
6250e4b17023SJohn Marino }
6251e4b17023SJohn Marino
6252e4b17023SJohn Marino return region;
6253e4b17023SJohn Marino }
6254e4b17023SJohn Marino
6255e4b17023SJohn Marino static tree
new_label_mapper(tree decl,void * data)6256e4b17023SJohn Marino new_label_mapper (tree decl, void *data)
6257e4b17023SJohn Marino {
6258e4b17023SJohn Marino htab_t hash = (htab_t) data;
6259e4b17023SJohn Marino struct tree_map *m;
6260e4b17023SJohn Marino void **slot;
6261e4b17023SJohn Marino
6262e4b17023SJohn Marino gcc_assert (TREE_CODE (decl) == LABEL_DECL);
6263e4b17023SJohn Marino
6264e4b17023SJohn Marino m = XNEW (struct tree_map);
6265e4b17023SJohn Marino m->hash = DECL_UID (decl);
6266e4b17023SJohn Marino m->base.from = decl;
6267e4b17023SJohn Marino m->to = create_artificial_label (UNKNOWN_LOCATION);
6268e4b17023SJohn Marino LABEL_DECL_UID (m->to) = LABEL_DECL_UID (decl);
6269e4b17023SJohn Marino if (LABEL_DECL_UID (m->to) >= cfun->cfg->last_label_uid)
6270e4b17023SJohn Marino cfun->cfg->last_label_uid = LABEL_DECL_UID (m->to) + 1;
6271e4b17023SJohn Marino
6272e4b17023SJohn Marino slot = htab_find_slot_with_hash (hash, m, m->hash, INSERT);
6273e4b17023SJohn Marino gcc_assert (*slot == NULL);
6274e4b17023SJohn Marino
6275e4b17023SJohn Marino *slot = m;
6276e4b17023SJohn Marino
6277e4b17023SJohn Marino return m->to;
6278e4b17023SJohn Marino }
6279e4b17023SJohn Marino
6280e4b17023SJohn Marino /* Change DECL_CONTEXT of all BLOCK_VARS in block, including
6281e4b17023SJohn Marino subblocks. */
6282e4b17023SJohn Marino
6283e4b17023SJohn Marino static void
replace_block_vars_by_duplicates(tree block,struct pointer_map_t * vars_map,tree to_context)6284e4b17023SJohn Marino replace_block_vars_by_duplicates (tree block, struct pointer_map_t *vars_map,
6285e4b17023SJohn Marino tree to_context)
6286e4b17023SJohn Marino {
6287e4b17023SJohn Marino tree *tp, t;
6288e4b17023SJohn Marino
6289e4b17023SJohn Marino for (tp = &BLOCK_VARS (block); *tp; tp = &DECL_CHAIN (*tp))
6290e4b17023SJohn Marino {
6291e4b17023SJohn Marino t = *tp;
6292e4b17023SJohn Marino if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != CONST_DECL)
6293e4b17023SJohn Marino continue;
6294e4b17023SJohn Marino replace_by_duplicate_decl (&t, vars_map, to_context);
6295e4b17023SJohn Marino if (t != *tp)
6296e4b17023SJohn Marino {
6297e4b17023SJohn Marino if (TREE_CODE (*tp) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*tp))
6298e4b17023SJohn Marino {
6299e4b17023SJohn Marino SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (*tp));
6300e4b17023SJohn Marino DECL_HAS_VALUE_EXPR_P (t) = 1;
6301e4b17023SJohn Marino }
6302e4b17023SJohn Marino DECL_CHAIN (t) = DECL_CHAIN (*tp);
6303e4b17023SJohn Marino *tp = t;
6304e4b17023SJohn Marino }
6305e4b17023SJohn Marino }
6306e4b17023SJohn Marino
6307e4b17023SJohn Marino for (block = BLOCK_SUBBLOCKS (block); block; block = BLOCK_CHAIN (block))
6308e4b17023SJohn Marino replace_block_vars_by_duplicates (block, vars_map, to_context);
6309e4b17023SJohn Marino }
6310e4b17023SJohn Marino
6311e4b17023SJohn Marino /* Move a single-entry, single-exit region delimited by ENTRY_BB and
6312e4b17023SJohn Marino EXIT_BB to function DEST_CFUN. The whole region is replaced by a
6313e4b17023SJohn Marino single basic block in the original CFG and the new basic block is
6314e4b17023SJohn Marino returned. DEST_CFUN must not have a CFG yet.
6315e4b17023SJohn Marino
6316e4b17023SJohn Marino Note that the region need not be a pure SESE region. Blocks inside
6317e4b17023SJohn Marino the region may contain calls to abort/exit. The only restriction
6318e4b17023SJohn Marino is that ENTRY_BB should be the only entry point and it must
6319e4b17023SJohn Marino dominate EXIT_BB.
6320e4b17023SJohn Marino
6321e4b17023SJohn Marino Change TREE_BLOCK of all statements in ORIG_BLOCK to the new
6322e4b17023SJohn Marino functions outermost BLOCK, move all subblocks of ORIG_BLOCK
6323e4b17023SJohn Marino to the new function.
6324e4b17023SJohn Marino
6325e4b17023SJohn Marino All local variables referenced in the region are assumed to be in
6326e4b17023SJohn Marino the corresponding BLOCK_VARS and unexpanded variable lists
6327e4b17023SJohn Marino associated with DEST_CFUN. */
6328e4b17023SJohn Marino
6329e4b17023SJohn Marino basic_block
move_sese_region_to_fn(struct function * dest_cfun,basic_block entry_bb,basic_block exit_bb,tree orig_block)6330e4b17023SJohn Marino move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
6331e4b17023SJohn Marino basic_block exit_bb, tree orig_block)
6332e4b17023SJohn Marino {
6333e4b17023SJohn Marino VEC(basic_block,heap) *bbs, *dom_bbs;
6334e4b17023SJohn Marino basic_block dom_entry = get_immediate_dominator (CDI_DOMINATORS, entry_bb);
6335e4b17023SJohn Marino basic_block after, bb, *entry_pred, *exit_succ, abb;
6336e4b17023SJohn Marino struct function *saved_cfun = cfun;
6337e4b17023SJohn Marino int *entry_flag, *exit_flag;
6338e4b17023SJohn Marino unsigned *entry_prob, *exit_prob;
6339e4b17023SJohn Marino unsigned i, num_entry_edges, num_exit_edges;
6340e4b17023SJohn Marino edge e;
6341e4b17023SJohn Marino edge_iterator ei;
6342e4b17023SJohn Marino htab_t new_label_map;
6343e4b17023SJohn Marino struct pointer_map_t *vars_map, *eh_map;
6344e4b17023SJohn Marino struct loop *loop = entry_bb->loop_father;
6345e4b17023SJohn Marino struct move_stmt_d d;
6346e4b17023SJohn Marino
6347e4b17023SJohn Marino /* If ENTRY does not strictly dominate EXIT, this cannot be an SESE
6348e4b17023SJohn Marino region. */
6349e4b17023SJohn Marino gcc_assert (entry_bb != exit_bb
6350e4b17023SJohn Marino && (!exit_bb
6351e4b17023SJohn Marino || dominated_by_p (CDI_DOMINATORS, exit_bb, entry_bb)));
6352e4b17023SJohn Marino
6353e4b17023SJohn Marino /* Collect all the blocks in the region. Manually add ENTRY_BB
6354e4b17023SJohn Marino because it won't be added by dfs_enumerate_from. */
6355e4b17023SJohn Marino bbs = NULL;
6356e4b17023SJohn Marino VEC_safe_push (basic_block, heap, bbs, entry_bb);
6357e4b17023SJohn Marino gather_blocks_in_sese_region (entry_bb, exit_bb, &bbs);
6358e4b17023SJohn Marino
6359e4b17023SJohn Marino /* The blocks that used to be dominated by something in BBS will now be
6360e4b17023SJohn Marino dominated by the new block. */
6361e4b17023SJohn Marino dom_bbs = get_dominated_by_region (CDI_DOMINATORS,
6362e4b17023SJohn Marino VEC_address (basic_block, bbs),
6363e4b17023SJohn Marino VEC_length (basic_block, bbs));
6364e4b17023SJohn Marino
6365e4b17023SJohn Marino /* Detach ENTRY_BB and EXIT_BB from CFUN->CFG. We need to remember
6366e4b17023SJohn Marino the predecessor edges to ENTRY_BB and the successor edges to
6367e4b17023SJohn Marino EXIT_BB so that we can re-attach them to the new basic block that
6368e4b17023SJohn Marino will replace the region. */
6369e4b17023SJohn Marino num_entry_edges = EDGE_COUNT (entry_bb->preds);
6370e4b17023SJohn Marino entry_pred = (basic_block *) xcalloc (num_entry_edges, sizeof (basic_block));
6371e4b17023SJohn Marino entry_flag = (int *) xcalloc (num_entry_edges, sizeof (int));
6372e4b17023SJohn Marino entry_prob = XNEWVEC (unsigned, num_entry_edges);
6373e4b17023SJohn Marino i = 0;
6374e4b17023SJohn Marino for (ei = ei_start (entry_bb->preds); (e = ei_safe_edge (ei)) != NULL;)
6375e4b17023SJohn Marino {
6376e4b17023SJohn Marino entry_prob[i] = e->probability;
6377e4b17023SJohn Marino entry_flag[i] = e->flags;
6378e4b17023SJohn Marino entry_pred[i++] = e->src;
6379e4b17023SJohn Marino remove_edge (e);
6380e4b17023SJohn Marino }
6381e4b17023SJohn Marino
6382e4b17023SJohn Marino if (exit_bb)
6383e4b17023SJohn Marino {
6384e4b17023SJohn Marino num_exit_edges = EDGE_COUNT (exit_bb->succs);
6385e4b17023SJohn Marino exit_succ = (basic_block *) xcalloc (num_exit_edges,
6386e4b17023SJohn Marino sizeof (basic_block));
6387e4b17023SJohn Marino exit_flag = (int *) xcalloc (num_exit_edges, sizeof (int));
6388e4b17023SJohn Marino exit_prob = XNEWVEC (unsigned, num_exit_edges);
6389e4b17023SJohn Marino i = 0;
6390e4b17023SJohn Marino for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;)
6391e4b17023SJohn Marino {
6392e4b17023SJohn Marino exit_prob[i] = e->probability;
6393e4b17023SJohn Marino exit_flag[i] = e->flags;
6394e4b17023SJohn Marino exit_succ[i++] = e->dest;
6395e4b17023SJohn Marino remove_edge (e);
6396e4b17023SJohn Marino }
6397e4b17023SJohn Marino }
6398e4b17023SJohn Marino else
6399e4b17023SJohn Marino {
6400e4b17023SJohn Marino num_exit_edges = 0;
6401e4b17023SJohn Marino exit_succ = NULL;
6402e4b17023SJohn Marino exit_flag = NULL;
6403e4b17023SJohn Marino exit_prob = NULL;
6404e4b17023SJohn Marino }
6405e4b17023SJohn Marino
6406e4b17023SJohn Marino /* Switch context to the child function to initialize DEST_FN's CFG. */
6407e4b17023SJohn Marino gcc_assert (dest_cfun->cfg == NULL);
6408e4b17023SJohn Marino push_cfun (dest_cfun);
6409e4b17023SJohn Marino
6410e4b17023SJohn Marino init_empty_tree_cfg ();
6411e4b17023SJohn Marino
6412e4b17023SJohn Marino /* Initialize EH information for the new function. */
6413e4b17023SJohn Marino eh_map = NULL;
6414e4b17023SJohn Marino new_label_map = NULL;
6415e4b17023SJohn Marino if (saved_cfun->eh)
6416e4b17023SJohn Marino {
6417e4b17023SJohn Marino eh_region region = NULL;
6418e4b17023SJohn Marino
6419e4b17023SJohn Marino FOR_EACH_VEC_ELT (basic_block, bbs, i, bb)
6420e4b17023SJohn Marino region = find_outermost_region_in_block (saved_cfun, bb, region);
6421e4b17023SJohn Marino
6422e4b17023SJohn Marino init_eh_for_function ();
6423e4b17023SJohn Marino if (region != NULL)
6424e4b17023SJohn Marino {
6425e4b17023SJohn Marino new_label_map = htab_create (17, tree_map_hash, tree_map_eq, free);
6426e4b17023SJohn Marino eh_map = duplicate_eh_regions (saved_cfun, region, 0,
6427e4b17023SJohn Marino new_label_mapper, new_label_map);
6428e4b17023SJohn Marino }
6429e4b17023SJohn Marino }
6430e4b17023SJohn Marino
6431e4b17023SJohn Marino pop_cfun ();
6432e4b17023SJohn Marino
6433e4b17023SJohn Marino /* Move blocks from BBS into DEST_CFUN. */
6434e4b17023SJohn Marino gcc_assert (VEC_length (basic_block, bbs) >= 2);
6435e4b17023SJohn Marino after = dest_cfun->cfg->x_entry_block_ptr;
6436e4b17023SJohn Marino vars_map = pointer_map_create ();
6437e4b17023SJohn Marino
6438e4b17023SJohn Marino memset (&d, 0, sizeof (d));
6439e4b17023SJohn Marino d.orig_block = orig_block;
6440e4b17023SJohn Marino d.new_block = DECL_INITIAL (dest_cfun->decl);
6441e4b17023SJohn Marino d.from_context = cfun->decl;
6442e4b17023SJohn Marino d.to_context = dest_cfun->decl;
6443e4b17023SJohn Marino d.vars_map = vars_map;
6444e4b17023SJohn Marino d.new_label_map = new_label_map;
6445e4b17023SJohn Marino d.eh_map = eh_map;
6446e4b17023SJohn Marino d.remap_decls_p = true;
6447e4b17023SJohn Marino
6448e4b17023SJohn Marino FOR_EACH_VEC_ELT (basic_block, bbs, i, bb)
6449e4b17023SJohn Marino {
6450e4b17023SJohn Marino /* No need to update edge counts on the last block. It has
6451e4b17023SJohn Marino already been updated earlier when we detached the region from
6452e4b17023SJohn Marino the original CFG. */
6453e4b17023SJohn Marino move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, &d);
6454e4b17023SJohn Marino after = bb;
6455e4b17023SJohn Marino }
6456e4b17023SJohn Marino
6457e4b17023SJohn Marino /* Rewire BLOCK_SUBBLOCKS of orig_block. */
6458e4b17023SJohn Marino if (orig_block)
6459e4b17023SJohn Marino {
6460e4b17023SJohn Marino tree block;
6461e4b17023SJohn Marino gcc_assert (BLOCK_SUBBLOCKS (DECL_INITIAL (dest_cfun->decl))
6462e4b17023SJohn Marino == NULL_TREE);
6463e4b17023SJohn Marino BLOCK_SUBBLOCKS (DECL_INITIAL (dest_cfun->decl))
6464e4b17023SJohn Marino = BLOCK_SUBBLOCKS (orig_block);
6465e4b17023SJohn Marino for (block = BLOCK_SUBBLOCKS (orig_block);
6466e4b17023SJohn Marino block; block = BLOCK_CHAIN (block))
6467e4b17023SJohn Marino BLOCK_SUPERCONTEXT (block) = DECL_INITIAL (dest_cfun->decl);
6468e4b17023SJohn Marino BLOCK_SUBBLOCKS (orig_block) = NULL_TREE;
6469e4b17023SJohn Marino }
6470e4b17023SJohn Marino
6471e4b17023SJohn Marino replace_block_vars_by_duplicates (DECL_INITIAL (dest_cfun->decl),
6472e4b17023SJohn Marino vars_map, dest_cfun->decl);
6473e4b17023SJohn Marino
6474e4b17023SJohn Marino if (new_label_map)
6475e4b17023SJohn Marino htab_delete (new_label_map);
6476e4b17023SJohn Marino if (eh_map)
6477e4b17023SJohn Marino pointer_map_destroy (eh_map);
6478e4b17023SJohn Marino pointer_map_destroy (vars_map);
6479e4b17023SJohn Marino
6480e4b17023SJohn Marino /* Rewire the entry and exit blocks. The successor to the entry
6481e4b17023SJohn Marino block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in
6482e4b17023SJohn Marino the child function. Similarly, the predecessor of DEST_FN's
6483e4b17023SJohn Marino EXIT_BLOCK_PTR turns into the predecessor of EXIT_BLOCK_PTR. We
6484e4b17023SJohn Marino need to switch CFUN between DEST_CFUN and SAVED_CFUN so that the
6485e4b17023SJohn Marino various CFG manipulation function get to the right CFG.
6486e4b17023SJohn Marino
6487e4b17023SJohn Marino FIXME, this is silly. The CFG ought to become a parameter to
6488e4b17023SJohn Marino these helpers. */
6489e4b17023SJohn Marino push_cfun (dest_cfun);
6490e4b17023SJohn Marino make_edge (ENTRY_BLOCK_PTR, entry_bb, EDGE_FALLTHRU);
6491e4b17023SJohn Marino if (exit_bb)
6492e4b17023SJohn Marino make_edge (exit_bb, EXIT_BLOCK_PTR, 0);
6493e4b17023SJohn Marino pop_cfun ();
6494e4b17023SJohn Marino
6495e4b17023SJohn Marino /* Back in the original function, the SESE region has disappeared,
6496e4b17023SJohn Marino create a new basic block in its place. */
6497e4b17023SJohn Marino bb = create_empty_bb (entry_pred[0]);
6498e4b17023SJohn Marino if (current_loops)
6499e4b17023SJohn Marino add_bb_to_loop (bb, loop);
6500e4b17023SJohn Marino for (i = 0; i < num_entry_edges; i++)
6501e4b17023SJohn Marino {
6502e4b17023SJohn Marino e = make_edge (entry_pred[i], bb, entry_flag[i]);
6503e4b17023SJohn Marino e->probability = entry_prob[i];
6504e4b17023SJohn Marino }
6505e4b17023SJohn Marino
6506e4b17023SJohn Marino for (i = 0; i < num_exit_edges; i++)
6507e4b17023SJohn Marino {
6508e4b17023SJohn Marino e = make_edge (bb, exit_succ[i], exit_flag[i]);
6509e4b17023SJohn Marino e->probability = exit_prob[i];
6510e4b17023SJohn Marino }
6511e4b17023SJohn Marino
6512e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, bb, dom_entry);
6513e4b17023SJohn Marino FOR_EACH_VEC_ELT (basic_block, dom_bbs, i, abb)
6514e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, abb, bb);
6515e4b17023SJohn Marino VEC_free (basic_block, heap, dom_bbs);
6516e4b17023SJohn Marino
6517e4b17023SJohn Marino if (exit_bb)
6518e4b17023SJohn Marino {
6519e4b17023SJohn Marino free (exit_prob);
6520e4b17023SJohn Marino free (exit_flag);
6521e4b17023SJohn Marino free (exit_succ);
6522e4b17023SJohn Marino }
6523e4b17023SJohn Marino free (entry_prob);
6524e4b17023SJohn Marino free (entry_flag);
6525e4b17023SJohn Marino free (entry_pred);
6526e4b17023SJohn Marino VEC_free (basic_block, heap, bbs);
6527e4b17023SJohn Marino
6528e4b17023SJohn Marino return bb;
6529e4b17023SJohn Marino }
6530e4b17023SJohn Marino
6531e4b17023SJohn Marino
6532e4b17023SJohn Marino /* Dump FUNCTION_DECL FN to file FILE using FLAGS (see TDF_* in tree-pass.h)
6533e4b17023SJohn Marino */
6534e4b17023SJohn Marino
6535e4b17023SJohn Marino void
dump_function_to_file(tree fn,FILE * file,int flags)6536e4b17023SJohn Marino dump_function_to_file (tree fn, FILE *file, int flags)
6537e4b17023SJohn Marino {
6538e4b17023SJohn Marino tree arg, var;
6539e4b17023SJohn Marino struct function *dsf;
6540e4b17023SJohn Marino bool ignore_topmost_bind = false, any_var = false;
6541e4b17023SJohn Marino basic_block bb;
6542e4b17023SJohn Marino tree chain;
6543e4b17023SJohn Marino bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn);
6544e4b17023SJohn Marino
6545e4b17023SJohn Marino fprintf (file, "%s %s(", lang_hooks.decl_printable_name (fn, 2),
6546e4b17023SJohn Marino tmclone ? "[tm-clone] " : "");
6547e4b17023SJohn Marino
6548e4b17023SJohn Marino arg = DECL_ARGUMENTS (fn);
6549e4b17023SJohn Marino while (arg)
6550e4b17023SJohn Marino {
6551e4b17023SJohn Marino print_generic_expr (file, TREE_TYPE (arg), dump_flags);
6552e4b17023SJohn Marino fprintf (file, " ");
6553e4b17023SJohn Marino print_generic_expr (file, arg, dump_flags);
6554e4b17023SJohn Marino if (flags & TDF_VERBOSE)
6555e4b17023SJohn Marino print_node (file, "", arg, 4);
6556e4b17023SJohn Marino if (DECL_CHAIN (arg))
6557e4b17023SJohn Marino fprintf (file, ", ");
6558e4b17023SJohn Marino arg = DECL_CHAIN (arg);
6559e4b17023SJohn Marino }
6560e4b17023SJohn Marino fprintf (file, ")\n");
6561e4b17023SJohn Marino
6562e4b17023SJohn Marino if (flags & TDF_VERBOSE)
6563e4b17023SJohn Marino print_node (file, "", fn, 2);
6564e4b17023SJohn Marino
6565e4b17023SJohn Marino dsf = DECL_STRUCT_FUNCTION (fn);
6566e4b17023SJohn Marino if (dsf && (flags & TDF_EH))
6567e4b17023SJohn Marino dump_eh_tree (file, dsf);
6568e4b17023SJohn Marino
6569e4b17023SJohn Marino if (flags & TDF_RAW && !gimple_has_body_p (fn))
6570e4b17023SJohn Marino {
6571e4b17023SJohn Marino dump_node (fn, TDF_SLIM | flags, file);
6572e4b17023SJohn Marino return;
6573e4b17023SJohn Marino }
6574e4b17023SJohn Marino
6575e4b17023SJohn Marino /* Switch CFUN to point to FN. */
6576e4b17023SJohn Marino push_cfun (DECL_STRUCT_FUNCTION (fn));
6577e4b17023SJohn Marino
6578e4b17023SJohn Marino /* When GIMPLE is lowered, the variables are no longer available in
6579e4b17023SJohn Marino BIND_EXPRs, so display them separately. */
6580e4b17023SJohn Marino if (cfun && cfun->decl == fn && !VEC_empty (tree, cfun->local_decls))
6581e4b17023SJohn Marino {
6582e4b17023SJohn Marino unsigned ix;
6583e4b17023SJohn Marino ignore_topmost_bind = true;
6584e4b17023SJohn Marino
6585e4b17023SJohn Marino fprintf (file, "{\n");
6586e4b17023SJohn Marino FOR_EACH_LOCAL_DECL (cfun, ix, var)
6587e4b17023SJohn Marino {
6588e4b17023SJohn Marino print_generic_decl (file, var, flags);
6589e4b17023SJohn Marino if (flags & TDF_VERBOSE)
6590e4b17023SJohn Marino print_node (file, "", var, 4);
6591e4b17023SJohn Marino fprintf (file, "\n");
6592e4b17023SJohn Marino
6593e4b17023SJohn Marino any_var = true;
6594e4b17023SJohn Marino }
6595e4b17023SJohn Marino }
6596e4b17023SJohn Marino
6597e4b17023SJohn Marino if (cfun && cfun->decl == fn && cfun->cfg && basic_block_info)
6598e4b17023SJohn Marino {
6599e4b17023SJohn Marino /* If the CFG has been built, emit a CFG-based dump. */
6600e4b17023SJohn Marino check_bb_profile (ENTRY_BLOCK_PTR, file);
6601e4b17023SJohn Marino if (!ignore_topmost_bind)
6602e4b17023SJohn Marino fprintf (file, "{\n");
6603e4b17023SJohn Marino
6604e4b17023SJohn Marino if (any_var && n_basic_blocks)
6605e4b17023SJohn Marino fprintf (file, "\n");
6606e4b17023SJohn Marino
6607e4b17023SJohn Marino FOR_EACH_BB (bb)
6608e4b17023SJohn Marino gimple_dump_bb (bb, file, 2, flags);
6609e4b17023SJohn Marino
6610e4b17023SJohn Marino fprintf (file, "}\n");
6611e4b17023SJohn Marino check_bb_profile (EXIT_BLOCK_PTR, file);
6612e4b17023SJohn Marino }
6613e4b17023SJohn Marino else if (DECL_SAVED_TREE (fn) == NULL)
6614e4b17023SJohn Marino {
6615e4b17023SJohn Marino /* The function is now in GIMPLE form but the CFG has not been
6616e4b17023SJohn Marino built yet. Emit the single sequence of GIMPLE statements
6617e4b17023SJohn Marino that make up its body. */
6618e4b17023SJohn Marino gimple_seq body = gimple_body (fn);
6619e4b17023SJohn Marino
6620e4b17023SJohn Marino if (gimple_seq_first_stmt (body)
6621e4b17023SJohn Marino && gimple_seq_first_stmt (body) == gimple_seq_last_stmt (body)
6622e4b17023SJohn Marino && gimple_code (gimple_seq_first_stmt (body)) == GIMPLE_BIND)
6623e4b17023SJohn Marino print_gimple_seq (file, body, 0, flags);
6624e4b17023SJohn Marino else
6625e4b17023SJohn Marino {
6626e4b17023SJohn Marino if (!ignore_topmost_bind)
6627e4b17023SJohn Marino fprintf (file, "{\n");
6628e4b17023SJohn Marino
6629e4b17023SJohn Marino if (any_var)
6630e4b17023SJohn Marino fprintf (file, "\n");
6631e4b17023SJohn Marino
6632e4b17023SJohn Marino print_gimple_seq (file, body, 2, flags);
6633e4b17023SJohn Marino fprintf (file, "}\n");
6634e4b17023SJohn Marino }
6635e4b17023SJohn Marino }
6636e4b17023SJohn Marino else
6637e4b17023SJohn Marino {
6638e4b17023SJohn Marino int indent;
6639e4b17023SJohn Marino
6640e4b17023SJohn Marino /* Make a tree based dump. */
6641e4b17023SJohn Marino chain = DECL_SAVED_TREE (fn);
6642e4b17023SJohn Marino
6643e4b17023SJohn Marino if (chain && TREE_CODE (chain) == BIND_EXPR)
6644e4b17023SJohn Marino {
6645e4b17023SJohn Marino if (ignore_topmost_bind)
6646e4b17023SJohn Marino {
6647e4b17023SJohn Marino chain = BIND_EXPR_BODY (chain);
6648e4b17023SJohn Marino indent = 2;
6649e4b17023SJohn Marino }
6650e4b17023SJohn Marino else
6651e4b17023SJohn Marino indent = 0;
6652e4b17023SJohn Marino }
6653e4b17023SJohn Marino else
6654e4b17023SJohn Marino {
6655e4b17023SJohn Marino if (!ignore_topmost_bind)
6656e4b17023SJohn Marino fprintf (file, "{\n");
6657e4b17023SJohn Marino indent = 2;
6658e4b17023SJohn Marino }
6659e4b17023SJohn Marino
6660e4b17023SJohn Marino if (any_var)
6661e4b17023SJohn Marino fprintf (file, "\n");
6662e4b17023SJohn Marino
6663e4b17023SJohn Marino print_generic_stmt_indented (file, chain, flags, indent);
6664e4b17023SJohn Marino if (ignore_topmost_bind)
6665e4b17023SJohn Marino fprintf (file, "}\n");
6666e4b17023SJohn Marino }
6667e4b17023SJohn Marino
6668e4b17023SJohn Marino if (flags & TDF_ENUMERATE_LOCALS)
6669e4b17023SJohn Marino dump_enumerated_decls (file, flags);
6670e4b17023SJohn Marino fprintf (file, "\n\n");
6671e4b17023SJohn Marino
6672e4b17023SJohn Marino /* Restore CFUN. */
6673e4b17023SJohn Marino pop_cfun ();
6674e4b17023SJohn Marino }
6675e4b17023SJohn Marino
6676e4b17023SJohn Marino
6677e4b17023SJohn Marino /* Dump FUNCTION_DECL FN to stderr using FLAGS (see TDF_* in tree.h) */
6678e4b17023SJohn Marino
6679e4b17023SJohn Marino DEBUG_FUNCTION void
debug_function(tree fn,int flags)6680e4b17023SJohn Marino debug_function (tree fn, int flags)
6681e4b17023SJohn Marino {
6682e4b17023SJohn Marino dump_function_to_file (fn, stderr, flags);
6683e4b17023SJohn Marino }
6684e4b17023SJohn Marino
6685e4b17023SJohn Marino
6686e4b17023SJohn Marino /* Print on FILE the indexes for the predecessors of basic_block BB. */
6687e4b17023SJohn Marino
6688e4b17023SJohn Marino static void
print_pred_bbs(FILE * file,basic_block bb)6689e4b17023SJohn Marino print_pred_bbs (FILE *file, basic_block bb)
6690e4b17023SJohn Marino {
6691e4b17023SJohn Marino edge e;
6692e4b17023SJohn Marino edge_iterator ei;
6693e4b17023SJohn Marino
6694e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds)
6695e4b17023SJohn Marino fprintf (file, "bb_%d ", e->src->index);
6696e4b17023SJohn Marino }
6697e4b17023SJohn Marino
6698e4b17023SJohn Marino
6699e4b17023SJohn Marino /* Print on FILE the indexes for the successors of basic_block BB. */
6700e4b17023SJohn Marino
6701e4b17023SJohn Marino static void
print_succ_bbs(FILE * file,basic_block bb)6702e4b17023SJohn Marino print_succ_bbs (FILE *file, basic_block bb)
6703e4b17023SJohn Marino {
6704e4b17023SJohn Marino edge e;
6705e4b17023SJohn Marino edge_iterator ei;
6706e4b17023SJohn Marino
6707e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
6708e4b17023SJohn Marino fprintf (file, "bb_%d ", e->dest->index);
6709e4b17023SJohn Marino }
6710e4b17023SJohn Marino
6711e4b17023SJohn Marino /* Print to FILE the basic block BB following the VERBOSITY level. */
6712e4b17023SJohn Marino
6713e4b17023SJohn Marino void
print_loops_bb(FILE * file,basic_block bb,int indent,int verbosity)6714e4b17023SJohn Marino print_loops_bb (FILE *file, basic_block bb, int indent, int verbosity)
6715e4b17023SJohn Marino {
6716e4b17023SJohn Marino char *s_indent = (char *) alloca ((size_t) indent + 1);
6717e4b17023SJohn Marino memset ((void *) s_indent, ' ', (size_t) indent);
6718e4b17023SJohn Marino s_indent[indent] = '\0';
6719e4b17023SJohn Marino
6720e4b17023SJohn Marino /* Print basic_block's header. */
6721e4b17023SJohn Marino if (verbosity >= 2)
6722e4b17023SJohn Marino {
6723e4b17023SJohn Marino fprintf (file, "%s bb_%d (preds = {", s_indent, bb->index);
6724e4b17023SJohn Marino print_pred_bbs (file, bb);
6725e4b17023SJohn Marino fprintf (file, "}, succs = {");
6726e4b17023SJohn Marino print_succ_bbs (file, bb);
6727e4b17023SJohn Marino fprintf (file, "})\n");
6728e4b17023SJohn Marino }
6729e4b17023SJohn Marino
6730e4b17023SJohn Marino /* Print basic_block's body. */
6731e4b17023SJohn Marino if (verbosity >= 3)
6732e4b17023SJohn Marino {
6733e4b17023SJohn Marino fprintf (file, "%s {\n", s_indent);
6734e4b17023SJohn Marino gimple_dump_bb (bb, file, indent + 4, TDF_VOPS|TDF_MEMSYMS);
6735e4b17023SJohn Marino fprintf (file, "%s }\n", s_indent);
6736e4b17023SJohn Marino }
6737e4b17023SJohn Marino }
6738e4b17023SJohn Marino
6739e4b17023SJohn Marino static void print_loop_and_siblings (FILE *, struct loop *, int, int);
6740e4b17023SJohn Marino
6741e4b17023SJohn Marino /* Pretty print LOOP on FILE, indented INDENT spaces. Following
6742e4b17023SJohn Marino VERBOSITY level this outputs the contents of the loop, or just its
6743e4b17023SJohn Marino structure. */
6744e4b17023SJohn Marino
6745e4b17023SJohn Marino static void
print_loop(FILE * file,struct loop * loop,int indent,int verbosity)6746e4b17023SJohn Marino print_loop (FILE *file, struct loop *loop, int indent, int verbosity)
6747e4b17023SJohn Marino {
6748e4b17023SJohn Marino char *s_indent;
6749e4b17023SJohn Marino basic_block bb;
6750e4b17023SJohn Marino
6751e4b17023SJohn Marino if (loop == NULL)
6752e4b17023SJohn Marino return;
6753e4b17023SJohn Marino
6754e4b17023SJohn Marino s_indent = (char *) alloca ((size_t) indent + 1);
6755e4b17023SJohn Marino memset ((void *) s_indent, ' ', (size_t) indent);
6756e4b17023SJohn Marino s_indent[indent] = '\0';
6757e4b17023SJohn Marino
6758e4b17023SJohn Marino /* Print loop's header. */
6759e4b17023SJohn Marino fprintf (file, "%sloop_%d (header = %d, latch = %d", s_indent,
6760e4b17023SJohn Marino loop->num, loop->header->index, loop->latch->index);
6761e4b17023SJohn Marino fprintf (file, ", niter = ");
6762e4b17023SJohn Marino print_generic_expr (file, loop->nb_iterations, 0);
6763e4b17023SJohn Marino
6764e4b17023SJohn Marino if (loop->any_upper_bound)
6765e4b17023SJohn Marino {
6766e4b17023SJohn Marino fprintf (file, ", upper_bound = ");
6767e4b17023SJohn Marino dump_double_int (file, loop->nb_iterations_upper_bound, true);
6768e4b17023SJohn Marino }
6769e4b17023SJohn Marino
6770e4b17023SJohn Marino if (loop->any_estimate)
6771e4b17023SJohn Marino {
6772e4b17023SJohn Marino fprintf (file, ", estimate = ");
6773e4b17023SJohn Marino dump_double_int (file, loop->nb_iterations_estimate, true);
6774e4b17023SJohn Marino }
6775e4b17023SJohn Marino fprintf (file, ")\n");
6776e4b17023SJohn Marino
6777e4b17023SJohn Marino /* Print loop's body. */
6778e4b17023SJohn Marino if (verbosity >= 1)
6779e4b17023SJohn Marino {
6780e4b17023SJohn Marino fprintf (file, "%s{\n", s_indent);
6781e4b17023SJohn Marino FOR_EACH_BB (bb)
6782e4b17023SJohn Marino if (bb->loop_father == loop)
6783e4b17023SJohn Marino print_loops_bb (file, bb, indent, verbosity);
6784e4b17023SJohn Marino
6785e4b17023SJohn Marino print_loop_and_siblings (file, loop->inner, indent + 2, verbosity);
6786e4b17023SJohn Marino fprintf (file, "%s}\n", s_indent);
6787e4b17023SJohn Marino }
6788e4b17023SJohn Marino }
6789e4b17023SJohn Marino
6790e4b17023SJohn Marino /* Print the LOOP and its sibling loops on FILE, indented INDENT
6791e4b17023SJohn Marino spaces. Following VERBOSITY level this outputs the contents of the
6792e4b17023SJohn Marino loop, or just its structure. */
6793e4b17023SJohn Marino
6794e4b17023SJohn Marino static void
print_loop_and_siblings(FILE * file,struct loop * loop,int indent,int verbosity)6795e4b17023SJohn Marino print_loop_and_siblings (FILE *file, struct loop *loop, int indent, int verbosity)
6796e4b17023SJohn Marino {
6797e4b17023SJohn Marino if (loop == NULL)
6798e4b17023SJohn Marino return;
6799e4b17023SJohn Marino
6800e4b17023SJohn Marino print_loop (file, loop, indent, verbosity);
6801e4b17023SJohn Marino print_loop_and_siblings (file, loop->next, indent, verbosity);
6802e4b17023SJohn Marino }
6803e4b17023SJohn Marino
6804e4b17023SJohn Marino /* Follow a CFG edge from the entry point of the program, and on entry
6805e4b17023SJohn Marino of a loop, pretty print the loop structure on FILE. */
6806e4b17023SJohn Marino
6807e4b17023SJohn Marino void
print_loops(FILE * file,int verbosity)6808e4b17023SJohn Marino print_loops (FILE *file, int verbosity)
6809e4b17023SJohn Marino {
6810e4b17023SJohn Marino basic_block bb;
6811e4b17023SJohn Marino
6812e4b17023SJohn Marino bb = ENTRY_BLOCK_PTR;
6813e4b17023SJohn Marino if (bb && bb->loop_father)
6814e4b17023SJohn Marino print_loop_and_siblings (file, bb->loop_father, 0, verbosity);
6815e4b17023SJohn Marino }
6816e4b17023SJohn Marino
6817e4b17023SJohn Marino
6818e4b17023SJohn Marino /* Debugging loops structure at tree level, at some VERBOSITY level. */
6819e4b17023SJohn Marino
6820e4b17023SJohn Marino DEBUG_FUNCTION void
debug_loops(int verbosity)6821e4b17023SJohn Marino debug_loops (int verbosity)
6822e4b17023SJohn Marino {
6823e4b17023SJohn Marino print_loops (stderr, verbosity);
6824e4b17023SJohn Marino }
6825e4b17023SJohn Marino
6826e4b17023SJohn Marino /* Print on stderr the code of LOOP, at some VERBOSITY level. */
6827e4b17023SJohn Marino
6828e4b17023SJohn Marino DEBUG_FUNCTION void
debug_loop(struct loop * loop,int verbosity)6829e4b17023SJohn Marino debug_loop (struct loop *loop, int verbosity)
6830e4b17023SJohn Marino {
6831e4b17023SJohn Marino print_loop (stderr, loop, 0, verbosity);
6832e4b17023SJohn Marino }
6833e4b17023SJohn Marino
6834e4b17023SJohn Marino /* Print on stderr the code of loop number NUM, at some VERBOSITY
6835e4b17023SJohn Marino level. */
6836e4b17023SJohn Marino
6837e4b17023SJohn Marino DEBUG_FUNCTION void
debug_loop_num(unsigned num,int verbosity)6838e4b17023SJohn Marino debug_loop_num (unsigned num, int verbosity)
6839e4b17023SJohn Marino {
6840e4b17023SJohn Marino debug_loop (get_loop (num), verbosity);
6841e4b17023SJohn Marino }
6842e4b17023SJohn Marino
6843e4b17023SJohn Marino /* Return true if BB ends with a call, possibly followed by some
6844e4b17023SJohn Marino instructions that must stay with the call. Return false,
6845e4b17023SJohn Marino otherwise. */
6846e4b17023SJohn Marino
6847e4b17023SJohn Marino static bool
gimple_block_ends_with_call_p(basic_block bb)6848e4b17023SJohn Marino gimple_block_ends_with_call_p (basic_block bb)
6849e4b17023SJohn Marino {
6850e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
6851e4b17023SJohn Marino return !gsi_end_p (gsi) && is_gimple_call (gsi_stmt (gsi));
6852e4b17023SJohn Marino }
6853e4b17023SJohn Marino
6854e4b17023SJohn Marino
6855e4b17023SJohn Marino /* Return true if BB ends with a conditional branch. Return false,
6856e4b17023SJohn Marino otherwise. */
6857e4b17023SJohn Marino
6858e4b17023SJohn Marino static bool
gimple_block_ends_with_condjump_p(const_basic_block bb)6859e4b17023SJohn Marino gimple_block_ends_with_condjump_p (const_basic_block bb)
6860e4b17023SJohn Marino {
6861e4b17023SJohn Marino gimple stmt = last_stmt (CONST_CAST_BB (bb));
6862e4b17023SJohn Marino return (stmt && gimple_code (stmt) == GIMPLE_COND);
6863e4b17023SJohn Marino }
6864e4b17023SJohn Marino
6865e4b17023SJohn Marino
6866e4b17023SJohn Marino /* Return true if we need to add fake edge to exit at statement T.
6867e4b17023SJohn Marino Helper function for gimple_flow_call_edges_add. */
6868e4b17023SJohn Marino
6869e4b17023SJohn Marino static bool
need_fake_edge_p(gimple t)6870e4b17023SJohn Marino need_fake_edge_p (gimple t)
6871e4b17023SJohn Marino {
6872e4b17023SJohn Marino tree fndecl = NULL_TREE;
6873e4b17023SJohn Marino int call_flags = 0;
6874e4b17023SJohn Marino
6875e4b17023SJohn Marino /* NORETURN and LONGJMP calls already have an edge to exit.
6876e4b17023SJohn Marino CONST and PURE calls do not need one.
6877e4b17023SJohn Marino We don't currently check for CONST and PURE here, although
6878e4b17023SJohn Marino it would be a good idea, because those attributes are
6879e4b17023SJohn Marino figured out from the RTL in mark_constant_function, and
6880e4b17023SJohn Marino the counter incrementation code from -fprofile-arcs
6881e4b17023SJohn Marino leads to different results from -fbranch-probabilities. */
6882e4b17023SJohn Marino if (is_gimple_call (t))
6883e4b17023SJohn Marino {
6884e4b17023SJohn Marino fndecl = gimple_call_fndecl (t);
6885e4b17023SJohn Marino call_flags = gimple_call_flags (t);
6886e4b17023SJohn Marino }
6887e4b17023SJohn Marino
6888e4b17023SJohn Marino if (is_gimple_call (t)
6889e4b17023SJohn Marino && fndecl
6890e4b17023SJohn Marino && DECL_BUILT_IN (fndecl)
6891e4b17023SJohn Marino && (call_flags & ECF_NOTHROW)
6892e4b17023SJohn Marino && !(call_flags & ECF_RETURNS_TWICE)
6893e4b17023SJohn Marino /* fork() doesn't really return twice, but the effect of
6894e4b17023SJohn Marino wrapping it in __gcov_fork() which calls __gcov_flush()
6895e4b17023SJohn Marino and clears the counters before forking has the same
6896e4b17023SJohn Marino effect as returning twice. Force a fake edge. */
6897e4b17023SJohn Marino && !(DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
6898e4b17023SJohn Marino && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FORK))
6899e4b17023SJohn Marino return false;
6900e4b17023SJohn Marino
6901e4b17023SJohn Marino if (is_gimple_call (t))
6902e4b17023SJohn Marino {
6903e4b17023SJohn Marino edge_iterator ei;
6904e4b17023SJohn Marino edge e;
6905e4b17023SJohn Marino basic_block bb;
6906e4b17023SJohn Marino
6907e4b17023SJohn Marino if (!(call_flags & ECF_NORETURN))
6908e4b17023SJohn Marino return true;
6909e4b17023SJohn Marino
6910e4b17023SJohn Marino bb = gimple_bb (t);
6911e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
6912e4b17023SJohn Marino if ((e->flags & EDGE_FAKE) == 0)
6913e4b17023SJohn Marino return true;
6914e4b17023SJohn Marino }
6915e4b17023SJohn Marino
6916e4b17023SJohn Marino if (gimple_code (t) == GIMPLE_ASM
6917e4b17023SJohn Marino && (gimple_asm_volatile_p (t) || gimple_asm_input_p (t)))
6918e4b17023SJohn Marino return true;
6919e4b17023SJohn Marino
6920e4b17023SJohn Marino return false;
6921e4b17023SJohn Marino }
6922e4b17023SJohn Marino
6923e4b17023SJohn Marino
6924e4b17023SJohn Marino /* Add fake edges to the function exit for any non constant and non
6925e4b17023SJohn Marino noreturn calls (or noreturn calls with EH/abnormal edges),
6926e4b17023SJohn Marino volatile inline assembly in the bitmap of blocks specified by BLOCKS
6927e4b17023SJohn Marino or to the whole CFG if BLOCKS is zero. Return the number of blocks
6928e4b17023SJohn Marino that were split.
6929e4b17023SJohn Marino
6930e4b17023SJohn Marino The goal is to expose cases in which entering a basic block does
6931e4b17023SJohn Marino not imply that all subsequent instructions must be executed. */
6932e4b17023SJohn Marino
6933e4b17023SJohn Marino static int
gimple_flow_call_edges_add(sbitmap blocks)6934e4b17023SJohn Marino gimple_flow_call_edges_add (sbitmap blocks)
6935e4b17023SJohn Marino {
6936e4b17023SJohn Marino int i;
6937e4b17023SJohn Marino int blocks_split = 0;
6938e4b17023SJohn Marino int last_bb = last_basic_block;
6939e4b17023SJohn Marino bool check_last_block = false;
6940e4b17023SJohn Marino
6941e4b17023SJohn Marino if (n_basic_blocks == NUM_FIXED_BLOCKS)
6942e4b17023SJohn Marino return 0;
6943e4b17023SJohn Marino
6944e4b17023SJohn Marino if (! blocks)
6945e4b17023SJohn Marino check_last_block = true;
6946e4b17023SJohn Marino else
6947e4b17023SJohn Marino check_last_block = TEST_BIT (blocks, EXIT_BLOCK_PTR->prev_bb->index);
6948e4b17023SJohn Marino
6949e4b17023SJohn Marino /* In the last basic block, before epilogue generation, there will be
6950e4b17023SJohn Marino a fallthru edge to EXIT. Special care is required if the last insn
6951e4b17023SJohn Marino of the last basic block is a call because make_edge folds duplicate
6952e4b17023SJohn Marino edges, which would result in the fallthru edge also being marked
6953e4b17023SJohn Marino fake, which would result in the fallthru edge being removed by
6954e4b17023SJohn Marino remove_fake_edges, which would result in an invalid CFG.
6955e4b17023SJohn Marino
6956e4b17023SJohn Marino Moreover, we can't elide the outgoing fake edge, since the block
6957e4b17023SJohn Marino profiler needs to take this into account in order to solve the minimal
6958e4b17023SJohn Marino spanning tree in the case that the call doesn't return.
6959e4b17023SJohn Marino
6960e4b17023SJohn Marino Handle this by adding a dummy instruction in a new last basic block. */
6961e4b17023SJohn Marino if (check_last_block)
6962e4b17023SJohn Marino {
6963e4b17023SJohn Marino basic_block bb = EXIT_BLOCK_PTR->prev_bb;
6964e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
6965e4b17023SJohn Marino gimple t = NULL;
6966e4b17023SJohn Marino
6967e4b17023SJohn Marino if (!gsi_end_p (gsi))
6968e4b17023SJohn Marino t = gsi_stmt (gsi);
6969e4b17023SJohn Marino
6970e4b17023SJohn Marino if (t && need_fake_edge_p (t))
6971e4b17023SJohn Marino {
6972e4b17023SJohn Marino edge e;
6973e4b17023SJohn Marino
6974e4b17023SJohn Marino e = find_edge (bb, EXIT_BLOCK_PTR);
6975e4b17023SJohn Marino if (e)
6976e4b17023SJohn Marino {
6977e4b17023SJohn Marino gsi_insert_on_edge (e, gimple_build_nop ());
6978e4b17023SJohn Marino gsi_commit_edge_inserts ();
6979e4b17023SJohn Marino }
6980e4b17023SJohn Marino }
6981e4b17023SJohn Marino }
6982e4b17023SJohn Marino
6983e4b17023SJohn Marino /* Now add fake edges to the function exit for any non constant
6984e4b17023SJohn Marino calls since there is no way that we can determine if they will
6985e4b17023SJohn Marino return or not... */
6986e4b17023SJohn Marino for (i = 0; i < last_bb; i++)
6987e4b17023SJohn Marino {
6988e4b17023SJohn Marino basic_block bb = BASIC_BLOCK (i);
6989e4b17023SJohn Marino gimple_stmt_iterator gsi;
6990e4b17023SJohn Marino gimple stmt, last_stmt;
6991e4b17023SJohn Marino
6992e4b17023SJohn Marino if (!bb)
6993e4b17023SJohn Marino continue;
6994e4b17023SJohn Marino
6995e4b17023SJohn Marino if (blocks && !TEST_BIT (blocks, i))
6996e4b17023SJohn Marino continue;
6997e4b17023SJohn Marino
6998e4b17023SJohn Marino gsi = gsi_last_nondebug_bb (bb);
6999e4b17023SJohn Marino if (!gsi_end_p (gsi))
7000e4b17023SJohn Marino {
7001e4b17023SJohn Marino last_stmt = gsi_stmt (gsi);
7002e4b17023SJohn Marino do
7003e4b17023SJohn Marino {
7004e4b17023SJohn Marino stmt = gsi_stmt (gsi);
7005e4b17023SJohn Marino if (need_fake_edge_p (stmt))
7006e4b17023SJohn Marino {
7007e4b17023SJohn Marino edge e;
7008e4b17023SJohn Marino
7009e4b17023SJohn Marino /* The handling above of the final block before the
7010e4b17023SJohn Marino epilogue should be enough to verify that there is
7011e4b17023SJohn Marino no edge to the exit block in CFG already.
7012e4b17023SJohn Marino Calling make_edge in such case would cause us to
7013e4b17023SJohn Marino mark that edge as fake and remove it later. */
7014e4b17023SJohn Marino #ifdef ENABLE_CHECKING
7015e4b17023SJohn Marino if (stmt == last_stmt)
7016e4b17023SJohn Marino {
7017e4b17023SJohn Marino e = find_edge (bb, EXIT_BLOCK_PTR);
7018e4b17023SJohn Marino gcc_assert (e == NULL);
7019e4b17023SJohn Marino }
7020e4b17023SJohn Marino #endif
7021e4b17023SJohn Marino
7022e4b17023SJohn Marino /* Note that the following may create a new basic block
7023e4b17023SJohn Marino and renumber the existing basic blocks. */
7024e4b17023SJohn Marino if (stmt != last_stmt)
7025e4b17023SJohn Marino {
7026e4b17023SJohn Marino e = split_block (bb, stmt);
7027e4b17023SJohn Marino if (e)
7028e4b17023SJohn Marino blocks_split++;
7029e4b17023SJohn Marino }
7030e4b17023SJohn Marino make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
7031e4b17023SJohn Marino }
7032e4b17023SJohn Marino gsi_prev (&gsi);
7033e4b17023SJohn Marino }
7034e4b17023SJohn Marino while (!gsi_end_p (gsi));
7035e4b17023SJohn Marino }
7036e4b17023SJohn Marino }
7037e4b17023SJohn Marino
7038e4b17023SJohn Marino if (blocks_split)
7039e4b17023SJohn Marino verify_flow_info ();
7040e4b17023SJohn Marino
7041e4b17023SJohn Marino return blocks_split;
7042e4b17023SJohn Marino }
7043e4b17023SJohn Marino
7044e4b17023SJohn Marino /* Removes edge E and all the blocks dominated by it, and updates dominance
7045e4b17023SJohn Marino information. The IL in E->src needs to be updated separately.
7046e4b17023SJohn Marino If dominance info is not available, only the edge E is removed.*/
7047e4b17023SJohn Marino
7048e4b17023SJohn Marino void
remove_edge_and_dominated_blocks(edge e)7049e4b17023SJohn Marino remove_edge_and_dominated_blocks (edge e)
7050e4b17023SJohn Marino {
7051e4b17023SJohn Marino VEC (basic_block, heap) *bbs_to_remove = NULL;
7052e4b17023SJohn Marino VEC (basic_block, heap) *bbs_to_fix_dom = NULL;
7053e4b17023SJohn Marino bitmap df, df_idom;
7054e4b17023SJohn Marino edge f;
7055e4b17023SJohn Marino edge_iterator ei;
7056e4b17023SJohn Marino bool none_removed = false;
7057e4b17023SJohn Marino unsigned i;
7058e4b17023SJohn Marino basic_block bb, dbb;
7059e4b17023SJohn Marino bitmap_iterator bi;
7060e4b17023SJohn Marino
7061e4b17023SJohn Marino if (!dom_info_available_p (CDI_DOMINATORS))
7062e4b17023SJohn Marino {
7063e4b17023SJohn Marino remove_edge (e);
7064e4b17023SJohn Marino return;
7065e4b17023SJohn Marino }
7066e4b17023SJohn Marino
7067e4b17023SJohn Marino /* No updating is needed for edges to exit. */
7068e4b17023SJohn Marino if (e->dest == EXIT_BLOCK_PTR)
7069e4b17023SJohn Marino {
7070e4b17023SJohn Marino if (cfgcleanup_altered_bbs)
7071e4b17023SJohn Marino bitmap_set_bit (cfgcleanup_altered_bbs, e->src->index);
7072e4b17023SJohn Marino remove_edge (e);
7073e4b17023SJohn Marino return;
7074e4b17023SJohn Marino }
7075e4b17023SJohn Marino
7076e4b17023SJohn Marino /* First, we find the basic blocks to remove. If E->dest has a predecessor
7077e4b17023SJohn Marino that is not dominated by E->dest, then this set is empty. Otherwise,
7078e4b17023SJohn Marino all the basic blocks dominated by E->dest are removed.
7079e4b17023SJohn Marino
7080e4b17023SJohn Marino Also, to DF_IDOM we store the immediate dominators of the blocks in
7081e4b17023SJohn Marino the dominance frontier of E (i.e., of the successors of the
7082e4b17023SJohn Marino removed blocks, if there are any, and of E->dest otherwise). */
7083e4b17023SJohn Marino FOR_EACH_EDGE (f, ei, e->dest->preds)
7084e4b17023SJohn Marino {
7085e4b17023SJohn Marino if (f == e)
7086e4b17023SJohn Marino continue;
7087e4b17023SJohn Marino
7088e4b17023SJohn Marino if (!dominated_by_p (CDI_DOMINATORS, f->src, e->dest))
7089e4b17023SJohn Marino {
7090e4b17023SJohn Marino none_removed = true;
7091e4b17023SJohn Marino break;
7092e4b17023SJohn Marino }
7093e4b17023SJohn Marino }
7094e4b17023SJohn Marino
7095e4b17023SJohn Marino df = BITMAP_ALLOC (NULL);
7096e4b17023SJohn Marino df_idom = BITMAP_ALLOC (NULL);
7097e4b17023SJohn Marino
7098e4b17023SJohn Marino if (none_removed)
7099e4b17023SJohn Marino bitmap_set_bit (df_idom,
7100e4b17023SJohn Marino get_immediate_dominator (CDI_DOMINATORS, e->dest)->index);
7101e4b17023SJohn Marino else
7102e4b17023SJohn Marino {
7103e4b17023SJohn Marino bbs_to_remove = get_all_dominated_blocks (CDI_DOMINATORS, e->dest);
7104e4b17023SJohn Marino FOR_EACH_VEC_ELT (basic_block, bbs_to_remove, i, bb)
7105e4b17023SJohn Marino {
7106e4b17023SJohn Marino FOR_EACH_EDGE (f, ei, bb->succs)
7107e4b17023SJohn Marino {
7108e4b17023SJohn Marino if (f->dest != EXIT_BLOCK_PTR)
7109e4b17023SJohn Marino bitmap_set_bit (df, f->dest->index);
7110e4b17023SJohn Marino }
7111e4b17023SJohn Marino }
7112e4b17023SJohn Marino FOR_EACH_VEC_ELT (basic_block, bbs_to_remove, i, bb)
7113e4b17023SJohn Marino bitmap_clear_bit (df, bb->index);
7114e4b17023SJohn Marino
7115e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (df, 0, i, bi)
7116e4b17023SJohn Marino {
7117e4b17023SJohn Marino bb = BASIC_BLOCK (i);
7118e4b17023SJohn Marino bitmap_set_bit (df_idom,
7119e4b17023SJohn Marino get_immediate_dominator (CDI_DOMINATORS, bb)->index);
7120e4b17023SJohn Marino }
7121e4b17023SJohn Marino }
7122e4b17023SJohn Marino
7123e4b17023SJohn Marino if (cfgcleanup_altered_bbs)
7124e4b17023SJohn Marino {
7125e4b17023SJohn Marino /* Record the set of the altered basic blocks. */
7126e4b17023SJohn Marino bitmap_set_bit (cfgcleanup_altered_bbs, e->src->index);
7127e4b17023SJohn Marino bitmap_ior_into (cfgcleanup_altered_bbs, df);
7128e4b17023SJohn Marino }
7129e4b17023SJohn Marino
7130e4b17023SJohn Marino /* Remove E and the cancelled blocks. */
7131e4b17023SJohn Marino if (none_removed)
7132e4b17023SJohn Marino remove_edge (e);
7133e4b17023SJohn Marino else
7134e4b17023SJohn Marino {
7135e4b17023SJohn Marino /* Walk backwards so as to get a chance to substitute all
7136e4b17023SJohn Marino released DEFs into debug stmts. See
7137e4b17023SJohn Marino eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
7138e4b17023SJohn Marino details. */
7139e4b17023SJohn Marino for (i = VEC_length (basic_block, bbs_to_remove); i-- > 0; )
7140e4b17023SJohn Marino delete_basic_block (VEC_index (basic_block, bbs_to_remove, i));
7141e4b17023SJohn Marino }
7142e4b17023SJohn Marino
7143e4b17023SJohn Marino /* Update the dominance information. The immediate dominator may change only
7144e4b17023SJohn Marino for blocks whose immediate dominator belongs to DF_IDOM:
7145e4b17023SJohn Marino
7146e4b17023SJohn Marino Suppose that idom(X) = Y before removal of E and idom(X) != Y after the
7147e4b17023SJohn Marino removal. Let Z the arbitrary block such that idom(Z) = Y and
7148e4b17023SJohn Marino Z dominates X after the removal. Before removal, there exists a path P
7149e4b17023SJohn Marino from Y to X that avoids Z. Let F be the last edge on P that is
7150e4b17023SJohn Marino removed, and let W = F->dest. Before removal, idom(W) = Y (since Y
7151e4b17023SJohn Marino dominates W, and because of P, Z does not dominate W), and W belongs to
7152e4b17023SJohn Marino the dominance frontier of E. Therefore, Y belongs to DF_IDOM. */
7153e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (df_idom, 0, i, bi)
7154e4b17023SJohn Marino {
7155e4b17023SJohn Marino bb = BASIC_BLOCK (i);
7156e4b17023SJohn Marino for (dbb = first_dom_son (CDI_DOMINATORS, bb);
7157e4b17023SJohn Marino dbb;
7158e4b17023SJohn Marino dbb = next_dom_son (CDI_DOMINATORS, dbb))
7159e4b17023SJohn Marino VEC_safe_push (basic_block, heap, bbs_to_fix_dom, dbb);
7160e4b17023SJohn Marino }
7161e4b17023SJohn Marino
7162e4b17023SJohn Marino iterate_fix_dominators (CDI_DOMINATORS, bbs_to_fix_dom, true);
7163e4b17023SJohn Marino
7164e4b17023SJohn Marino BITMAP_FREE (df);
7165e4b17023SJohn Marino BITMAP_FREE (df_idom);
7166e4b17023SJohn Marino VEC_free (basic_block, heap, bbs_to_remove);
7167e4b17023SJohn Marino VEC_free (basic_block, heap, bbs_to_fix_dom);
7168e4b17023SJohn Marino }
7169e4b17023SJohn Marino
7170e4b17023SJohn Marino /* Purge dead EH edges from basic block BB. */
7171e4b17023SJohn Marino
7172e4b17023SJohn Marino bool
gimple_purge_dead_eh_edges(basic_block bb)7173e4b17023SJohn Marino gimple_purge_dead_eh_edges (basic_block bb)
7174e4b17023SJohn Marino {
7175e4b17023SJohn Marino bool changed = false;
7176e4b17023SJohn Marino edge e;
7177e4b17023SJohn Marino edge_iterator ei;
7178e4b17023SJohn Marino gimple stmt = last_stmt (bb);
7179e4b17023SJohn Marino
7180e4b17023SJohn Marino if (stmt && stmt_can_throw_internal (stmt))
7181e4b17023SJohn Marino return false;
7182e4b17023SJohn Marino
7183e4b17023SJohn Marino for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
7184e4b17023SJohn Marino {
7185e4b17023SJohn Marino if (e->flags & EDGE_EH)
7186e4b17023SJohn Marino {
7187e4b17023SJohn Marino remove_edge_and_dominated_blocks (e);
7188e4b17023SJohn Marino changed = true;
7189e4b17023SJohn Marino }
7190e4b17023SJohn Marino else
7191e4b17023SJohn Marino ei_next (&ei);
7192e4b17023SJohn Marino }
7193e4b17023SJohn Marino
7194e4b17023SJohn Marino return changed;
7195e4b17023SJohn Marino }
7196e4b17023SJohn Marino
7197e4b17023SJohn Marino /* Purge dead EH edges from basic block listed in BLOCKS. */
7198e4b17023SJohn Marino
7199e4b17023SJohn Marino bool
gimple_purge_all_dead_eh_edges(const_bitmap blocks)7200e4b17023SJohn Marino gimple_purge_all_dead_eh_edges (const_bitmap blocks)
7201e4b17023SJohn Marino {
7202e4b17023SJohn Marino bool changed = false;
7203e4b17023SJohn Marino unsigned i;
7204e4b17023SJohn Marino bitmap_iterator bi;
7205e4b17023SJohn Marino
7206e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i, bi)
7207e4b17023SJohn Marino {
7208e4b17023SJohn Marino basic_block bb = BASIC_BLOCK (i);
7209e4b17023SJohn Marino
7210e4b17023SJohn Marino /* Earlier gimple_purge_dead_eh_edges could have removed
7211e4b17023SJohn Marino this basic block already. */
7212e4b17023SJohn Marino gcc_assert (bb || changed);
7213e4b17023SJohn Marino if (bb != NULL)
7214e4b17023SJohn Marino changed |= gimple_purge_dead_eh_edges (bb);
7215e4b17023SJohn Marino }
7216e4b17023SJohn Marino
7217e4b17023SJohn Marino return changed;
7218e4b17023SJohn Marino }
7219e4b17023SJohn Marino
7220e4b17023SJohn Marino /* Purge dead abnormal call edges from basic block BB. */
7221e4b17023SJohn Marino
7222e4b17023SJohn Marino bool
gimple_purge_dead_abnormal_call_edges(basic_block bb)7223e4b17023SJohn Marino gimple_purge_dead_abnormal_call_edges (basic_block bb)
7224e4b17023SJohn Marino {
7225e4b17023SJohn Marino bool changed = false;
7226e4b17023SJohn Marino edge e;
7227e4b17023SJohn Marino edge_iterator ei;
7228e4b17023SJohn Marino gimple stmt = last_stmt (bb);
7229e4b17023SJohn Marino
7230e4b17023SJohn Marino if (!cfun->has_nonlocal_label)
7231e4b17023SJohn Marino return false;
7232e4b17023SJohn Marino
7233e4b17023SJohn Marino if (stmt && stmt_can_make_abnormal_goto (stmt))
7234e4b17023SJohn Marino return false;
7235e4b17023SJohn Marino
7236e4b17023SJohn Marino for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
7237e4b17023SJohn Marino {
7238e4b17023SJohn Marino if (e->flags & EDGE_ABNORMAL)
7239e4b17023SJohn Marino {
7240e4b17023SJohn Marino remove_edge_and_dominated_blocks (e);
7241e4b17023SJohn Marino changed = true;
7242e4b17023SJohn Marino }
7243e4b17023SJohn Marino else
7244e4b17023SJohn Marino ei_next (&ei);
7245e4b17023SJohn Marino }
7246e4b17023SJohn Marino
7247e4b17023SJohn Marino return changed;
7248e4b17023SJohn Marino }
7249e4b17023SJohn Marino
7250e4b17023SJohn Marino /* Purge dead abnormal call edges from basic block listed in BLOCKS. */
7251e4b17023SJohn Marino
7252e4b17023SJohn Marino bool
gimple_purge_all_dead_abnormal_call_edges(const_bitmap blocks)7253e4b17023SJohn Marino gimple_purge_all_dead_abnormal_call_edges (const_bitmap blocks)
7254e4b17023SJohn Marino {
7255e4b17023SJohn Marino bool changed = false;
7256e4b17023SJohn Marino unsigned i;
7257e4b17023SJohn Marino bitmap_iterator bi;
7258e4b17023SJohn Marino
7259e4b17023SJohn Marino EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i, bi)
7260e4b17023SJohn Marino {
7261e4b17023SJohn Marino basic_block bb = BASIC_BLOCK (i);
7262e4b17023SJohn Marino
7263e4b17023SJohn Marino /* Earlier gimple_purge_dead_abnormal_call_edges could have removed
7264e4b17023SJohn Marino this basic block already. */
7265e4b17023SJohn Marino gcc_assert (bb || changed);
7266e4b17023SJohn Marino if (bb != NULL)
7267e4b17023SJohn Marino changed |= gimple_purge_dead_abnormal_call_edges (bb);
7268e4b17023SJohn Marino }
7269e4b17023SJohn Marino
7270e4b17023SJohn Marino return changed;
7271e4b17023SJohn Marino }
7272e4b17023SJohn Marino
7273e4b17023SJohn Marino /* This function is called whenever a new edge is created or
7274e4b17023SJohn Marino redirected. */
7275e4b17023SJohn Marino
7276e4b17023SJohn Marino static void
gimple_execute_on_growing_pred(edge e)7277e4b17023SJohn Marino gimple_execute_on_growing_pred (edge e)
7278e4b17023SJohn Marino {
7279e4b17023SJohn Marino basic_block bb = e->dest;
7280e4b17023SJohn Marino
7281e4b17023SJohn Marino if (!gimple_seq_empty_p (phi_nodes (bb)))
7282e4b17023SJohn Marino reserve_phi_args_for_new_edge (bb);
7283e4b17023SJohn Marino }
7284e4b17023SJohn Marino
7285e4b17023SJohn Marino /* This function is called immediately before edge E is removed from
7286e4b17023SJohn Marino the edge vector E->dest->preds. */
7287e4b17023SJohn Marino
7288e4b17023SJohn Marino static void
gimple_execute_on_shrinking_pred(edge e)7289e4b17023SJohn Marino gimple_execute_on_shrinking_pred (edge e)
7290e4b17023SJohn Marino {
7291e4b17023SJohn Marino if (!gimple_seq_empty_p (phi_nodes (e->dest)))
7292e4b17023SJohn Marino remove_phi_args (e);
7293e4b17023SJohn Marino }
7294e4b17023SJohn Marino
7295e4b17023SJohn Marino /*---------------------------------------------------------------------------
7296e4b17023SJohn Marino Helper functions for Loop versioning
7297e4b17023SJohn Marino ---------------------------------------------------------------------------*/
7298e4b17023SJohn Marino
7299e4b17023SJohn Marino /* Adjust phi nodes for 'first' basic block. 'second' basic block is a copy
7300e4b17023SJohn Marino of 'first'. Both of them are dominated by 'new_head' basic block. When
7301e4b17023SJohn Marino 'new_head' was created by 'second's incoming edge it received phi arguments
7302e4b17023SJohn Marino on the edge by split_edge(). Later, additional edge 'e' was created to
7303e4b17023SJohn Marino connect 'new_head' and 'first'. Now this routine adds phi args on this
7304e4b17023SJohn Marino additional edge 'e' that new_head to second edge received as part of edge
7305e4b17023SJohn Marino splitting. */
7306e4b17023SJohn Marino
7307e4b17023SJohn Marino static void
gimple_lv_adjust_loop_header_phi(basic_block first,basic_block second,basic_block new_head,edge e)7308e4b17023SJohn Marino gimple_lv_adjust_loop_header_phi (basic_block first, basic_block second,
7309e4b17023SJohn Marino basic_block new_head, edge e)
7310e4b17023SJohn Marino {
7311e4b17023SJohn Marino gimple phi1, phi2;
7312e4b17023SJohn Marino gimple_stmt_iterator psi1, psi2;
7313e4b17023SJohn Marino tree def;
7314e4b17023SJohn Marino edge e2 = find_edge (new_head, second);
7315e4b17023SJohn Marino
7316e4b17023SJohn Marino /* Because NEW_HEAD has been created by splitting SECOND's incoming
7317e4b17023SJohn Marino edge, we should always have an edge from NEW_HEAD to SECOND. */
7318e4b17023SJohn Marino gcc_assert (e2 != NULL);
7319e4b17023SJohn Marino
7320e4b17023SJohn Marino /* Browse all 'second' basic block phi nodes and add phi args to
7321e4b17023SJohn Marino edge 'e' for 'first' head. PHI args are always in correct order. */
7322e4b17023SJohn Marino
7323e4b17023SJohn Marino for (psi2 = gsi_start_phis (second),
7324e4b17023SJohn Marino psi1 = gsi_start_phis (first);
7325e4b17023SJohn Marino !gsi_end_p (psi2) && !gsi_end_p (psi1);
7326e4b17023SJohn Marino gsi_next (&psi2), gsi_next (&psi1))
7327e4b17023SJohn Marino {
7328e4b17023SJohn Marino phi1 = gsi_stmt (psi1);
7329e4b17023SJohn Marino phi2 = gsi_stmt (psi2);
7330e4b17023SJohn Marino def = PHI_ARG_DEF (phi2, e2->dest_idx);
7331e4b17023SJohn Marino add_phi_arg (phi1, def, e, gimple_phi_arg_location_from_edge (phi2, e2));
7332e4b17023SJohn Marino }
7333e4b17023SJohn Marino }
7334e4b17023SJohn Marino
7335e4b17023SJohn Marino
7336e4b17023SJohn Marino /* Adds a if else statement to COND_BB with condition COND_EXPR.
7337e4b17023SJohn Marino SECOND_HEAD is the destination of the THEN and FIRST_HEAD is
7338e4b17023SJohn Marino the destination of the ELSE part. */
7339e4b17023SJohn Marino
7340e4b17023SJohn Marino static void
gimple_lv_add_condition_to_bb(basic_block first_head ATTRIBUTE_UNUSED,basic_block second_head ATTRIBUTE_UNUSED,basic_block cond_bb,void * cond_e)7341e4b17023SJohn Marino gimple_lv_add_condition_to_bb (basic_block first_head ATTRIBUTE_UNUSED,
7342e4b17023SJohn Marino basic_block second_head ATTRIBUTE_UNUSED,
7343e4b17023SJohn Marino basic_block cond_bb, void *cond_e)
7344e4b17023SJohn Marino {
7345e4b17023SJohn Marino gimple_stmt_iterator gsi;
7346e4b17023SJohn Marino gimple new_cond_expr;
7347e4b17023SJohn Marino tree cond_expr = (tree) cond_e;
7348e4b17023SJohn Marino edge e0;
7349e4b17023SJohn Marino
7350e4b17023SJohn Marino /* Build new conditional expr */
7351e4b17023SJohn Marino new_cond_expr = gimple_build_cond_from_tree (cond_expr,
7352e4b17023SJohn Marino NULL_TREE, NULL_TREE);
7353e4b17023SJohn Marino
7354e4b17023SJohn Marino /* Add new cond in cond_bb. */
7355e4b17023SJohn Marino gsi = gsi_last_bb (cond_bb);
7356e4b17023SJohn Marino gsi_insert_after (&gsi, new_cond_expr, GSI_NEW_STMT);
7357e4b17023SJohn Marino
7358e4b17023SJohn Marino /* Adjust edges appropriately to connect new head with first head
7359e4b17023SJohn Marino as well as second head. */
7360e4b17023SJohn Marino e0 = single_succ_edge (cond_bb);
7361e4b17023SJohn Marino e0->flags &= ~EDGE_FALLTHRU;
7362e4b17023SJohn Marino e0->flags |= EDGE_FALSE_VALUE;
7363e4b17023SJohn Marino }
7364e4b17023SJohn Marino
7365e4b17023SJohn Marino struct cfg_hooks gimple_cfg_hooks = {
7366e4b17023SJohn Marino "gimple",
7367e4b17023SJohn Marino gimple_verify_flow_info,
7368e4b17023SJohn Marino gimple_dump_bb, /* dump_bb */
7369e4b17023SJohn Marino create_bb, /* create_basic_block */
7370e4b17023SJohn Marino gimple_redirect_edge_and_branch, /* redirect_edge_and_branch */
7371e4b17023SJohn Marino gimple_redirect_edge_and_branch_force, /* redirect_edge_and_branch_force */
7372e4b17023SJohn Marino gimple_can_remove_branch_p, /* can_remove_branch_p */
7373e4b17023SJohn Marino remove_bb, /* delete_basic_block */
7374e4b17023SJohn Marino gimple_split_block, /* split_block */
7375e4b17023SJohn Marino gimple_move_block_after, /* move_block_after */
7376e4b17023SJohn Marino gimple_can_merge_blocks_p, /* can_merge_blocks_p */
7377e4b17023SJohn Marino gimple_merge_blocks, /* merge_blocks */
7378e4b17023SJohn Marino gimple_predict_edge, /* predict_edge */
7379e4b17023SJohn Marino gimple_predicted_by_p, /* predicted_by_p */
7380e4b17023SJohn Marino gimple_can_duplicate_bb_p, /* can_duplicate_block_p */
7381e4b17023SJohn Marino gimple_duplicate_bb, /* duplicate_block */
7382e4b17023SJohn Marino gimple_split_edge, /* split_edge */
7383e4b17023SJohn Marino gimple_make_forwarder_block, /* make_forward_block */
7384e4b17023SJohn Marino NULL, /* tidy_fallthru_edge */
7385e4b17023SJohn Marino NULL, /* force_nonfallthru */
7386e4b17023SJohn Marino gimple_block_ends_with_call_p,/* block_ends_with_call_p */
7387e4b17023SJohn Marino gimple_block_ends_with_condjump_p, /* block_ends_with_condjump_p */
7388e4b17023SJohn Marino gimple_flow_call_edges_add, /* flow_call_edges_add */
7389e4b17023SJohn Marino gimple_execute_on_growing_pred, /* execute_on_growing_pred */
7390e4b17023SJohn Marino gimple_execute_on_shrinking_pred, /* execute_on_shrinking_pred */
7391e4b17023SJohn Marino gimple_duplicate_loop_to_header_edge, /* duplicate loop for trees */
7392e4b17023SJohn Marino gimple_lv_add_condition_to_bb, /* lv_add_condition_to_bb */
7393e4b17023SJohn Marino gimple_lv_adjust_loop_header_phi, /* lv_adjust_loop_header_phi*/
7394e4b17023SJohn Marino extract_true_false_edges_from_block, /* extract_cond_bb_edges */
7395e4b17023SJohn Marino flush_pending_stmts /* flush_pending_stmts */
7396e4b17023SJohn Marino };
7397e4b17023SJohn Marino
7398e4b17023SJohn Marino
7399e4b17023SJohn Marino /* Split all critical edges. */
7400e4b17023SJohn Marino
7401*95d28233SJohn Marino unsigned int
split_critical_edges(void)7402e4b17023SJohn Marino split_critical_edges (void)
7403e4b17023SJohn Marino {
7404e4b17023SJohn Marino basic_block bb;
7405e4b17023SJohn Marino edge e;
7406e4b17023SJohn Marino edge_iterator ei;
7407e4b17023SJohn Marino
7408e4b17023SJohn Marino /* split_edge can redirect edges out of SWITCH_EXPRs, which can get
7409e4b17023SJohn Marino expensive. So we want to enable recording of edge to CASE_LABEL_EXPR
7410e4b17023SJohn Marino mappings around the calls to split_edge. */
7411e4b17023SJohn Marino start_recording_case_labels ();
7412e4b17023SJohn Marino FOR_ALL_BB (bb)
7413e4b17023SJohn Marino {
7414e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
7415e4b17023SJohn Marino {
7416e4b17023SJohn Marino if (EDGE_CRITICAL_P (e) && !(e->flags & EDGE_ABNORMAL))
7417e4b17023SJohn Marino split_edge (e);
7418e4b17023SJohn Marino /* PRE inserts statements to edges and expects that
7419e4b17023SJohn Marino since split_critical_edges was done beforehand, committing edge
7420e4b17023SJohn Marino insertions will not split more edges. In addition to critical
7421e4b17023SJohn Marino edges we must split edges that have multiple successors and
7422e4b17023SJohn Marino end by control flow statements, such as RESX.
7423e4b17023SJohn Marino Go ahead and split them too. This matches the logic in
7424e4b17023SJohn Marino gimple_find_edge_insert_loc. */
7425e4b17023SJohn Marino else if ((!single_pred_p (e->dest)
7426e4b17023SJohn Marino || !gimple_seq_empty_p (phi_nodes (e->dest))
7427e4b17023SJohn Marino || e->dest == EXIT_BLOCK_PTR)
7428e4b17023SJohn Marino && e->src != ENTRY_BLOCK_PTR
7429e4b17023SJohn Marino && !(e->flags & EDGE_ABNORMAL))
7430e4b17023SJohn Marino {
7431e4b17023SJohn Marino gimple_stmt_iterator gsi;
7432e4b17023SJohn Marino
7433e4b17023SJohn Marino gsi = gsi_last_bb (e->src);
7434e4b17023SJohn Marino if (!gsi_end_p (gsi)
7435e4b17023SJohn Marino && stmt_ends_bb_p (gsi_stmt (gsi))
7436e4b17023SJohn Marino && (gimple_code (gsi_stmt (gsi)) != GIMPLE_RETURN
7437e4b17023SJohn Marino && !gimple_call_builtin_p (gsi_stmt (gsi),
7438e4b17023SJohn Marino BUILT_IN_RETURN)))
7439e4b17023SJohn Marino split_edge (e);
7440e4b17023SJohn Marino }
7441e4b17023SJohn Marino }
7442e4b17023SJohn Marino }
7443e4b17023SJohn Marino end_recording_case_labels ();
7444e4b17023SJohn Marino return 0;
7445e4b17023SJohn Marino }
7446e4b17023SJohn Marino
7447e4b17023SJohn Marino struct gimple_opt_pass pass_split_crit_edges =
7448e4b17023SJohn Marino {
7449e4b17023SJohn Marino {
7450e4b17023SJohn Marino GIMPLE_PASS,
7451e4b17023SJohn Marino "crited", /* name */
7452e4b17023SJohn Marino NULL, /* gate */
7453e4b17023SJohn Marino split_critical_edges, /* execute */
7454e4b17023SJohn Marino NULL, /* sub */
7455e4b17023SJohn Marino NULL, /* next */
7456e4b17023SJohn Marino 0, /* static_pass_number */
7457e4b17023SJohn Marino TV_TREE_SPLIT_EDGES, /* tv_id */
7458e4b17023SJohn Marino PROP_cfg, /* properties required */
7459e4b17023SJohn Marino PROP_no_crit_edges, /* properties_provided */
7460e4b17023SJohn Marino 0, /* properties_destroyed */
7461e4b17023SJohn Marino 0, /* todo_flags_start */
7462e4b17023SJohn Marino TODO_verify_flow /* todo_flags_finish */
7463e4b17023SJohn Marino }
7464e4b17023SJohn Marino };
7465e4b17023SJohn Marino
7466e4b17023SJohn Marino
7467e4b17023SJohn Marino /* Build a ternary operation and gimplify it. Emit code before GSI.
7468e4b17023SJohn Marino Return the gimple_val holding the result. */
7469e4b17023SJohn Marino
7470e4b17023SJohn Marino tree
gimplify_build3(gimple_stmt_iterator * gsi,enum tree_code code,tree type,tree a,tree b,tree c)7471e4b17023SJohn Marino gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
7472e4b17023SJohn Marino tree type, tree a, tree b, tree c)
7473e4b17023SJohn Marino {
7474e4b17023SJohn Marino tree ret;
7475e4b17023SJohn Marino location_t loc = gimple_location (gsi_stmt (*gsi));
7476e4b17023SJohn Marino
7477e4b17023SJohn Marino ret = fold_build3_loc (loc, code, type, a, b, c);
7478e4b17023SJohn Marino STRIP_NOPS (ret);
7479e4b17023SJohn Marino
7480e4b17023SJohn Marino return force_gimple_operand_gsi (gsi, ret, true, NULL, true,
7481e4b17023SJohn Marino GSI_SAME_STMT);
7482e4b17023SJohn Marino }
7483e4b17023SJohn Marino
7484e4b17023SJohn Marino /* Build a binary operation and gimplify it. Emit code before GSI.
7485e4b17023SJohn Marino Return the gimple_val holding the result. */
7486e4b17023SJohn Marino
7487e4b17023SJohn Marino tree
gimplify_build2(gimple_stmt_iterator * gsi,enum tree_code code,tree type,tree a,tree b)7488e4b17023SJohn Marino gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
7489e4b17023SJohn Marino tree type, tree a, tree b)
7490e4b17023SJohn Marino {
7491e4b17023SJohn Marino tree ret;
7492e4b17023SJohn Marino
7493e4b17023SJohn Marino ret = fold_build2_loc (gimple_location (gsi_stmt (*gsi)), code, type, a, b);
7494e4b17023SJohn Marino STRIP_NOPS (ret);
7495e4b17023SJohn Marino
7496e4b17023SJohn Marino return force_gimple_operand_gsi (gsi, ret, true, NULL, true,
7497e4b17023SJohn Marino GSI_SAME_STMT);
7498e4b17023SJohn Marino }
7499e4b17023SJohn Marino
7500e4b17023SJohn Marino /* Build a unary operation and gimplify it. Emit code before GSI.
7501e4b17023SJohn Marino Return the gimple_val holding the result. */
7502e4b17023SJohn Marino
7503e4b17023SJohn Marino tree
gimplify_build1(gimple_stmt_iterator * gsi,enum tree_code code,tree type,tree a)7504e4b17023SJohn Marino gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
7505e4b17023SJohn Marino tree a)
7506e4b17023SJohn Marino {
7507e4b17023SJohn Marino tree ret;
7508e4b17023SJohn Marino
7509e4b17023SJohn Marino ret = fold_build1_loc (gimple_location (gsi_stmt (*gsi)), code, type, a);
7510e4b17023SJohn Marino STRIP_NOPS (ret);
7511e4b17023SJohn Marino
7512e4b17023SJohn Marino return force_gimple_operand_gsi (gsi, ret, true, NULL, true,
7513e4b17023SJohn Marino GSI_SAME_STMT);
7514e4b17023SJohn Marino }
7515e4b17023SJohn Marino
7516e4b17023SJohn Marino
7517e4b17023SJohn Marino
7518e4b17023SJohn Marino /* Emit return warnings. */
7519e4b17023SJohn Marino
7520e4b17023SJohn Marino static unsigned int
execute_warn_function_return(void)7521e4b17023SJohn Marino execute_warn_function_return (void)
7522e4b17023SJohn Marino {
7523e4b17023SJohn Marino source_location location;
7524e4b17023SJohn Marino gimple last;
7525e4b17023SJohn Marino edge e;
7526e4b17023SJohn Marino edge_iterator ei;
7527e4b17023SJohn Marino
7528e4b17023SJohn Marino /* If we have a path to EXIT, then we do return. */
7529e4b17023SJohn Marino if (TREE_THIS_VOLATILE (cfun->decl)
7530e4b17023SJohn Marino && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0)
7531e4b17023SJohn Marino {
7532e4b17023SJohn Marino location = UNKNOWN_LOCATION;
7533e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
7534e4b17023SJohn Marino {
7535e4b17023SJohn Marino last = last_stmt (e->src);
7536e4b17023SJohn Marino if ((gimple_code (last) == GIMPLE_RETURN
7537e4b17023SJohn Marino || gimple_call_builtin_p (last, BUILT_IN_RETURN))
7538e4b17023SJohn Marino && (location = gimple_location (last)) != UNKNOWN_LOCATION)
7539e4b17023SJohn Marino break;
7540e4b17023SJohn Marino }
7541e4b17023SJohn Marino if (location == UNKNOWN_LOCATION)
7542e4b17023SJohn Marino location = cfun->function_end_locus;
7543e4b17023SJohn Marino warning_at (location, 0, "%<noreturn%> function does return");
7544e4b17023SJohn Marino }
7545e4b17023SJohn Marino
7546e4b17023SJohn Marino /* If we see "return;" in some basic block, then we do reach the end
7547e4b17023SJohn Marino without returning a value. */
7548e4b17023SJohn Marino else if (warn_return_type
7549e4b17023SJohn Marino && !TREE_NO_WARNING (cfun->decl)
7550e4b17023SJohn Marino && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0
7551e4b17023SJohn Marino && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
7552e4b17023SJohn Marino {
7553e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
7554e4b17023SJohn Marino {
7555e4b17023SJohn Marino gimple last = last_stmt (e->src);
7556e4b17023SJohn Marino if (gimple_code (last) == GIMPLE_RETURN
7557e4b17023SJohn Marino && gimple_return_retval (last) == NULL
7558e4b17023SJohn Marino && !gimple_no_warning_p (last))
7559e4b17023SJohn Marino {
7560e4b17023SJohn Marino location = gimple_location (last);
7561e4b17023SJohn Marino if (location == UNKNOWN_LOCATION)
7562e4b17023SJohn Marino location = cfun->function_end_locus;
7563e4b17023SJohn Marino warning_at (location, OPT_Wreturn_type, "control reaches end of non-void function");
7564e4b17023SJohn Marino TREE_NO_WARNING (cfun->decl) = 1;
7565e4b17023SJohn Marino break;
7566e4b17023SJohn Marino }
7567e4b17023SJohn Marino }
7568e4b17023SJohn Marino }
7569e4b17023SJohn Marino return 0;
7570e4b17023SJohn Marino }
7571e4b17023SJohn Marino
7572e4b17023SJohn Marino
7573e4b17023SJohn Marino /* Given a basic block B which ends with a conditional and has
7574e4b17023SJohn Marino precisely two successors, determine which of the edges is taken if
7575e4b17023SJohn Marino the conditional is true and which is taken if the conditional is
7576e4b17023SJohn Marino false. Set TRUE_EDGE and FALSE_EDGE appropriately. */
7577e4b17023SJohn Marino
7578e4b17023SJohn Marino void
extract_true_false_edges_from_block(basic_block b,edge * true_edge,edge * false_edge)7579e4b17023SJohn Marino extract_true_false_edges_from_block (basic_block b,
7580e4b17023SJohn Marino edge *true_edge,
7581e4b17023SJohn Marino edge *false_edge)
7582e4b17023SJohn Marino {
7583e4b17023SJohn Marino edge e = EDGE_SUCC (b, 0);
7584e4b17023SJohn Marino
7585e4b17023SJohn Marino if (e->flags & EDGE_TRUE_VALUE)
7586e4b17023SJohn Marino {
7587e4b17023SJohn Marino *true_edge = e;
7588e4b17023SJohn Marino *false_edge = EDGE_SUCC (b, 1);
7589e4b17023SJohn Marino }
7590e4b17023SJohn Marino else
7591e4b17023SJohn Marino {
7592e4b17023SJohn Marino *false_edge = e;
7593e4b17023SJohn Marino *true_edge = EDGE_SUCC (b, 1);
7594e4b17023SJohn Marino }
7595e4b17023SJohn Marino }
7596e4b17023SJohn Marino
7597e4b17023SJohn Marino struct gimple_opt_pass pass_warn_function_return =
7598e4b17023SJohn Marino {
7599e4b17023SJohn Marino {
7600e4b17023SJohn Marino GIMPLE_PASS,
7601e4b17023SJohn Marino "*warn_function_return", /* name */
7602e4b17023SJohn Marino NULL, /* gate */
7603e4b17023SJohn Marino execute_warn_function_return, /* execute */
7604e4b17023SJohn Marino NULL, /* sub */
7605e4b17023SJohn Marino NULL, /* next */
7606e4b17023SJohn Marino 0, /* static_pass_number */
7607e4b17023SJohn Marino TV_NONE, /* tv_id */
7608e4b17023SJohn Marino PROP_cfg, /* properties_required */
7609e4b17023SJohn Marino 0, /* properties_provided */
7610e4b17023SJohn Marino 0, /* properties_destroyed */
7611e4b17023SJohn Marino 0, /* todo_flags_start */
7612e4b17023SJohn Marino 0 /* todo_flags_finish */
7613e4b17023SJohn Marino }
7614e4b17023SJohn Marino };
7615e4b17023SJohn Marino
7616e4b17023SJohn Marino /* Emit noreturn warnings. */
7617e4b17023SJohn Marino
7618e4b17023SJohn Marino static unsigned int
execute_warn_function_noreturn(void)7619e4b17023SJohn Marino execute_warn_function_noreturn (void)
7620e4b17023SJohn Marino {
7621e4b17023SJohn Marino if (!TREE_THIS_VOLATILE (current_function_decl)
7622e4b17023SJohn Marino && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0)
7623e4b17023SJohn Marino warn_function_noreturn (current_function_decl);
7624e4b17023SJohn Marino return 0;
7625e4b17023SJohn Marino }
7626e4b17023SJohn Marino
7627e4b17023SJohn Marino static bool
gate_warn_function_noreturn(void)7628e4b17023SJohn Marino gate_warn_function_noreturn (void)
7629e4b17023SJohn Marino {
7630e4b17023SJohn Marino return warn_suggest_attribute_noreturn;
7631e4b17023SJohn Marino }
7632e4b17023SJohn Marino
7633e4b17023SJohn Marino struct gimple_opt_pass pass_warn_function_noreturn =
7634e4b17023SJohn Marino {
7635e4b17023SJohn Marino {
7636e4b17023SJohn Marino GIMPLE_PASS,
7637e4b17023SJohn Marino "*warn_function_noreturn", /* name */
7638e4b17023SJohn Marino gate_warn_function_noreturn, /* gate */
7639e4b17023SJohn Marino execute_warn_function_noreturn, /* execute */
7640e4b17023SJohn Marino NULL, /* sub */
7641e4b17023SJohn Marino NULL, /* next */
7642e4b17023SJohn Marino 0, /* static_pass_number */
7643e4b17023SJohn Marino TV_NONE, /* tv_id */
7644e4b17023SJohn Marino PROP_cfg, /* properties_required */
7645e4b17023SJohn Marino 0, /* properties_provided */
7646e4b17023SJohn Marino 0, /* properties_destroyed */
7647e4b17023SJohn Marino 0, /* todo_flags_start */
7648e4b17023SJohn Marino 0 /* todo_flags_finish */
7649e4b17023SJohn Marino }
7650e4b17023SJohn Marino };
7651e4b17023SJohn Marino
7652e4b17023SJohn Marino
7653e4b17023SJohn Marino /* Walk a gimplified function and warn for functions whose return value is
7654e4b17023SJohn Marino ignored and attribute((warn_unused_result)) is set. This is done before
7655e4b17023SJohn Marino inlining, so we don't have to worry about that. */
7656e4b17023SJohn Marino
7657e4b17023SJohn Marino static void
do_warn_unused_result(gimple_seq seq)7658e4b17023SJohn Marino do_warn_unused_result (gimple_seq seq)
7659e4b17023SJohn Marino {
7660e4b17023SJohn Marino tree fdecl, ftype;
7661e4b17023SJohn Marino gimple_stmt_iterator i;
7662e4b17023SJohn Marino
7663e4b17023SJohn Marino for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
7664e4b17023SJohn Marino {
7665e4b17023SJohn Marino gimple g = gsi_stmt (i);
7666e4b17023SJohn Marino
7667e4b17023SJohn Marino switch (gimple_code (g))
7668e4b17023SJohn Marino {
7669e4b17023SJohn Marino case GIMPLE_BIND:
7670e4b17023SJohn Marino do_warn_unused_result (gimple_bind_body (g));
7671e4b17023SJohn Marino break;
7672e4b17023SJohn Marino case GIMPLE_TRY:
7673e4b17023SJohn Marino do_warn_unused_result (gimple_try_eval (g));
7674e4b17023SJohn Marino do_warn_unused_result (gimple_try_cleanup (g));
7675e4b17023SJohn Marino break;
7676e4b17023SJohn Marino case GIMPLE_CATCH:
7677e4b17023SJohn Marino do_warn_unused_result (gimple_catch_handler (g));
7678e4b17023SJohn Marino break;
7679e4b17023SJohn Marino case GIMPLE_EH_FILTER:
7680e4b17023SJohn Marino do_warn_unused_result (gimple_eh_filter_failure (g));
7681e4b17023SJohn Marino break;
7682e4b17023SJohn Marino
7683e4b17023SJohn Marino case GIMPLE_CALL:
7684e4b17023SJohn Marino if (gimple_call_lhs (g))
7685e4b17023SJohn Marino break;
7686e4b17023SJohn Marino if (gimple_call_internal_p (g))
7687e4b17023SJohn Marino break;
7688e4b17023SJohn Marino
7689e4b17023SJohn Marino /* This is a naked call, as opposed to a GIMPLE_CALL with an
7690e4b17023SJohn Marino LHS. All calls whose value is ignored should be
7691e4b17023SJohn Marino represented like this. Look for the attribute. */
7692e4b17023SJohn Marino fdecl = gimple_call_fndecl (g);
7693e4b17023SJohn Marino ftype = gimple_call_fntype (g);
7694e4b17023SJohn Marino
7695e4b17023SJohn Marino if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
7696e4b17023SJohn Marino {
7697e4b17023SJohn Marino location_t loc = gimple_location (g);
7698e4b17023SJohn Marino
7699e4b17023SJohn Marino if (fdecl)
7700e4b17023SJohn Marino warning_at (loc, OPT_Wunused_result,
7701e4b17023SJohn Marino "ignoring return value of %qD, "
7702e4b17023SJohn Marino "declared with attribute warn_unused_result",
7703e4b17023SJohn Marino fdecl);
7704e4b17023SJohn Marino else
7705e4b17023SJohn Marino warning_at (loc, OPT_Wunused_result,
7706e4b17023SJohn Marino "ignoring return value of function "
7707e4b17023SJohn Marino "declared with attribute warn_unused_result");
7708e4b17023SJohn Marino }
7709e4b17023SJohn Marino break;
7710e4b17023SJohn Marino
7711e4b17023SJohn Marino default:
7712e4b17023SJohn Marino /* Not a container, not a call, or a call whose value is used. */
7713e4b17023SJohn Marino break;
7714e4b17023SJohn Marino }
7715e4b17023SJohn Marino }
7716e4b17023SJohn Marino }
7717e4b17023SJohn Marino
7718e4b17023SJohn Marino static unsigned int
run_warn_unused_result(void)7719e4b17023SJohn Marino run_warn_unused_result (void)
7720e4b17023SJohn Marino {
7721e4b17023SJohn Marino do_warn_unused_result (gimple_body (current_function_decl));
7722e4b17023SJohn Marino return 0;
7723e4b17023SJohn Marino }
7724e4b17023SJohn Marino
7725e4b17023SJohn Marino static bool
gate_warn_unused_result(void)7726e4b17023SJohn Marino gate_warn_unused_result (void)
7727e4b17023SJohn Marino {
7728e4b17023SJohn Marino return flag_warn_unused_result;
7729e4b17023SJohn Marino }
7730e4b17023SJohn Marino
7731e4b17023SJohn Marino struct gimple_opt_pass pass_warn_unused_result =
7732e4b17023SJohn Marino {
7733e4b17023SJohn Marino {
7734e4b17023SJohn Marino GIMPLE_PASS,
7735e4b17023SJohn Marino "*warn_unused_result", /* name */
7736e4b17023SJohn Marino gate_warn_unused_result, /* gate */
7737e4b17023SJohn Marino run_warn_unused_result, /* execute */
7738e4b17023SJohn Marino NULL, /* sub */
7739e4b17023SJohn Marino NULL, /* next */
7740e4b17023SJohn Marino 0, /* static_pass_number */
7741e4b17023SJohn Marino TV_NONE, /* tv_id */
7742e4b17023SJohn Marino PROP_gimple_any, /* properties_required */
7743e4b17023SJohn Marino 0, /* properties_provided */
7744e4b17023SJohn Marino 0, /* properties_destroyed */
7745e4b17023SJohn Marino 0, /* todo_flags_start */
7746e4b17023SJohn Marino 0, /* todo_flags_finish */
7747e4b17023SJohn Marino }
7748e4b17023SJohn Marino };
7749