xref: /openbsd-src/gnu/gcc/gcc/tree-ssa-propagate.c (revision ad47ef84d0efe57c98b8641fe6c923a822d16b70)
1404b540aSrobert /* Generic SSA value propagation engine.
2404b540aSrobert    Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
3404b540aSrobert    Contributed by Diego Novillo <dnovillo@redhat.com>
4404b540aSrobert 
5404b540aSrobert    This file is part of GCC.
6404b540aSrobert 
7404b540aSrobert    GCC is free software; you can redistribute it and/or modify it
8404b540aSrobert    under the terms of the GNU General Public License as published by the
9404b540aSrobert    Free Software Foundation; either version 2, or (at your option) any
10404b540aSrobert    later version.
11404b540aSrobert 
12404b540aSrobert    GCC is distributed in the hope that it will be useful, but WITHOUT
13404b540aSrobert    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14404b540aSrobert    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15404b540aSrobert    for more details.
16404b540aSrobert 
17404b540aSrobert    You should have received a copy of the GNU General Public License
18404b540aSrobert    along with GCC; see the file COPYING.  If not, write to the Free
19404b540aSrobert    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20404b540aSrobert    02110-1301, USA.  */
21404b540aSrobert 
22404b540aSrobert #include "config.h"
23404b540aSrobert #include "system.h"
24404b540aSrobert #include "coretypes.h"
25404b540aSrobert #include "tm.h"
26404b540aSrobert #include "tree.h"
27404b540aSrobert #include "flags.h"
28404b540aSrobert #include "rtl.h"
29404b540aSrobert #include "tm_p.h"
30404b540aSrobert #include "ggc.h"
31404b540aSrobert #include "basic-block.h"
32404b540aSrobert #include "output.h"
33404b540aSrobert #include "expr.h"
34404b540aSrobert #include "function.h"
35404b540aSrobert #include "diagnostic.h"
36404b540aSrobert #include "timevar.h"
37404b540aSrobert #include "tree-dump.h"
38404b540aSrobert #include "tree-flow.h"
39404b540aSrobert #include "tree-pass.h"
40404b540aSrobert #include "tree-ssa-propagate.h"
41404b540aSrobert #include "langhooks.h"
42404b540aSrobert #include "varray.h"
43404b540aSrobert #include "vec.h"
44404b540aSrobert 
45404b540aSrobert /* This file implements a generic value propagation engine based on
46404b540aSrobert    the same propagation used by the SSA-CCP algorithm [1].
47404b540aSrobert 
48404b540aSrobert    Propagation is performed by simulating the execution of every
49404b540aSrobert    statement that produces the value being propagated.  Simulation
50404b540aSrobert    proceeds as follows:
51404b540aSrobert 
52404b540aSrobert    1- Initially, all edges of the CFG are marked not executable and
53404b540aSrobert       the CFG worklist is seeded with all the statements in the entry
54404b540aSrobert       basic block (block 0).
55404b540aSrobert 
56404b540aSrobert    2- Every statement S is simulated with a call to the call-back
57404b540aSrobert       function SSA_PROP_VISIT_STMT.  This evaluation may produce 3
58404b540aSrobert       results:
59404b540aSrobert 
60404b540aSrobert       	SSA_PROP_NOT_INTERESTING: Statement S produces nothing of
61404b540aSrobert 	    interest and does not affect any of the work lists.
62404b540aSrobert 
63404b540aSrobert 	SSA_PROP_VARYING: The value produced by S cannot be determined
64404b540aSrobert 	    at compile time.  Further simulation of S is not required.
65404b540aSrobert 	    If S is a conditional jump, all the outgoing edges for the
66404b540aSrobert 	    block are considered executable and added to the work
67404b540aSrobert 	    list.
68404b540aSrobert 
69404b540aSrobert 	SSA_PROP_INTERESTING: S produces a value that can be computed
70404b540aSrobert 	    at compile time.  Its result can be propagated into the
71404b540aSrobert 	    statements that feed from S.  Furthermore, if S is a
72404b540aSrobert 	    conditional jump, only the edge known to be taken is added
73404b540aSrobert 	    to the work list.  Edges that are known not to execute are
74404b540aSrobert 	    never simulated.
75404b540aSrobert 
76404b540aSrobert    3- PHI nodes are simulated with a call to SSA_PROP_VISIT_PHI.  The
77404b540aSrobert       return value from SSA_PROP_VISIT_PHI has the same semantics as
78404b540aSrobert       described in #2.
79404b540aSrobert 
80404b540aSrobert    4- Three work lists are kept.  Statements are only added to these
81404b540aSrobert       lists if they produce one of SSA_PROP_INTERESTING or
82404b540aSrobert       SSA_PROP_VARYING.
83404b540aSrobert 
84404b540aSrobert    	CFG_BLOCKS contains the list of blocks to be simulated.
85404b540aSrobert 	    Blocks are added to this list if their incoming edges are
86404b540aSrobert 	    found executable.
87404b540aSrobert 
88404b540aSrobert 	VARYING_SSA_EDGES contains the list of statements that feed
89404b540aSrobert 	    from statements that produce an SSA_PROP_VARYING result.
90404b540aSrobert 	    These are simulated first to speed up processing.
91404b540aSrobert 
92404b540aSrobert 	INTERESTING_SSA_EDGES contains the list of statements that
93404b540aSrobert 	    feed from statements that produce an SSA_PROP_INTERESTING
94404b540aSrobert 	    result.
95404b540aSrobert 
96404b540aSrobert    5- Simulation terminates when all three work lists are drained.
97404b540aSrobert 
98404b540aSrobert    Before calling ssa_propagate, it is important to clear
99404b540aSrobert    DONT_SIMULATE_AGAIN for all the statements in the program that
100404b540aSrobert    should be simulated.  This initialization allows an implementation
101404b540aSrobert    to specify which statements should never be simulated.
102404b540aSrobert 
103404b540aSrobert    It is also important to compute def-use information before calling
104404b540aSrobert    ssa_propagate.
105404b540aSrobert 
106404b540aSrobert    References:
107404b540aSrobert 
108404b540aSrobert      [1] Constant propagation with conditional branches,
109404b540aSrobert          Wegman and Zadeck, ACM TOPLAS 13(2):181-210.
110404b540aSrobert 
111404b540aSrobert      [2] Building an Optimizing Compiler,
112404b540aSrobert 	 Robert Morgan, Butterworth-Heinemann, 1998, Section 8.9.
113404b540aSrobert 
114404b540aSrobert      [3] Advanced Compiler Design and Implementation,
115404b540aSrobert 	 Steven Muchnick, Morgan Kaufmann, 1997, Section 12.6  */
116404b540aSrobert 
117404b540aSrobert /* Function pointers used to parameterize the propagation engine.  */
118404b540aSrobert static ssa_prop_visit_stmt_fn ssa_prop_visit_stmt;
119404b540aSrobert static ssa_prop_visit_phi_fn ssa_prop_visit_phi;
120404b540aSrobert 
121404b540aSrobert /* Use the TREE_DEPRECATED bitflag to mark statements that have been
122404b540aSrobert    added to one of the SSA edges worklists.  This flag is used to
123404b540aSrobert    avoid visiting statements unnecessarily when draining an SSA edge
124404b540aSrobert    worklist.  If while simulating a basic block, we find a statement with
125404b540aSrobert    STMT_IN_SSA_EDGE_WORKLIST set, we clear it to prevent SSA edge
126404b540aSrobert    processing from visiting it again.  */
127404b540aSrobert #define STMT_IN_SSA_EDGE_WORKLIST(T)	TREE_DEPRECATED (T)
128404b540aSrobert 
129404b540aSrobert /* A bitmap to keep track of executable blocks in the CFG.  */
130404b540aSrobert static sbitmap executable_blocks;
131404b540aSrobert 
132404b540aSrobert /* Array of control flow edges on the worklist.  */
133404b540aSrobert static VEC(basic_block,heap) *cfg_blocks;
134404b540aSrobert 
135404b540aSrobert static unsigned int cfg_blocks_num = 0;
136404b540aSrobert static int cfg_blocks_tail;
137404b540aSrobert static int cfg_blocks_head;
138404b540aSrobert 
139404b540aSrobert static sbitmap bb_in_list;
140404b540aSrobert 
141404b540aSrobert /* Worklist of SSA edges which will need reexamination as their
142404b540aSrobert    definition has changed.  SSA edges are def-use edges in the SSA
143404b540aSrobert    web.  For each D-U edge, we store the target statement or PHI node
144404b540aSrobert    U.  */
145404b540aSrobert static GTY(()) VEC(tree,gc) *interesting_ssa_edges;
146404b540aSrobert 
147404b540aSrobert /* Identical to INTERESTING_SSA_EDGES.  For performance reasons, the
148404b540aSrobert    list of SSA edges is split into two.  One contains all SSA edges
149404b540aSrobert    who need to be reexamined because their lattice value changed to
150404b540aSrobert    varying (this worklist), and the other contains all other SSA edges
151404b540aSrobert    to be reexamined (INTERESTING_SSA_EDGES).
152404b540aSrobert 
153404b540aSrobert    Since most values in the program are VARYING, the ideal situation
154404b540aSrobert    is to move them to that lattice value as quickly as possible.
155404b540aSrobert    Thus, it doesn't make sense to process any other type of lattice
156404b540aSrobert    value until all VARYING values are propagated fully, which is one
157404b540aSrobert    thing using the VARYING worklist achieves.  In addition, if we
158404b540aSrobert    don't use a separate worklist for VARYING edges, we end up with
159404b540aSrobert    situations where lattice values move from
160404b540aSrobert    UNDEFINED->INTERESTING->VARYING instead of UNDEFINED->VARYING.  */
161404b540aSrobert static GTY(()) VEC(tree,gc) *varying_ssa_edges;
162404b540aSrobert 
163404b540aSrobert 
164404b540aSrobert /* Return true if the block worklist empty.  */
165404b540aSrobert 
166404b540aSrobert static inline bool
cfg_blocks_empty_p(void)167404b540aSrobert cfg_blocks_empty_p (void)
168404b540aSrobert {
169404b540aSrobert   return (cfg_blocks_num == 0);
170404b540aSrobert }
171404b540aSrobert 
172404b540aSrobert 
173404b540aSrobert /* Add a basic block to the worklist.  The block must not be already
174404b540aSrobert    in the worklist, and it must not be the ENTRY or EXIT block.  */
175404b540aSrobert 
176404b540aSrobert static void
cfg_blocks_add(basic_block bb)177404b540aSrobert cfg_blocks_add (basic_block bb)
178404b540aSrobert {
179404b540aSrobert   gcc_assert (bb != ENTRY_BLOCK_PTR && bb != EXIT_BLOCK_PTR);
180404b540aSrobert   gcc_assert (!TEST_BIT (bb_in_list, bb->index));
181404b540aSrobert 
182404b540aSrobert   if (cfg_blocks_empty_p ())
183404b540aSrobert     {
184404b540aSrobert       cfg_blocks_tail = cfg_blocks_head = 0;
185404b540aSrobert       cfg_blocks_num = 1;
186404b540aSrobert     }
187404b540aSrobert   else
188404b540aSrobert     {
189404b540aSrobert       cfg_blocks_num++;
190404b540aSrobert       if (cfg_blocks_num > VEC_length (basic_block, cfg_blocks))
191404b540aSrobert 	{
192404b540aSrobert 	  /* We have to grow the array now.  Adjust to queue to occupy
193404b540aSrobert 	     the full space of the original array.  We do not need to
194404b540aSrobert 	     initialize the newly allocated portion of the array
195404b540aSrobert 	     because we keep track of CFG_BLOCKS_HEAD and
196404b540aSrobert 	     CFG_BLOCKS_HEAD.  */
197404b540aSrobert 	  cfg_blocks_tail = VEC_length (basic_block, cfg_blocks);
198404b540aSrobert 	  cfg_blocks_head = 0;
199404b540aSrobert 	  VEC_safe_grow (basic_block, heap, cfg_blocks, 2 * cfg_blocks_tail);
200404b540aSrobert 	}
201404b540aSrobert       else
202404b540aSrobert 	cfg_blocks_tail = ((cfg_blocks_tail + 1)
203404b540aSrobert 			   % VEC_length (basic_block, cfg_blocks));
204404b540aSrobert     }
205404b540aSrobert 
206404b540aSrobert   VEC_replace (basic_block, cfg_blocks, cfg_blocks_tail, bb);
207404b540aSrobert   SET_BIT (bb_in_list, bb->index);
208404b540aSrobert }
209404b540aSrobert 
210404b540aSrobert 
211404b540aSrobert /* Remove a block from the worklist.  */
212404b540aSrobert 
213404b540aSrobert static basic_block
cfg_blocks_get(void)214404b540aSrobert cfg_blocks_get (void)
215404b540aSrobert {
216404b540aSrobert   basic_block bb;
217404b540aSrobert 
218404b540aSrobert   bb = VEC_index (basic_block, cfg_blocks, cfg_blocks_head);
219404b540aSrobert 
220404b540aSrobert   gcc_assert (!cfg_blocks_empty_p ());
221404b540aSrobert   gcc_assert (bb);
222404b540aSrobert 
223404b540aSrobert   cfg_blocks_head = ((cfg_blocks_head + 1)
224404b540aSrobert 		     % VEC_length (basic_block, cfg_blocks));
225404b540aSrobert   --cfg_blocks_num;
226404b540aSrobert   RESET_BIT (bb_in_list, bb->index);
227404b540aSrobert 
228404b540aSrobert   return bb;
229404b540aSrobert }
230404b540aSrobert 
231404b540aSrobert 
232404b540aSrobert /* We have just defined a new value for VAR.  If IS_VARYING is true,
233404b540aSrobert    add all immediate uses of VAR to VARYING_SSA_EDGES, otherwise add
234404b540aSrobert    them to INTERESTING_SSA_EDGES.  */
235404b540aSrobert 
236404b540aSrobert static void
add_ssa_edge(tree var,bool is_varying)237404b540aSrobert add_ssa_edge (tree var, bool is_varying)
238404b540aSrobert {
239404b540aSrobert   imm_use_iterator iter;
240404b540aSrobert   use_operand_p use_p;
241404b540aSrobert 
242404b540aSrobert   FOR_EACH_IMM_USE_FAST (use_p, iter, var)
243404b540aSrobert     {
244404b540aSrobert       tree use_stmt = USE_STMT (use_p);
245404b540aSrobert 
246404b540aSrobert       if (!DONT_SIMULATE_AGAIN (use_stmt)
247404b540aSrobert 	  && !STMT_IN_SSA_EDGE_WORKLIST (use_stmt))
248404b540aSrobert 	{
249404b540aSrobert 	  STMT_IN_SSA_EDGE_WORKLIST (use_stmt) = 1;
250404b540aSrobert 	  if (is_varying)
251404b540aSrobert 	    VEC_safe_push (tree, gc, varying_ssa_edges, use_stmt);
252404b540aSrobert 	  else
253404b540aSrobert 	    VEC_safe_push (tree, gc, interesting_ssa_edges, use_stmt);
254404b540aSrobert 	}
255404b540aSrobert     }
256404b540aSrobert }
257404b540aSrobert 
258404b540aSrobert 
259404b540aSrobert /* Add edge E to the control flow worklist.  */
260404b540aSrobert 
261404b540aSrobert static void
add_control_edge(edge e)262404b540aSrobert add_control_edge (edge e)
263404b540aSrobert {
264404b540aSrobert   basic_block bb = e->dest;
265404b540aSrobert   if (bb == EXIT_BLOCK_PTR)
266404b540aSrobert     return;
267404b540aSrobert 
268404b540aSrobert   /* If the edge had already been executed, skip it.  */
269404b540aSrobert   if (e->flags & EDGE_EXECUTABLE)
270404b540aSrobert     return;
271404b540aSrobert 
272404b540aSrobert   e->flags |= EDGE_EXECUTABLE;
273404b540aSrobert 
274404b540aSrobert   /* If the block is already in the list, we're done.  */
275404b540aSrobert   if (TEST_BIT (bb_in_list, bb->index))
276404b540aSrobert     return;
277404b540aSrobert 
278404b540aSrobert   cfg_blocks_add (bb);
279404b540aSrobert 
280404b540aSrobert   if (dump_file && (dump_flags & TDF_DETAILS))
281404b540aSrobert     fprintf (dump_file, "Adding Destination of edge (%d -> %d) to worklist\n\n",
282404b540aSrobert 	e->src->index, e->dest->index);
283404b540aSrobert }
284404b540aSrobert 
285404b540aSrobert 
286404b540aSrobert /* Simulate the execution of STMT and update the work lists accordingly.  */
287404b540aSrobert 
288404b540aSrobert static void
simulate_stmt(tree stmt)289404b540aSrobert simulate_stmt (tree stmt)
290404b540aSrobert {
291404b540aSrobert   enum ssa_prop_result val = SSA_PROP_NOT_INTERESTING;
292404b540aSrobert   edge taken_edge = NULL;
293404b540aSrobert   tree output_name = NULL_TREE;
294404b540aSrobert 
295404b540aSrobert   /* Don't bother visiting statements that are already
296404b540aSrobert      considered varying by the propagator.  */
297404b540aSrobert   if (DONT_SIMULATE_AGAIN (stmt))
298404b540aSrobert     return;
299404b540aSrobert 
300404b540aSrobert   if (TREE_CODE (stmt) == PHI_NODE)
301404b540aSrobert     {
302404b540aSrobert       val = ssa_prop_visit_phi (stmt);
303404b540aSrobert       output_name = PHI_RESULT (stmt);
304404b540aSrobert     }
305404b540aSrobert   else
306404b540aSrobert     val = ssa_prop_visit_stmt (stmt, &taken_edge, &output_name);
307404b540aSrobert 
308404b540aSrobert   if (val == SSA_PROP_VARYING)
309404b540aSrobert     {
310404b540aSrobert       DONT_SIMULATE_AGAIN (stmt) = 1;
311404b540aSrobert 
312404b540aSrobert       /* If the statement produced a new varying value, add the SSA
313404b540aSrobert 	 edges coming out of OUTPUT_NAME.  */
314404b540aSrobert       if (output_name)
315404b540aSrobert 	add_ssa_edge (output_name, true);
316404b540aSrobert 
317404b540aSrobert       /* If STMT transfers control out of its basic block, add
318404b540aSrobert 	 all outgoing edges to the work list.  */
319404b540aSrobert       if (stmt_ends_bb_p (stmt))
320404b540aSrobert 	{
321404b540aSrobert 	  edge e;
322404b540aSrobert 	  edge_iterator ei;
323404b540aSrobert 	  basic_block bb = bb_for_stmt (stmt);
324404b540aSrobert 	  FOR_EACH_EDGE (e, ei, bb->succs)
325404b540aSrobert 	    add_control_edge (e);
326404b540aSrobert 	}
327404b540aSrobert     }
328404b540aSrobert   else if (val == SSA_PROP_INTERESTING)
329404b540aSrobert     {
330404b540aSrobert       /* If the statement produced new value, add the SSA edges coming
331404b540aSrobert 	 out of OUTPUT_NAME.  */
332404b540aSrobert       if (output_name)
333404b540aSrobert 	add_ssa_edge (output_name, false);
334404b540aSrobert 
335404b540aSrobert       /* If we know which edge is going to be taken out of this block,
336404b540aSrobert 	 add it to the CFG work list.  */
337404b540aSrobert       if (taken_edge)
338404b540aSrobert 	add_control_edge (taken_edge);
339404b540aSrobert     }
340404b540aSrobert }
341404b540aSrobert 
342404b540aSrobert /* Process an SSA edge worklist.  WORKLIST is the SSA edge worklist to
343404b540aSrobert    drain.  This pops statements off the given WORKLIST and processes
344404b540aSrobert    them until there are no more statements on WORKLIST.
345404b540aSrobert    We take a pointer to WORKLIST because it may be reallocated when an
346404b540aSrobert    SSA edge is added to it in simulate_stmt.  */
347404b540aSrobert 
348404b540aSrobert static void
process_ssa_edge_worklist(VEC (tree,gc)** worklist)349404b540aSrobert process_ssa_edge_worklist (VEC(tree,gc) **worklist)
350404b540aSrobert {
351404b540aSrobert   /* Drain the entire worklist.  */
352404b540aSrobert   while (VEC_length (tree, *worklist) > 0)
353404b540aSrobert     {
354404b540aSrobert       basic_block bb;
355404b540aSrobert 
356404b540aSrobert       /* Pull the statement to simulate off the worklist.  */
357404b540aSrobert       tree stmt = VEC_pop (tree, *worklist);
358404b540aSrobert 
359404b540aSrobert       /* If this statement was already visited by simulate_block, then
360404b540aSrobert 	 we don't need to visit it again here.  */
361404b540aSrobert       if (!STMT_IN_SSA_EDGE_WORKLIST (stmt))
362404b540aSrobert 	continue;
363404b540aSrobert 
364404b540aSrobert       /* STMT is no longer in a worklist.  */
365404b540aSrobert       STMT_IN_SSA_EDGE_WORKLIST (stmt) = 0;
366404b540aSrobert 
367404b540aSrobert       if (dump_file && (dump_flags & TDF_DETAILS))
368404b540aSrobert 	{
369404b540aSrobert 	  fprintf (dump_file, "\nSimulating statement (from ssa_edges): ");
370404b540aSrobert 	  print_generic_stmt (dump_file, stmt, dump_flags);
371404b540aSrobert 	}
372404b540aSrobert 
373404b540aSrobert       bb = bb_for_stmt (stmt);
374404b540aSrobert 
375404b540aSrobert       /* PHI nodes are always visited, regardless of whether or not
376404b540aSrobert 	 the destination block is executable.  Otherwise, visit the
377404b540aSrobert 	 statement only if its block is marked executable.  */
378404b540aSrobert       if (TREE_CODE (stmt) == PHI_NODE
379404b540aSrobert 	  || TEST_BIT (executable_blocks, bb->index))
380404b540aSrobert 	simulate_stmt (stmt);
381404b540aSrobert     }
382404b540aSrobert }
383404b540aSrobert 
384404b540aSrobert 
385404b540aSrobert /* Simulate the execution of BLOCK.  Evaluate the statement associated
386404b540aSrobert    with each variable reference inside the block.  */
387404b540aSrobert 
388404b540aSrobert static void
simulate_block(basic_block block)389404b540aSrobert simulate_block (basic_block block)
390404b540aSrobert {
391404b540aSrobert   tree phi;
392404b540aSrobert 
393404b540aSrobert   /* There is nothing to do for the exit block.  */
394404b540aSrobert   if (block == EXIT_BLOCK_PTR)
395404b540aSrobert     return;
396404b540aSrobert 
397404b540aSrobert   if (dump_file && (dump_flags & TDF_DETAILS))
398404b540aSrobert     fprintf (dump_file, "\nSimulating block %d\n", block->index);
399404b540aSrobert 
400404b540aSrobert   /* Always simulate PHI nodes, even if we have simulated this block
401404b540aSrobert      before.  */
402404b540aSrobert   for (phi = phi_nodes (block); phi; phi = PHI_CHAIN (phi))
403404b540aSrobert     simulate_stmt (phi);
404404b540aSrobert 
405404b540aSrobert   /* If this is the first time we've simulated this block, then we
406404b540aSrobert      must simulate each of its statements.  */
407404b540aSrobert   if (!TEST_BIT (executable_blocks, block->index))
408404b540aSrobert     {
409404b540aSrobert       block_stmt_iterator j;
410404b540aSrobert       unsigned int normal_edge_count;
411404b540aSrobert       edge e, normal_edge;
412404b540aSrobert       edge_iterator ei;
413404b540aSrobert 
414404b540aSrobert       /* Note that we have simulated this block.  */
415404b540aSrobert       SET_BIT (executable_blocks, block->index);
416404b540aSrobert 
417404b540aSrobert       for (j = bsi_start (block); !bsi_end_p (j); bsi_next (&j))
418404b540aSrobert 	{
419404b540aSrobert 	  tree stmt = bsi_stmt (j);
420404b540aSrobert 
421404b540aSrobert 	  /* If this statement is already in the worklist then
422404b540aSrobert 	     "cancel" it.  The reevaluation implied by the worklist
423404b540aSrobert 	     entry will produce the same value we generate here and
424404b540aSrobert 	     thus reevaluating it again from the worklist is
425404b540aSrobert 	     pointless.  */
426404b540aSrobert 	  if (STMT_IN_SSA_EDGE_WORKLIST (stmt))
427404b540aSrobert 	    STMT_IN_SSA_EDGE_WORKLIST (stmt) = 0;
428404b540aSrobert 
429404b540aSrobert 	  simulate_stmt (stmt);
430404b540aSrobert 	}
431404b540aSrobert 
432404b540aSrobert       /* We can not predict when abnormal edges will be executed, so
433404b540aSrobert 	 once a block is considered executable, we consider any
434404b540aSrobert 	 outgoing abnormal edges as executable.
435404b540aSrobert 
436404b540aSrobert 	 At the same time, if this block has only one successor that is
437404b540aSrobert 	 reached by non-abnormal edges, then add that successor to the
438404b540aSrobert 	 worklist.  */
439404b540aSrobert       normal_edge_count = 0;
440404b540aSrobert       normal_edge = NULL;
441404b540aSrobert       FOR_EACH_EDGE (e, ei, block->succs)
442404b540aSrobert 	{
443404b540aSrobert 	  if (e->flags & EDGE_ABNORMAL)
444404b540aSrobert 	    add_control_edge (e);
445404b540aSrobert 	  else
446404b540aSrobert 	    {
447404b540aSrobert 	      normal_edge_count++;
448404b540aSrobert 	      normal_edge = e;
449404b540aSrobert 	    }
450404b540aSrobert 	}
451404b540aSrobert 
452404b540aSrobert       if (normal_edge_count == 1)
453404b540aSrobert 	add_control_edge (normal_edge);
454404b540aSrobert     }
455404b540aSrobert }
456404b540aSrobert 
457404b540aSrobert 
458404b540aSrobert /* Initialize local data structures and work lists.  */
459404b540aSrobert 
460404b540aSrobert static void
ssa_prop_init(void)461404b540aSrobert ssa_prop_init (void)
462404b540aSrobert {
463404b540aSrobert   edge e;
464404b540aSrobert   edge_iterator ei;
465404b540aSrobert   basic_block bb;
466404b540aSrobert   size_t i;
467404b540aSrobert 
468404b540aSrobert   /* Worklists of SSA edges.  */
469404b540aSrobert   interesting_ssa_edges = VEC_alloc (tree, gc, 20);
470404b540aSrobert   varying_ssa_edges = VEC_alloc (tree, gc, 20);
471404b540aSrobert 
472404b540aSrobert   executable_blocks = sbitmap_alloc (last_basic_block);
473404b540aSrobert   sbitmap_zero (executable_blocks);
474404b540aSrobert 
475404b540aSrobert   bb_in_list = sbitmap_alloc (last_basic_block);
476404b540aSrobert   sbitmap_zero (bb_in_list);
477404b540aSrobert 
478404b540aSrobert   if (dump_file && (dump_flags & TDF_DETAILS))
479404b540aSrobert     dump_immediate_uses (dump_file);
480404b540aSrobert 
481404b540aSrobert   cfg_blocks = VEC_alloc (basic_block, heap, 20);
482404b540aSrobert   VEC_safe_grow (basic_block, heap, cfg_blocks, 20);
483404b540aSrobert 
484404b540aSrobert   /* Initialize the values for every SSA_NAME.  */
485404b540aSrobert   for (i = 1; i < num_ssa_names; i++)
486404b540aSrobert     if (ssa_name (i))
487404b540aSrobert       SSA_NAME_VALUE (ssa_name (i)) = NULL_TREE;
488404b540aSrobert 
489404b540aSrobert   /* Initially assume that every edge in the CFG is not executable.
490404b540aSrobert      (including the edges coming out of ENTRY_BLOCK_PTR).  */
491404b540aSrobert   FOR_ALL_BB (bb)
492404b540aSrobert     {
493404b540aSrobert       block_stmt_iterator si;
494404b540aSrobert 
495404b540aSrobert       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
496404b540aSrobert 	STMT_IN_SSA_EDGE_WORKLIST (bsi_stmt (si)) = 0;
497404b540aSrobert 
498404b540aSrobert       FOR_EACH_EDGE (e, ei, bb->succs)
499404b540aSrobert 	e->flags &= ~EDGE_EXECUTABLE;
500404b540aSrobert     }
501404b540aSrobert 
502404b540aSrobert   /* Seed the algorithm by adding the successors of the entry block to the
503404b540aSrobert      edge worklist.  */
504404b540aSrobert   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
505404b540aSrobert     add_control_edge (e);
506404b540aSrobert }
507404b540aSrobert 
508404b540aSrobert 
509404b540aSrobert /* Free allocated storage.  */
510404b540aSrobert 
511404b540aSrobert static void
ssa_prop_fini(void)512404b540aSrobert ssa_prop_fini (void)
513404b540aSrobert {
514404b540aSrobert   VEC_free (tree, gc, interesting_ssa_edges);
515404b540aSrobert   VEC_free (tree, gc, varying_ssa_edges);
516404b540aSrobert   VEC_free (basic_block, heap, cfg_blocks);
517404b540aSrobert   cfg_blocks = NULL;
518404b540aSrobert   sbitmap_free (bb_in_list);
519404b540aSrobert   sbitmap_free (executable_blocks);
520404b540aSrobert }
521404b540aSrobert 
522404b540aSrobert 
523404b540aSrobert /* Get the main expression from statement STMT.  */
524404b540aSrobert 
525404b540aSrobert tree
get_rhs(tree stmt)526404b540aSrobert get_rhs (tree stmt)
527404b540aSrobert {
528404b540aSrobert   enum tree_code code = TREE_CODE (stmt);
529404b540aSrobert 
530404b540aSrobert   switch (code)
531404b540aSrobert     {
532404b540aSrobert     case RETURN_EXPR:
533404b540aSrobert       stmt = TREE_OPERAND (stmt, 0);
534404b540aSrobert       if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
535404b540aSrobert 	return stmt;
536404b540aSrobert       /* FALLTHRU */
537404b540aSrobert 
538404b540aSrobert     case MODIFY_EXPR:
539404b540aSrobert       stmt = TREE_OPERAND (stmt, 1);
540404b540aSrobert       if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
541404b540aSrobert 	return TREE_OPERAND (stmt, 0);
542404b540aSrobert       else
543404b540aSrobert 	return stmt;
544404b540aSrobert 
545404b540aSrobert     case COND_EXPR:
546404b540aSrobert       return COND_EXPR_COND (stmt);
547404b540aSrobert     case SWITCH_EXPR:
548404b540aSrobert       return SWITCH_COND (stmt);
549404b540aSrobert     case GOTO_EXPR:
550404b540aSrobert       return GOTO_DESTINATION (stmt);
551404b540aSrobert     case LABEL_EXPR:
552404b540aSrobert       return LABEL_EXPR_LABEL (stmt);
553404b540aSrobert 
554404b540aSrobert     default:
555404b540aSrobert       return stmt;
556404b540aSrobert     }
557404b540aSrobert }
558404b540aSrobert 
559404b540aSrobert 
560404b540aSrobert /* Set the main expression of *STMT_P to EXPR.  If EXPR is not a valid
561404b540aSrobert    GIMPLE expression no changes are done and the function returns
562404b540aSrobert    false.  */
563404b540aSrobert 
564404b540aSrobert bool
set_rhs(tree * stmt_p,tree expr)565404b540aSrobert set_rhs (tree *stmt_p, tree expr)
566404b540aSrobert {
567404b540aSrobert   tree stmt = *stmt_p, op;
568404b540aSrobert   enum tree_code code = TREE_CODE (expr);
569404b540aSrobert   stmt_ann_t ann;
570404b540aSrobert   tree var;
571404b540aSrobert   ssa_op_iter iter;
572404b540aSrobert 
573404b540aSrobert   /* Verify the constant folded result is valid gimple.  */
574*ad47ef84Sdcoppa   switch (TREE_CODE_CLASS (code))
575404b540aSrobert     {
576*ad47ef84Sdcoppa     case tcc_declaration:
577*ad47ef84Sdcoppa       if (!is_gimple_variable(expr))
578*ad47ef84Sdcoppa  	return false;
579*ad47ef84Sdcoppa       break;
580*ad47ef84Sdcoppa 
581*ad47ef84Sdcoppa     case tcc_constant:
582*ad47ef84Sdcoppa       break;
583*ad47ef84Sdcoppa 
584*ad47ef84Sdcoppa     case tcc_binary:
585*ad47ef84Sdcoppa     case tcc_comparison:
586404b540aSrobert       if (!is_gimple_val (TREE_OPERAND (expr, 0))
587404b540aSrobert 	  || !is_gimple_val (TREE_OPERAND (expr, 1)))
588404b540aSrobert 	return false;
589*ad47ef84Sdcoppa       break;
590*ad47ef84Sdcoppa 
591*ad47ef84Sdcoppa     case tcc_unary:
592404b540aSrobert       if (!is_gimple_val (TREE_OPERAND (expr, 0)))
593404b540aSrobert 	return false;
594*ad47ef84Sdcoppa       break;
595*ad47ef84Sdcoppa     case tcc_expression:
596*ad47ef84Sdcoppa       switch (code)
597404b540aSrobert 	{
598*ad47ef84Sdcoppa 	case ADDR_EXPR:
599404b540aSrobert           if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF
600404b540aSrobert 	      && !is_gimple_val (TREE_OPERAND (TREE_OPERAND (expr, 0), 1)))
601404b540aSrobert 	    return false;
602*ad47ef84Sdcoppa 	  break;
603*ad47ef84Sdcoppa 
604*ad47ef84Sdcoppa 	case TRUTH_NOT_EXPR:
605*ad47ef84Sdcoppa 	  if (!is_gimple_val (TREE_OPERAND (expr, 0)))
606404b540aSrobert 	    return false;
607*ad47ef84Sdcoppa 	  break;
608*ad47ef84Sdcoppa 
609*ad47ef84Sdcoppa 	case TRUTH_AND_EXPR:
610*ad47ef84Sdcoppa 	case TRUTH_XOR_EXPR:
611*ad47ef84Sdcoppa 	case TRUTH_OR_EXPR:
612*ad47ef84Sdcoppa 	  if (!is_gimple_val (TREE_OPERAND (expr, 0))
613*ad47ef84Sdcoppa 	      || !is_gimple_val (TREE_OPERAND (expr, 1)))
614*ad47ef84Sdcoppa 	    return false;
615*ad47ef84Sdcoppa 	  break;
616*ad47ef84Sdcoppa 
617*ad47ef84Sdcoppa 	case CALL_EXPR:
618*ad47ef84Sdcoppa 	case EXC_PTR_EXPR:
619*ad47ef84Sdcoppa 	case FILTER_EXPR:
620*ad47ef84Sdcoppa 	  break;
621*ad47ef84Sdcoppa 
622*ad47ef84Sdcoppa 	default:
623*ad47ef84Sdcoppa 	  return false;
624*ad47ef84Sdcoppa 	}
625*ad47ef84Sdcoppa       break;
626*ad47ef84Sdcoppa 
627*ad47ef84Sdcoppa     case tcc_exceptional:
628*ad47ef84Sdcoppa       switch (code)
629*ad47ef84Sdcoppa 	{
630*ad47ef84Sdcoppa 	case SSA_NAME:
631*ad47ef84Sdcoppa 	  break;
632*ad47ef84Sdcoppa 
633*ad47ef84Sdcoppa 	default:
634*ad47ef84Sdcoppa 	  return false;
635*ad47ef84Sdcoppa 	}
636*ad47ef84Sdcoppa       break;
637*ad47ef84Sdcoppa 
638*ad47ef84Sdcoppa     default:
639*ad47ef84Sdcoppa       return false;
640*ad47ef84Sdcoppa     }
641404b540aSrobert 
642404b540aSrobert   if (EXPR_HAS_LOCATION (stmt)
643404b540aSrobert       && EXPR_P (expr)
644404b540aSrobert       && ! EXPR_HAS_LOCATION (expr)
645404b540aSrobert       && TREE_SIDE_EFFECTS (expr)
646404b540aSrobert       && TREE_CODE (expr) != LABEL_EXPR)
647404b540aSrobert     SET_EXPR_LOCATION (expr, EXPR_LOCATION (stmt));
648404b540aSrobert 
649404b540aSrobert   switch (TREE_CODE (stmt))
650404b540aSrobert     {
651404b540aSrobert     case RETURN_EXPR:
652404b540aSrobert       op = TREE_OPERAND (stmt, 0);
653404b540aSrobert       if (TREE_CODE (op) != MODIFY_EXPR)
654404b540aSrobert 	{
655404b540aSrobert 	  TREE_OPERAND (stmt, 0) = expr;
656404b540aSrobert 	  break;
657404b540aSrobert 	}
658404b540aSrobert       stmt = op;
659404b540aSrobert       /* FALLTHRU */
660404b540aSrobert 
661404b540aSrobert     case MODIFY_EXPR:
662404b540aSrobert       op = TREE_OPERAND (stmt, 1);
663404b540aSrobert       if (TREE_CODE (op) == WITH_SIZE_EXPR)
664404b540aSrobert 	stmt = op;
665404b540aSrobert       TREE_OPERAND (stmt, 1) = expr;
666404b540aSrobert       break;
667404b540aSrobert 
668404b540aSrobert     case COND_EXPR:
669404b540aSrobert       if (!is_gimple_condexpr (expr))
670404b540aSrobert         return false;
671404b540aSrobert       COND_EXPR_COND (stmt) = expr;
672404b540aSrobert       break;
673404b540aSrobert     case SWITCH_EXPR:
674404b540aSrobert       SWITCH_COND (stmt) = expr;
675404b540aSrobert       break;
676404b540aSrobert     case GOTO_EXPR:
677404b540aSrobert       GOTO_DESTINATION (stmt) = expr;
678404b540aSrobert       break;
679404b540aSrobert     case LABEL_EXPR:
680404b540aSrobert       LABEL_EXPR_LABEL (stmt) = expr;
681404b540aSrobert       break;
682404b540aSrobert 
683404b540aSrobert     default:
684404b540aSrobert       /* Replace the whole statement with EXPR.  If EXPR has no side
685404b540aSrobert 	 effects, then replace *STMT_P with an empty statement.  */
686404b540aSrobert       ann = stmt_ann (stmt);
687404b540aSrobert       *stmt_p = TREE_SIDE_EFFECTS (expr) ? expr : build_empty_stmt ();
688404b540aSrobert       (*stmt_p)->common.ann = (tree_ann_t) ann;
689404b540aSrobert 
690404b540aSrobert       if (in_ssa_p
691404b540aSrobert 	  && TREE_SIDE_EFFECTS (expr))
692404b540aSrobert 	{
693404b540aSrobert 	  /* Fix all the SSA_NAMEs created by *STMT_P to point to its new
694404b540aSrobert 	     replacement.  */
695404b540aSrobert 	  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_DEFS)
696404b540aSrobert 	    {
697404b540aSrobert 	      if (TREE_CODE (var) == SSA_NAME)
698404b540aSrobert 		SSA_NAME_DEF_STMT (var) = *stmt_p;
699404b540aSrobert 	    }
700404b540aSrobert 	}
701404b540aSrobert       break;
702404b540aSrobert     }
703404b540aSrobert 
704404b540aSrobert   return true;
705404b540aSrobert }
706404b540aSrobert 
707404b540aSrobert 
708404b540aSrobert /* Entry point to the propagation engine.
709404b540aSrobert 
710404b540aSrobert    VISIT_STMT is called for every statement visited.
711404b540aSrobert    VISIT_PHI is called for every PHI node visited.  */
712404b540aSrobert 
713404b540aSrobert void
ssa_propagate(ssa_prop_visit_stmt_fn visit_stmt,ssa_prop_visit_phi_fn visit_phi)714404b540aSrobert ssa_propagate (ssa_prop_visit_stmt_fn visit_stmt,
715404b540aSrobert 	       ssa_prop_visit_phi_fn visit_phi)
716404b540aSrobert {
717404b540aSrobert   ssa_prop_visit_stmt = visit_stmt;
718404b540aSrobert   ssa_prop_visit_phi = visit_phi;
719404b540aSrobert 
720404b540aSrobert   ssa_prop_init ();
721404b540aSrobert 
722404b540aSrobert   /* Iterate until the worklists are empty.  */
723404b540aSrobert   while (!cfg_blocks_empty_p ()
724404b540aSrobert 	 || VEC_length (tree, interesting_ssa_edges) > 0
725404b540aSrobert 	 || VEC_length (tree, varying_ssa_edges) > 0)
726404b540aSrobert     {
727404b540aSrobert       if (!cfg_blocks_empty_p ())
728404b540aSrobert 	{
729404b540aSrobert 	  /* Pull the next block to simulate off the worklist.  */
730404b540aSrobert 	  basic_block dest_block = cfg_blocks_get ();
731404b540aSrobert 	  simulate_block (dest_block);
732404b540aSrobert 	}
733404b540aSrobert 
734404b540aSrobert       /* In order to move things to varying as quickly as
735404b540aSrobert 	 possible,process the VARYING_SSA_EDGES worklist first.  */
736404b540aSrobert       process_ssa_edge_worklist (&varying_ssa_edges);
737404b540aSrobert 
738404b540aSrobert       /* Now process the INTERESTING_SSA_EDGES worklist.  */
739404b540aSrobert       process_ssa_edge_worklist (&interesting_ssa_edges);
740404b540aSrobert     }
741404b540aSrobert 
742404b540aSrobert   ssa_prop_fini ();
743404b540aSrobert }
744404b540aSrobert 
745404b540aSrobert 
746404b540aSrobert /* Return the first V_MAY_DEF or V_MUST_DEF operand for STMT.  */
747404b540aSrobert 
748404b540aSrobert tree
first_vdef(tree stmt)749404b540aSrobert first_vdef (tree stmt)
750404b540aSrobert {
751404b540aSrobert   ssa_op_iter iter;
752404b540aSrobert   tree op;
753404b540aSrobert 
754404b540aSrobert   /* Simply return the first operand we arrive at.  */
755404b540aSrobert   FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_DEFS)
756404b540aSrobert     return (op);
757404b540aSrobert 
758404b540aSrobert   gcc_unreachable ();
759404b540aSrobert }
760404b540aSrobert 
761404b540aSrobert 
762404b540aSrobert /* Return true if STMT is of the form 'LHS = mem_ref', where 'mem_ref'
763404b540aSrobert    is a non-volatile pointer dereference, a structure reference or a
764404b540aSrobert    reference to a single _DECL.  Ignore volatile memory references
765404b540aSrobert    because they are not interesting for the optimizers.  */
766404b540aSrobert 
767404b540aSrobert bool
stmt_makes_single_load(tree stmt)768404b540aSrobert stmt_makes_single_load (tree stmt)
769404b540aSrobert {
770404b540aSrobert   tree rhs;
771404b540aSrobert 
772404b540aSrobert   if (TREE_CODE (stmt) != MODIFY_EXPR)
773404b540aSrobert     return false;
774404b540aSrobert 
775404b540aSrobert   if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF|SSA_OP_VUSE))
776404b540aSrobert     return false;
777404b540aSrobert 
778404b540aSrobert   rhs = TREE_OPERAND (stmt, 1);
779404b540aSrobert   STRIP_NOPS (rhs);
780404b540aSrobert 
781404b540aSrobert   return (!TREE_THIS_VOLATILE (rhs)
782404b540aSrobert 	  && (DECL_P (rhs)
783404b540aSrobert 	      || REFERENCE_CLASS_P (rhs)));
784404b540aSrobert }
785404b540aSrobert 
786404b540aSrobert 
787404b540aSrobert /* Return true if STMT is of the form 'mem_ref = RHS', where 'mem_ref'
788404b540aSrobert    is a non-volatile pointer dereference, a structure reference or a
789404b540aSrobert    reference to a single _DECL.  Ignore volatile memory references
790404b540aSrobert    because they are not interesting for the optimizers.  */
791404b540aSrobert 
792404b540aSrobert bool
stmt_makes_single_store(tree stmt)793404b540aSrobert stmt_makes_single_store (tree stmt)
794404b540aSrobert {
795404b540aSrobert   tree lhs;
796404b540aSrobert 
797404b540aSrobert   if (TREE_CODE (stmt) != MODIFY_EXPR)
798404b540aSrobert     return false;
799404b540aSrobert 
800404b540aSrobert   if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF|SSA_OP_VMUSTDEF))
801404b540aSrobert     return false;
802404b540aSrobert 
803404b540aSrobert   lhs = TREE_OPERAND (stmt, 0);
804404b540aSrobert   STRIP_NOPS (lhs);
805404b540aSrobert 
806404b540aSrobert   return (!TREE_THIS_VOLATILE (lhs)
807404b540aSrobert           && (DECL_P (lhs)
808404b540aSrobert 	      || REFERENCE_CLASS_P (lhs)));
809404b540aSrobert }
810404b540aSrobert 
811404b540aSrobert 
812404b540aSrobert /* If STMT makes a single memory load and all the virtual use operands
813404b540aSrobert    have the same value in array VALUES, return it.  Otherwise, return
814404b540aSrobert    NULL.  */
815404b540aSrobert 
816404b540aSrobert prop_value_t *
get_value_loaded_by(tree stmt,prop_value_t * values)817404b540aSrobert get_value_loaded_by (tree stmt, prop_value_t *values)
818404b540aSrobert {
819404b540aSrobert   ssa_op_iter i;
820404b540aSrobert   tree vuse;
821404b540aSrobert   prop_value_t *prev_val = NULL;
822404b540aSrobert   prop_value_t *val = NULL;
823404b540aSrobert 
824404b540aSrobert   FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, i, SSA_OP_VIRTUAL_USES)
825404b540aSrobert     {
826404b540aSrobert       val = &values[SSA_NAME_VERSION (vuse)];
827404b540aSrobert       if (prev_val && prev_val->value != val->value)
828404b540aSrobert 	return NULL;
829404b540aSrobert       prev_val = val;
830404b540aSrobert     }
831404b540aSrobert 
832404b540aSrobert   return val;
833404b540aSrobert }
834404b540aSrobert 
835404b540aSrobert 
836404b540aSrobert /* Propagation statistics.  */
837404b540aSrobert struct prop_stats_d
838404b540aSrobert {
839404b540aSrobert   long num_const_prop;
840404b540aSrobert   long num_copy_prop;
841404b540aSrobert   long num_pred_folded;
842404b540aSrobert };
843404b540aSrobert 
844404b540aSrobert static struct prop_stats_d prop_stats;
845404b540aSrobert 
846404b540aSrobert /* Replace USE references in statement STMT with the values stored in
847404b540aSrobert    PROP_VALUE. Return true if at least one reference was replaced.  If
848404b540aSrobert    REPLACED_ADDRESSES_P is given, it will be set to true if an address
849404b540aSrobert    constant was replaced.  */
850404b540aSrobert 
851404b540aSrobert bool
replace_uses_in(tree stmt,bool * replaced_addresses_p,prop_value_t * prop_value)852404b540aSrobert replace_uses_in (tree stmt, bool *replaced_addresses_p,
853404b540aSrobert 		 prop_value_t *prop_value)
854404b540aSrobert {
855404b540aSrobert   bool replaced = false;
856404b540aSrobert   use_operand_p use;
857404b540aSrobert   ssa_op_iter iter;
858404b540aSrobert 
859404b540aSrobert   FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
860404b540aSrobert     {
861404b540aSrobert       tree tuse = USE_FROM_PTR (use);
862404b540aSrobert       tree val = prop_value[SSA_NAME_VERSION (tuse)].value;
863404b540aSrobert 
864404b540aSrobert       if (val == tuse || val == NULL_TREE)
865404b540aSrobert 	continue;
866404b540aSrobert 
867404b540aSrobert       if (TREE_CODE (stmt) == ASM_EXPR
868404b540aSrobert 	  && !may_propagate_copy_into_asm (tuse))
869404b540aSrobert 	continue;
870404b540aSrobert 
871404b540aSrobert       if (!may_propagate_copy (tuse, val))
872404b540aSrobert 	continue;
873404b540aSrobert 
874404b540aSrobert       if (TREE_CODE (val) != SSA_NAME)
875404b540aSrobert 	prop_stats.num_const_prop++;
876404b540aSrobert       else
877404b540aSrobert 	prop_stats.num_copy_prop++;
878404b540aSrobert 
879404b540aSrobert       propagate_value (use, val);
880404b540aSrobert 
881404b540aSrobert       replaced = true;
882404b540aSrobert       if (POINTER_TYPE_P (TREE_TYPE (tuse)) && replaced_addresses_p)
883404b540aSrobert 	*replaced_addresses_p = true;
884404b540aSrobert     }
885404b540aSrobert 
886404b540aSrobert   return replaced;
887404b540aSrobert }
888404b540aSrobert 
889404b540aSrobert 
890404b540aSrobert /* Replace the VUSE references in statement STMT with the values
891404b540aSrobert    stored in PROP_VALUE.  Return true if a reference was replaced.  If
892404b540aSrobert    REPLACED_ADDRESSES_P is given, it will be set to true if an address
893404b540aSrobert    constant was replaced.
894404b540aSrobert 
895404b540aSrobert    Replacing VUSE operands is slightly more complex than replacing
896404b540aSrobert    regular USEs.  We are only interested in two types of replacements
897404b540aSrobert    here:
898404b540aSrobert 
899404b540aSrobert    1- If the value to be replaced is a constant or an SSA name for a
900404b540aSrobert       GIMPLE register, then we are making a copy/constant propagation
901404b540aSrobert       from a memory store.  For instance,
902404b540aSrobert 
903404b540aSrobert       	# a_3 = V_MAY_DEF <a_2>
904404b540aSrobert 	a.b = x_1;
905404b540aSrobert 	...
906404b540aSrobert  	# VUSE <a_3>
907404b540aSrobert 	y_4 = a.b;
908404b540aSrobert 
909404b540aSrobert       This replacement is only possible iff STMT is an assignment
910404b540aSrobert       whose RHS is identical to the LHS of the statement that created
911404b540aSrobert       the VUSE(s) that we are replacing.  Otherwise, we may do the
912404b540aSrobert       wrong replacement:
913404b540aSrobert 
914404b540aSrobert       	# a_3 = V_MAY_DEF <a_2>
915404b540aSrobert 	# b_5 = V_MAY_DEF <b_4>
916404b540aSrobert 	*p = 10;
917404b540aSrobert 	...
918404b540aSrobert 	# VUSE <b_5>
919404b540aSrobert 	x_8 = b;
920404b540aSrobert 
921404b540aSrobert       Even though 'b_5' acquires the value '10' during propagation,
922404b540aSrobert       there is no way for the propagator to tell whether the
923404b540aSrobert       replacement is correct in every reached use, because values are
924404b540aSrobert       computed at definition sites.  Therefore, when doing final
925404b540aSrobert       substitution of propagated values, we have to check each use
926404b540aSrobert       site.  Since the RHS of STMT ('b') is different from the LHS of
927404b540aSrobert       the originating statement ('*p'), we cannot replace 'b' with
928404b540aSrobert       '10'.
929404b540aSrobert 
930404b540aSrobert       Similarly, when merging values from PHI node arguments,
931404b540aSrobert       propagators need to take care not to merge the same values
932404b540aSrobert       stored in different locations:
933404b540aSrobert 
934404b540aSrobert      		if (...)
935404b540aSrobert 		  # a_3 = V_MAY_DEF <a_2>
936404b540aSrobert 		  a.b = 3;
937404b540aSrobert 		else
938404b540aSrobert 		  # a_4 = V_MAY_DEF <a_2>
939404b540aSrobert 		  a.c = 3;
940404b540aSrobert 		# a_5 = PHI <a_3, a_4>
941404b540aSrobert 
942404b540aSrobert       It would be wrong to propagate '3' into 'a_5' because that
943404b540aSrobert       operation merges two stores to different memory locations.
944404b540aSrobert 
945404b540aSrobert 
946404b540aSrobert    2- If the value to be replaced is an SSA name for a virtual
947404b540aSrobert       register, then we simply replace each VUSE operand with its
948404b540aSrobert       value from PROP_VALUE.  This is the same replacement done by
949404b540aSrobert       replace_uses_in.  */
950404b540aSrobert 
951404b540aSrobert static bool
replace_vuses_in(tree stmt,bool * replaced_addresses_p,prop_value_t * prop_value)952404b540aSrobert replace_vuses_in (tree stmt, bool *replaced_addresses_p,
953404b540aSrobert                   prop_value_t *prop_value)
954404b540aSrobert {
955404b540aSrobert   bool replaced = false;
956404b540aSrobert   ssa_op_iter iter;
957404b540aSrobert   use_operand_p vuse;
958404b540aSrobert 
959404b540aSrobert   if (stmt_makes_single_load (stmt))
960404b540aSrobert     {
961404b540aSrobert       /* If STMT is an assignment whose RHS is a single memory load,
962404b540aSrobert 	 see if we are trying to propagate a constant or a GIMPLE
963404b540aSrobert 	 register (case #1 above).  */
964404b540aSrobert       prop_value_t *val = get_value_loaded_by (stmt, prop_value);
965404b540aSrobert       tree rhs = TREE_OPERAND (stmt, 1);
966404b540aSrobert 
967404b540aSrobert       if (val
968404b540aSrobert 	  && val->value
969404b540aSrobert 	  && (is_gimple_reg (val->value)
970404b540aSrobert 	      || is_gimple_min_invariant (val->value))
971404b540aSrobert 	  && simple_cst_equal (rhs, val->mem_ref) == 1)
972404b540aSrobert 
973404b540aSrobert 	{
974404b540aSrobert 	  /* If we are replacing a constant address, inform our
975404b540aSrobert 	     caller.  */
976404b540aSrobert 	  if (TREE_CODE (val->value) != SSA_NAME
977404b540aSrobert 	      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 1)))
978404b540aSrobert 	      && replaced_addresses_p)
979404b540aSrobert 	    *replaced_addresses_p = true;
980404b540aSrobert 
981404b540aSrobert 	  /* We can only perform the substitution if the load is done
982404b540aSrobert 	     from the same memory location as the original store.
983404b540aSrobert 	     Since we already know that there are no intervening
984404b540aSrobert 	     stores between DEF_STMT and STMT, we only need to check
985404b540aSrobert 	     that the RHS of STMT is the same as the memory reference
986404b540aSrobert 	     propagated together with the value.  */
987404b540aSrobert 	  TREE_OPERAND (stmt, 1) = val->value;
988404b540aSrobert 
989404b540aSrobert 	  if (TREE_CODE (val->value) != SSA_NAME)
990404b540aSrobert 	    prop_stats.num_const_prop++;
991404b540aSrobert 	  else
992404b540aSrobert 	    prop_stats.num_copy_prop++;
993404b540aSrobert 
994404b540aSrobert 	  /* Since we have replaced the whole RHS of STMT, there
995404b540aSrobert 	     is no point in checking the other VUSEs, as they will
996404b540aSrobert 	     all have the same value.  */
997404b540aSrobert 	  return true;
998404b540aSrobert 	}
999404b540aSrobert     }
1000404b540aSrobert 
1001404b540aSrobert   /* Otherwise, the values for every VUSE operand must be other
1002404b540aSrobert      SSA_NAMEs that can be propagated into STMT.  */
1003404b540aSrobert   FOR_EACH_SSA_USE_OPERAND (vuse, stmt, iter, SSA_OP_VIRTUAL_USES)
1004404b540aSrobert     {
1005404b540aSrobert       tree var = USE_FROM_PTR (vuse);
1006404b540aSrobert       tree val = prop_value[SSA_NAME_VERSION (var)].value;
1007404b540aSrobert 
1008404b540aSrobert       if (val == NULL_TREE || var == val)
1009404b540aSrobert 	continue;
1010404b540aSrobert 
1011404b540aSrobert       /* Constants and copies propagated between real and virtual
1012404b540aSrobert 	 operands are only possible in the cases handled above.  They
1013404b540aSrobert 	 should be ignored in any other context.  */
1014404b540aSrobert       if (is_gimple_min_invariant (val) || is_gimple_reg (val))
1015404b540aSrobert 	continue;
1016404b540aSrobert 
1017404b540aSrobert       propagate_value (vuse, val);
1018404b540aSrobert       prop_stats.num_copy_prop++;
1019404b540aSrobert       replaced = true;
1020404b540aSrobert     }
1021404b540aSrobert 
1022404b540aSrobert   return replaced;
1023404b540aSrobert }
1024404b540aSrobert 
1025404b540aSrobert 
1026404b540aSrobert /* Replace propagated values into all the arguments for PHI using the
1027404b540aSrobert    values from PROP_VALUE.  */
1028404b540aSrobert 
1029404b540aSrobert static void
replace_phi_args_in(tree phi,prop_value_t * prop_value)1030404b540aSrobert replace_phi_args_in (tree phi, prop_value_t *prop_value)
1031404b540aSrobert {
1032404b540aSrobert   int i;
1033404b540aSrobert   bool replaced = false;
1034404b540aSrobert   tree prev_phi = NULL;
1035404b540aSrobert 
1036404b540aSrobert   if (dump_file && (dump_flags & TDF_DETAILS))
1037404b540aSrobert     prev_phi = unshare_expr (phi);
1038404b540aSrobert 
1039404b540aSrobert   for (i = 0; i < PHI_NUM_ARGS (phi); i++)
1040404b540aSrobert     {
1041404b540aSrobert       tree arg = PHI_ARG_DEF (phi, i);
1042404b540aSrobert 
1043404b540aSrobert       if (TREE_CODE (arg) == SSA_NAME)
1044404b540aSrobert 	{
1045404b540aSrobert 	  tree val = prop_value[SSA_NAME_VERSION (arg)].value;
1046404b540aSrobert 
1047404b540aSrobert 	  if (val && val != arg && may_propagate_copy (arg, val))
1048404b540aSrobert 	    {
1049404b540aSrobert 	      if (TREE_CODE (val) != SSA_NAME)
1050404b540aSrobert 		prop_stats.num_const_prop++;
1051404b540aSrobert 	      else
1052404b540aSrobert 		prop_stats.num_copy_prop++;
1053404b540aSrobert 
1054404b540aSrobert 	      propagate_value (PHI_ARG_DEF_PTR (phi, i), val);
1055404b540aSrobert 	      replaced = true;
1056404b540aSrobert 
1057404b540aSrobert 	      /* If we propagated a copy and this argument flows
1058404b540aSrobert 		 through an abnormal edge, update the replacement
1059404b540aSrobert 		 accordingly.  */
1060404b540aSrobert 	      if (TREE_CODE (val) == SSA_NAME
1061404b540aSrobert 		  && PHI_ARG_EDGE (phi, i)->flags & EDGE_ABNORMAL)
1062404b540aSrobert 		SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1;
1063404b540aSrobert 	    }
1064404b540aSrobert 	}
1065404b540aSrobert     }
1066404b540aSrobert 
1067404b540aSrobert   if (replaced && dump_file && (dump_flags & TDF_DETAILS))
1068404b540aSrobert     {
1069404b540aSrobert       fprintf (dump_file, "Folded PHI node: ");
1070404b540aSrobert       print_generic_stmt (dump_file, prev_phi, TDF_SLIM);
1071404b540aSrobert       fprintf (dump_file, "           into: ");
1072404b540aSrobert       print_generic_stmt (dump_file, phi, TDF_SLIM);
1073404b540aSrobert       fprintf (dump_file, "\n");
1074404b540aSrobert     }
1075404b540aSrobert }
1076404b540aSrobert 
1077404b540aSrobert 
1078404b540aSrobert /* If STMT has a predicate whose value can be computed using the value
1079404b540aSrobert    range information computed by VRP, compute its value and return true.
1080404b540aSrobert    Otherwise, return false.  */
1081404b540aSrobert 
1082404b540aSrobert static bool
fold_predicate_in(tree stmt)1083404b540aSrobert fold_predicate_in (tree stmt)
1084404b540aSrobert {
1085404b540aSrobert   tree *pred_p = NULL;
1086404b540aSrobert   bool modify_expr_p = false;
1087404b540aSrobert   tree val;
1088404b540aSrobert 
1089404b540aSrobert   if (TREE_CODE (stmt) == MODIFY_EXPR
1090404b540aSrobert       && COMPARISON_CLASS_P (TREE_OPERAND (stmt, 1)))
1091404b540aSrobert     {
1092404b540aSrobert       modify_expr_p = true;
1093404b540aSrobert       pred_p = &TREE_OPERAND (stmt, 1);
1094404b540aSrobert     }
1095404b540aSrobert   else if (TREE_CODE (stmt) == COND_EXPR)
1096404b540aSrobert     pred_p = &COND_EXPR_COND (stmt);
1097404b540aSrobert   else
1098404b540aSrobert     return false;
1099404b540aSrobert 
1100404b540aSrobert   val = vrp_evaluate_conditional (*pred_p, stmt);
1101404b540aSrobert   if (val)
1102404b540aSrobert     {
1103404b540aSrobert       if (modify_expr_p)
1104404b540aSrobert         val = fold_convert (TREE_TYPE (*pred_p), val);
1105404b540aSrobert 
1106404b540aSrobert       if (dump_file)
1107404b540aSrobert 	{
1108404b540aSrobert 	  fprintf (dump_file, "Folding predicate ");
1109404b540aSrobert 	  print_generic_expr (dump_file, *pred_p, 0);
1110404b540aSrobert 	  fprintf (dump_file, " to ");
1111404b540aSrobert 	  print_generic_expr (dump_file, val, 0);
1112404b540aSrobert 	  fprintf (dump_file, "\n");
1113404b540aSrobert 	}
1114404b540aSrobert 
1115404b540aSrobert       prop_stats.num_pred_folded++;
1116404b540aSrobert       *pred_p = val;
1117404b540aSrobert       return true;
1118404b540aSrobert     }
1119404b540aSrobert 
1120404b540aSrobert   return false;
1121404b540aSrobert }
1122404b540aSrobert 
1123404b540aSrobert 
1124404b540aSrobert /* Perform final substitution and folding of propagated values.
1125404b540aSrobert 
1126404b540aSrobert    PROP_VALUE[I] contains the single value that should be substituted
1127404b540aSrobert    at every use of SSA name N_I.  If PROP_VALUE is NULL, no values are
1128404b540aSrobert    substituted.
1129404b540aSrobert 
1130404b540aSrobert    If USE_RANGES_P is true, statements that contain predicate
1131404b540aSrobert    expressions are evaluated with a call to vrp_evaluate_conditional.
1132404b540aSrobert    This will only give meaningful results when called from tree-vrp.c
1133404b540aSrobert    (the information used by vrp_evaluate_conditional is built by the
1134404b540aSrobert    VRP pass).  */
1135404b540aSrobert 
1136404b540aSrobert void
substitute_and_fold(prop_value_t * prop_value,bool use_ranges_p)1137404b540aSrobert substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
1138404b540aSrobert {
1139404b540aSrobert   basic_block bb;
1140404b540aSrobert 
1141404b540aSrobert   if (prop_value == NULL && !use_ranges_p)
1142404b540aSrobert     return;
1143404b540aSrobert 
1144404b540aSrobert   if (dump_file && (dump_flags & TDF_DETAILS))
1145404b540aSrobert     fprintf (dump_file, "\nSubstituing values and folding statements\n\n");
1146404b540aSrobert 
1147404b540aSrobert   memset (&prop_stats, 0, sizeof (prop_stats));
1148404b540aSrobert 
1149404b540aSrobert   /* Substitute values in every statement of every basic block.  */
1150404b540aSrobert   FOR_EACH_BB (bb)
1151404b540aSrobert     {
1152404b540aSrobert       block_stmt_iterator i;
1153404b540aSrobert       tree phi;
1154404b540aSrobert 
1155404b540aSrobert       /* Propagate known values into PHI nodes.  */
1156404b540aSrobert       if (prop_value)
1157404b540aSrobert 	for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
1158404b540aSrobert 	  replace_phi_args_in (phi, prop_value);
1159404b540aSrobert 
1160404b540aSrobert       for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
1161404b540aSrobert 	{
1162404b540aSrobert           bool replaced_address, did_replace;
1163404b540aSrobert 	  tree prev_stmt = NULL;
1164404b540aSrobert 	  tree stmt = bsi_stmt (i);
1165404b540aSrobert 
1166404b540aSrobert 	  /* Ignore ASSERT_EXPRs.  They are used by VRP to generate
1167404b540aSrobert 	     range information for names and they are discarded
1168404b540aSrobert 	     afterwards.  */
1169404b540aSrobert 	  if (TREE_CODE (stmt) == MODIFY_EXPR
1170404b540aSrobert 	      && TREE_CODE (TREE_OPERAND (stmt, 1)) == ASSERT_EXPR)
1171404b540aSrobert 	    continue;
1172404b540aSrobert 
1173404b540aSrobert 	  /* Replace the statement with its folded version and mark it
1174404b540aSrobert 	     folded.  */
1175404b540aSrobert 	  did_replace = false;
1176404b540aSrobert 	  replaced_address = false;
1177404b540aSrobert 	  if (dump_file && (dump_flags & TDF_DETAILS))
1178404b540aSrobert 	    prev_stmt = unshare_expr (stmt);
1179404b540aSrobert 
1180404b540aSrobert 	  /* If we have range information, see if we can fold
1181404b540aSrobert 	     predicate expressions.  */
1182404b540aSrobert 	  if (use_ranges_p)
1183404b540aSrobert 	    did_replace = fold_predicate_in (stmt);
1184404b540aSrobert 
1185404b540aSrobert 	  if (prop_value)
1186404b540aSrobert 	    {
1187404b540aSrobert 	      /* Only replace real uses if we couldn't fold the
1188404b540aSrobert 		 statement using value range information (value range
1189404b540aSrobert 		 information is not collected on virtuals, so we only
1190404b540aSrobert 		 need to check this for real uses).  */
1191404b540aSrobert 	      if (!did_replace)
1192404b540aSrobert 		did_replace |= replace_uses_in (stmt, &replaced_address,
1193404b540aSrobert 		                                prop_value);
1194404b540aSrobert 
1195404b540aSrobert 	      did_replace |= replace_vuses_in (stmt, &replaced_address,
1196404b540aSrobert 		                               prop_value);
1197404b540aSrobert 	    }
1198404b540aSrobert 
1199404b540aSrobert 	  /* If we made a replacement, fold and cleanup the statement.  */
1200404b540aSrobert 	  if (did_replace)
1201404b540aSrobert 	    {
1202404b540aSrobert 	      tree old_stmt = stmt;
1203404b540aSrobert 	      tree rhs;
1204404b540aSrobert 
1205404b540aSrobert 	      fold_stmt (bsi_stmt_ptr (i));
1206404b540aSrobert 	      stmt = bsi_stmt (i);
1207404b540aSrobert 
1208404b540aSrobert 	      /* If we folded a builtin function, we'll likely
1209404b540aSrobert 		 need to rename VDEFs.  */
1210404b540aSrobert 	      mark_new_vars_to_rename (stmt);
1211404b540aSrobert 
1212404b540aSrobert               /* If we cleaned up EH information from the statement,
1213404b540aSrobert                  remove EH edges.  */
1214404b540aSrobert 	      if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
1215404b540aSrobert 		tree_purge_dead_eh_edges (bb);
1216404b540aSrobert 
1217404b540aSrobert 	      rhs = get_rhs (stmt);
1218404b540aSrobert 	      if (TREE_CODE (rhs) == ADDR_EXPR)
1219404b540aSrobert 		recompute_tree_invariant_for_addr_expr (rhs);
1220404b540aSrobert 
1221404b540aSrobert 	      if (dump_file && (dump_flags & TDF_DETAILS))
1222404b540aSrobert 		{
1223404b540aSrobert 		  fprintf (dump_file, "Folded statement: ");
1224404b540aSrobert 		  print_generic_stmt (dump_file, prev_stmt, TDF_SLIM);
1225404b540aSrobert 		  fprintf (dump_file, "            into: ");
1226404b540aSrobert 		  print_generic_stmt (dump_file, stmt, TDF_SLIM);
1227404b540aSrobert 		  fprintf (dump_file, "\n");
1228404b540aSrobert 		}
1229404b540aSrobert 	    }
1230404b540aSrobert 
1231404b540aSrobert 	  /* Some statements may be simplified using ranges.  For
1232404b540aSrobert 	     example, division may be replaced by shifts, modulo
1233404b540aSrobert 	     replaced with bitwise and, etc.   Do this after
1234404b540aSrobert 	     substituting constants, folding, etc so that we're
1235404b540aSrobert 	     presented with a fully propagated, canonicalized
1236404b540aSrobert 	     statement.  */
1237404b540aSrobert 	  if (use_ranges_p)
1238404b540aSrobert 	    simplify_stmt_using_ranges (stmt);
1239404b540aSrobert 
1240404b540aSrobert 	}
1241404b540aSrobert     }
1242404b540aSrobert 
1243404b540aSrobert   if (dump_file && (dump_flags & TDF_STATS))
1244404b540aSrobert     {
1245404b540aSrobert       fprintf (dump_file, "Constants propagated: %6ld\n",
1246404b540aSrobert 	       prop_stats.num_const_prop);
1247404b540aSrobert       fprintf (dump_file, "Copies propagated:    %6ld\n",
1248404b540aSrobert 	       prop_stats.num_copy_prop);
1249404b540aSrobert       fprintf (dump_file, "Predicates folded:    %6ld\n",
1250404b540aSrobert 	       prop_stats.num_pred_folded);
1251404b540aSrobert     }
1252404b540aSrobert }
1253404b540aSrobert 
1254404b540aSrobert #include "gt-tree-ssa-propagate.h"
1255