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