xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-cfg.c (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
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