* Makefile.in (tree-update-ssa.o): Add.
[official-gcc.git] / gcc / tree-ssa-threadupdate.c
blob5d05bea9791283600c22676191f9788617baaab2
1 /* Thread edges through blocks and update the control flow and SSA graphs.
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "flags.h"
27 #include "rtl.h"
28 #include "tm_p.h"
29 #include "ggc.h"
30 #include "basic-block.h"
31 #include "output.h"
32 #include "errors.h"
33 #include "expr.h"
34 #include "function.h"
35 #include "diagnostic.h"
36 #include "tree-flow.h"
37 #include "tree-dump.h"
38 #include "tree-pass.h"
40 /* Given a block B, update the CFG and SSA graph to reflect redirecting
41 one or more in-edges to B to instead reach the destination of an
42 out-edge from B while preserving any side effects in B.
44 i.e., given A->B and B->C, change A->B to be A->C yet still preserve the
45 side effects of executing B.
47 1. Make a copy of B (including its outgoing edges and statements). Call
48 the copy B'. Note B' has no incoming edges or PHIs at this time.
50 2. Remove the control statement at the end of B' and all outgoing edges
51 except B'->C.
53 3. Add a new argument to each PHI in C with the same value as the existing
54 argument associated with edge B->C. Associate the new PHI arguments
55 with the edge B'->C.
57 4. For each PHI in B, find or create a PHI in B' with an identical
58 PHI_RESULT. Add an argument to the PHI in B' which has the same
59 value as the PHI in B associated with the edge A->B. Associate
60 the new argument in the PHI in B' with the edge A->B.
62 5. Change the edge A->B to A->B'.
64 5a. This automatically deletes any PHI arguments associated with the
65 edge A->B in B.
67 5b. This automatically associates each new argument added in step 4
68 with the edge A->B'.
70 6. Repeat for other incoming edges into B.
72 7. Put the duplicated resources in B and all the B' blocks into SSA form.
74 Note that block duplication can be minimized by first collecting the
75 the set of unique destination blocks that the incoming edges should
76 be threaded to. Block duplication can be further minimized by using
77 B instead of creating B' for one destination if all edges into B are
78 going to be threaded to a successor of B. */
81 /* Main data structure recording information regarding B's duplicate
82 blocks. */
84 struct redirection_data
86 /* A duplicate of B with the trailing control statement removed and which
87 targets a single successor of B. */
88 basic_block dup_block;
90 /* An outgoing edge from B. DUP_BLOCK will have OUTGOING_EDGE->dest as
91 its single successor. */
92 edge outgoing_edge;
95 /* Main data structure to hold information for duplicates of BB. */
96 static varray_type redirection_data;
98 /* For each PHI node in BB, find or create a PHI node in NEW_BB for the
99 same PHI_RESULT. Add an argument to the PHI node in NEW_BB which
100 corresponds to the same PHI argument associated with edge E in BB. */
102 static void
103 copy_phis_to_block (basic_block new_bb, basic_block bb, edge e)
105 tree phi, arg;
106 tree new_phi;
108 /* Walk over every PHI in BB. */
109 for (phi = phi_nodes (bb), new_phi = phi_nodes (new_bb);
110 phi;
111 phi = PHI_CHAIN (phi), new_phi = PHI_CHAIN (new_phi))
113 gcc_assert (original_equivalent_name (PHI_RESULT (phi))
114 == original_equivalent_name (PHI_RESULT (new_phi)));
116 /* Extract the argument corresponding to E from the current PHI
117 node in BB. */
118 arg = PHI_ARG_DEF (phi, phi_arg_from_edge (phi, e));
120 /* Now add that same argument to the new PHI node in block NEW_BB. */
121 add_phi_arg (&new_phi, arg, e);
125 /* Remove the last statement in block BB if it is a control statement
126 Also remove all outgoing edges except the edge which reaches DEST_BB.
127 If DEST_BB is NULL, then remove all outgoing edges. */
129 static void
130 remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
132 block_stmt_iterator bsi;
133 edge e;
134 edge_iterator ei;
136 bsi = bsi_last (bb);
138 /* If the duplicate ends with a control statement, then remove it.
140 Note that if we are duplicating the template block rather than the
141 original basic block, then the duplicate might not have any real
142 statements in it. */
143 if (!bsi_end_p (bsi)
144 && bsi_stmt (bsi)
145 && (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR
146 || TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR))
147 bsi_remove (&bsi);
149 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
151 if (e->dest != dest_bb)
152 ssa_remove_edge (e);
153 else
154 ei_next (&ei);
158 /* Create a duplicate of BB which only reaches the destination of the edge
159 stored in RD. Record the duplicate block in RD. */
161 static void
162 create_block_for_threading (basic_block bb, struct redirection_data *rd)
164 /* We can use the generic block duplication code and simply remove
165 the stuff we do not need. */
166 rd->dup_block = duplicate_block (bb, NULL);
168 /* Zero out the profile, since the block is unreachable for now. */
169 rd->dup_block->frequency = 0;
170 rd->dup_block->count = 0;
172 /* The call to duplicate_block will copy everything, including the
173 useless COND_EXPR or SWITCH_EXPR at the end of BB. We just remove
174 the useless COND_EXPR or SWITCH_EXPR here rather than having a
175 specialized block copier. We also remove all outgoing edges
176 from the duplicate block. The appropriate edge will be created
177 later. */
178 remove_ctrl_stmt_and_useless_edges (rd->dup_block, NULL);
181 /* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
182 is reached via one or more specific incoming edges, we know which
183 outgoing edge from BB will be traversed.
185 We want to redirect those incoming edges to the target of the
186 appropriate outgoing edge. Doing so avoids a conditional branch
187 and may expose new optimization opportunities. Note that we have
188 to update dominator tree and SSA graph after such changes.
190 The key to keeping the SSA graph update manageable is to duplicate
191 the side effects occurring in BB so that those side effects still
192 occur on the paths which bypass BB after redirecting edges.
194 We accomplish this by creating duplicates of BB and arranging for
195 the duplicates to unconditionally pass control to one specific
196 successor of BB. We then revector the incoming edges into BB to
197 the appropriate duplicate of BB.
199 BB and its duplicates will have assignments to the same set of
200 SSA_NAMEs. Right now, we just call into rewrite_ssa_into_ssa
201 to update the SSA graph for those names.
203 We are also going to experiment with a true incremental update
204 scheme for the duplicated resources. One of the interesting
205 properties we can exploit here is that all the resources set
206 in BB will have the same IDFS, so we have one IDFS computation
207 per block with incoming threaded edges, which can lower the
208 cost of the true incremental update algorithm. */
210 static void
211 thread_block (basic_block bb)
213 /* E is an incoming edge into BB that we may or may not want to
214 redirect to a duplicate of BB. */
215 edge e;
216 edge_iterator ei;
217 basic_block template_block;
219 /* ALL indicates whether or not all incoming edges into BB should
220 be threaded to a duplicate of BB. */
221 bool all = true;
223 unsigned int i;
225 VARRAY_GENERIC_PTR_INIT (redirection_data, 2, "redirection data");
227 /* Look at each incoming edge into BB. Record each unique outgoing
228 edge that we want to thread an incoming edge to. Also note if
229 all incoming edges are threaded or not. */
230 FOR_EACH_EDGE (e, ei, bb->preds)
232 if (!e->aux)
234 all = false;
236 else
238 unsigned int i;
240 /* See if we can find an entry for the destination of this
241 threaded edge that has already been recorded. */
242 for (i = 0; i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
244 struct redirection_data *rd;
245 edge e2;
247 rd = VARRAY_GENERIC_PTR (redirection_data, i);
248 e2 = e->aux;
250 if (e2->dest == rd->outgoing_edge->dest)
251 break;
254 /* If the loop did not terminate early, then we have a new
255 destination for the incoming threaded edges. Record it. */
256 if (i == VARRAY_ACTIVE_SIZE (redirection_data))
258 struct redirection_data *rd;
260 rd = ggc_alloc_cleared (sizeof (struct redirection_data));
261 rd->outgoing_edge = e->aux;
262 VARRAY_PUSH_GENERIC_PTR (redirection_data, rd);
267 /* Now create duplicates of BB. Note that if all incoming edges are
268 threaded, then BB is going to become unreachable. In that case
269 we use BB for one of the duplicates rather than wasting memory
270 duplicating BB. Thus the odd starting condition for the loop.
272 Note that for a block with a high outgoing degree we can waste
273 a lot of time and memory creating and destroying useless edges.
275 So we first duplicate BB and remove the control structure at the
276 tail of the duplicate as well as all outgoing edges from the
277 duplicate. We then use that duplicate block as a template for
278 the rest of the duplicates. */
279 template_block = NULL;
280 for (i = (all ? 1 : 0); i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
282 struct redirection_data *rd = VARRAY_GENERIC_PTR (redirection_data, i);
284 if (template_block == NULL)
286 create_block_for_threading (bb, rd);
287 template_block = rd->dup_block;
289 else
291 create_block_for_threading (template_block, rd);
295 /* Now created up edges from the duplicate blocks to their new
296 destinations. Doing this as a separate loop after block creation
297 allows us to avoid creating lots of useless edges. */
298 for (i = (all ? 1 : 0); i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
300 struct redirection_data *rd = VARRAY_GENERIC_PTR (redirection_data, i);
301 tree phi;
302 edge e;
304 e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU);
306 /* If there are any PHI nodes at the destination of the outgoing edge
307 from the duplicate block, then we will need to add a new argument
308 to them. The argument should have the same value as the argument
309 associated with the outgoing edge stored in RD. */
310 for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
312 int indx = phi_arg_from_edge (phi, rd->outgoing_edge);
313 add_phi_arg (&phi, PHI_ARG_DEF (phi, indx), e);
317 /* The loop above created the duplicate blocks (and the statements
318 within the duplicate blocks). This loop creates PHI nodes for the
319 duplicated blocks and redirects the incoming edges into BB to reach
320 the duplicates of BB.
322 Note that redirecting the edge will change e->pred_next, so we have
323 to hold e->pred_next in a temporary.
325 If this turns out to be a performance problem, then we could create
326 a list of incoming edges associated with each entry in
327 REDIRECTION_DATA and walk over that list of edges instead. */
328 for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
330 edge new_dest = e->aux;
332 /* E was not threaded, then there is nothing to do. */
333 if (!new_dest)
335 ei_next (&ei);
336 continue;
339 /* Go ahead and clear E->aux. It's not needed anymore and failure
340 to clear it will cause all kinds of unpleasant problems later. */
341 e->aux = NULL;
343 /* We know E is an edge we want to thread. Find the entry associated
344 with E's new destination in the REDIRECTION_DATA array. */
345 for (i = 0; i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
347 struct redirection_data *rd;
349 rd = VARRAY_GENERIC_PTR (redirection_data, i);
351 /* We have found the right entry if the outgoing edge in this
352 entry matches E's new destination. Note that if we have not
353 created a duplicate block (rd->dup_block is NULL), then we
354 are going to re-use BB as a duplicate and we do not need
355 to create PHI nodes or redirect the edge. */
356 if (rd->outgoing_edge == new_dest && rd->dup_block)
358 edge e2;
359 copy_phis_to_block (rd->dup_block, bb, e);
361 if (dump_file && (dump_flags & TDF_DETAILS))
362 fprintf (dump_file, " Threaded jump %d --> %d to %d\n",
363 e->src->index, e->dest->index, rd->dup_block->index);
365 e2 = redirect_edge_and_branch (e, rd->dup_block);
366 PENDING_STMT (e2) = NULL;
368 if ((dump_file && (dump_flags & TDF_DETAILS))
369 && e->src != e2->src)
370 fprintf (dump_file, " basic block %d created\n",
371 e2->src->index);
372 break;
377 /* If all the incoming edges where threaded, then we used BB as one
378 of the duplicate blocks. We need to fixup BB in that case so that
379 it no longer has a COND_EXPR or SWITCH_EXPR and reaches one destination
380 unconditionally. */
381 if (all)
383 struct redirection_data *rd;
385 rd = VARRAY_GENERIC_PTR (redirection_data, 0);
387 if (dump_file && (dump_flags & TDF_DETAILS))
388 fprintf (dump_file, " Threaded jump %d --> %d to %d\n",
389 EDGE_PRED (bb, 0)->src->index, bb->index,
390 EDGE_SUCC (bb, 0)->dest->index);
392 remove_ctrl_stmt_and_useless_edges (bb, rd->outgoing_edge->dest);
393 EDGE_SUCC (bb, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
394 EDGE_SUCC (bb, 0)->flags |= EDGE_FALLTHRU;
397 /* Done with this block. Clear REDIRECTION_DATA. */
398 VARRAY_CLEAR (redirection_data);
401 /* Walk through all blocks and thread incoming edges to the block's
402 destinations as requested. This is the only entry point into this
403 file.
405 Blocks which have one or more incoming edges have INCOMING_EDGE_THREADED
406 set in the block's annotation.
407 this routine.
409 Each edge that should be threaded has the new destination edge stored in
410 the original edge's AUX field.
412 This routine (or one of its callees) will clear INCOMING_EDGE_THREADED
413 in the block annotations and the AUX field in the edges.
415 It is the caller's responsibility to fix the dominance information
416 and rewrite duplicated SSA_NAMEs back into SSA form.
418 Returns true if one or more edges were threaded, false otherwise. */
420 bool
421 thread_through_all_blocks (void)
423 basic_block bb;
424 bool retval = false;
426 FOR_EACH_BB (bb)
428 if (bb_ann (bb)->incoming_edge_threaded)
430 thread_block (bb);
431 retval = true;
432 bb_ann (bb)->incoming_edge_threaded = false;
435 return retval;