c-common.c, [...]: Fix comment typos.
[gcc.git] / gcc / tree-ssa-threadupdate.c
1 /* Thread edges through blocks and update the control flow and SSA graphs.
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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. */
20
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"
39
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.
43
44 ie, given A->B and B->C, change A->B to be A->C yet still preserve the
45 side effects of executing B.
46
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.
49
50 2. Remove the control statement at the end of B' and all outgoing edges
51 except B'->C.
52
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.
56
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 as 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.
61
62 5. Change the edge A->B to A->B'.
63
64 5a. This automatically deletes any PHI arguments associated with the
65 edge A->B in B.
66
67 5b. This automatically associates each new argument added in step 4
68 with the edge A->B'.
69
70 6. Repeat for other incoming edges into B.
71
72 7. Put the duplicated resources in B and all the B' blocks into SSA form.
73
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. */
79
80
81 /* Main data structure recording information regarding B's duplicate
82 blocks. */
83
84 struct redirection_data
85 {
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;
89
90 /* An outgoing edge from B. DUP_BLOCK will have OUTGOING_EDGE->dest as
91 its single successor. */
92 edge outgoing_edge;
93 };
94
95 /* Main data structure to hold information for duplicates of BB. */
96 static varray_type redirection_data;
97
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. */
101
102 static void
103 copy_phis_to_block (basic_block new_bb, basic_block bb, edge e)
104 {
105 tree phi, arg;
106
107 /* Walk over every PHI in BB. */
108 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
109 {
110 tree new_phi;
111
112 /* First try to find a PHI node in NEW_BB which has the same
113 PHI_RESULT as the PHI from BB we are currently processing. */
114 for (new_phi = phi_nodes (new_bb); new_phi;
115 new_phi = PHI_CHAIN (new_phi))
116 if (PHI_RESULT (new_phi) == PHI_RESULT (phi))
117 break;
118
119 /* If we did not find a suitable PHI in NEW_BB, create one. */
120 if (!new_phi)
121 new_phi = create_phi_node (PHI_RESULT (phi), new_bb);
122
123 /* Extract the argument corresponding to E from the current PHI
124 node in BB. */
125 arg = PHI_ARG_DEF_TREE (phi, phi_arg_from_edge (phi, e));
126
127 /* Now add that same argument to the new PHI node in block NEW_BB. */
128 add_phi_arg (&new_phi, arg, e);
129 }
130 }
131
132 /* Remove the last statement in block BB which must be a COND_EXPR or
133 SWITCH_EXPR. Also remove all outgoing edges except the edge which
134 reaches DEST_BB.
135
136 This is only used by jump threading which knows the last statement in
137 BB should be a COND_EXPR or SWITCH_EXPR. If the block ends with any other
138 statement, then we abort. */
139
140 static void
141 remove_last_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
142 {
143 block_stmt_iterator bsi;
144 edge e, next;
145
146 bsi = bsi_last (bb);
147
148 #ifdef ENABLE_CHECKING
149 if (TREE_CODE (bsi_stmt (bsi)) != COND_EXPR
150 && TREE_CODE (bsi_stmt (bsi)) != SWITCH_EXPR)
151 abort ();
152 #endif
153
154 bsi_remove (&bsi);
155
156 next = NULL;
157 for (e = bb->succ; e; e = next)
158 {
159 next = e->succ_next;
160
161 if (e->dest != dest_bb)
162 ssa_remove_edge (e);
163 }
164
165 /* BB now has a single outgoing edge. We need to update the flags for
166 that single outgoing edge. */
167 bb->succ->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
168 bb->succ->flags |= EDGE_FALLTHRU;
169 }
170
171 /* Create a duplicate of BB which only reaches the destination of the edge
172 stored in RD. Record the duplicate block in RD. */
173
174 static void
175 create_block_for_threading (basic_block bb, struct redirection_data *rd)
176 {
177 tree phi;
178
179 /* We can use the generic block duplication code and simply remove
180 the stuff we do not need. */
181 rd->dup_block = duplicate_block (bb, NULL);
182
183 /* The call to duplicate_block will copy everything, including the
184 useless COND_EXPR or SWITCH_EXPR at the end of the block. We just remove
185 the useless COND_EXPR or SWITCH_EXPR here rather than having a
186 specialized block copier. */
187 remove_last_stmt_and_useless_edges (rd->dup_block, rd->outgoing_edge->dest);
188
189 /* If there are any PHI nodes at the destination of the outgoing edge
190 from the duplicate block, then we will need to add a new argument
191 to them. The argument should have the same value as the argument
192 associated with the outgoing edge stored in RD. */
193 for (phi = phi_nodes (rd->dup_block->succ->dest); phi;
194 phi = PHI_CHAIN (phi))
195 {
196 int indx = phi_arg_from_edge (phi, rd->outgoing_edge);
197 add_phi_arg (&phi, PHI_ARG_DEF_TREE (phi, indx), rd->dup_block->succ);
198 }
199 }
200
201 /* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
202 is reached via one or more specific incoming edges, we know which
203 outgoing edge from BB will be traversed.
204
205 We want to redirect those incoming edges to the target of the
206 appropriate outgoing edge. Doing so avoids a conditional branch
207 and may expose new optimization opportunities. Note that we have
208 to update dominator tree and SSA graph after such changes.
209
210 The key to keeping the SSA graph update managable is to duplicate
211 the side effects occurring in BB so that those side effects still
212 occur on the paths which bypass BB after redirecting edges.
213
214 We accomplish this by creating duplicates of BB and arranging for
215 the duplicates to unconditionally pass control to one specific
216 successor of BB. We then revector the incoming edges into BB to
217 the appropriate duplicate of BB.
218
219 BB and its duplicates will have assignments to the same set of
220 SSA_NAMEs. Right now, we just call into rewrite_ssa_into_ssa
221 to update the SSA graph for those names.
222
223 We are also going to experiment with a true incremental update
224 scheme for the duplicated resources. Of of the interesting
225 properties we can exploit here is that all the resources set
226 in BB will have the same IDFS, so we have one IDFS computation
227 per block with incoming threaded edges, which can lower the
228 cost of the true incremental update algorithm. */
229
230 static void
231 thread_block (basic_block bb)
232 {
233 /* E is an incoming edge into BB that we may or may not want to
234 redirect to a duplicate of BB. */
235 edge e;
236
237 /* The next edge in a predecessor list. Used in loops where E->pred_next
238 may change within the loop. */
239 edge next;
240
241 /* ALL indicates whether or not all incoming edges into BB should
242 be threaded to a duplicate of BB. */
243 bool all = true;
244
245 unsigned int i;
246
247 VARRAY_GENERIC_PTR_INIT (redirection_data, 2, "redirection data");
248
249 /* Look at each incoming edge into BB. Record each unique outgoing
250 edge that we want to thread an incoming edge to. Also note if
251 all incoming edges are threaded or not. */
252 for (e = bb->pred; e; e = e->pred_next)
253 {
254 if (!e->aux)
255 {
256 all = false;
257 }
258 else
259 {
260 unsigned int i;
261
262 /* See if we can find an entry for the destination of this
263 threaded edge that has already been recorded. */
264 for (i = 0; i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
265 {
266 struct redirection_data *rd;
267 edge e2;
268
269 rd = VARRAY_GENERIC_PTR (redirection_data, i);
270 e2 = e->aux;
271
272 if (e2->dest == rd->outgoing_edge->dest)
273 break;
274 }
275
276 /* If the loop did not terminate early, then we have a new
277 destination for the incoming threaded edges. Record it. */
278 if (i == VARRAY_ACTIVE_SIZE (redirection_data))
279 {
280 struct redirection_data *rd;
281
282 rd = ggc_alloc_cleared (sizeof (struct redirection_data));
283 rd->outgoing_edge = e->aux;
284 VARRAY_PUSH_GENERIC_PTR (redirection_data, rd);
285 }
286 }
287 }
288
289 /* Now create duplicates of BB. Note that if all incoming edges are
290 threaded, then BB is going to become unreachable. In that case
291 we use BB for one of the duplicates rather than wasting memory
292 duplicating BB. Thus the odd starting condition for the loop. */
293 for (i = (all ? 1 : 0); i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
294 {
295 struct redirection_data *rd = VARRAY_GENERIC_PTR (redirection_data, i);
296 create_block_for_threading (bb, rd);
297 }
298
299 /* The loop above created the duplicate blocks (and the statements
300 within the duplicate blocks). This loop creates PHI nodes for the
301 duplicated blocks and redirects the incoming edges into BB to reach
302 the duplicates of BB.
303
304 Note that redirecting the edge will change e->pred_next, so we have
305 to hold e->pred_next in a temporary.
306
307 If this turns out to be a performance problem, then we could create
308 a list of incoming edges associated with each entry in
309 REDIRECTION_DATA and walk over that list of edges instead. */
310 next = NULL;
311 for (e = bb->pred; e; e = next)
312 {
313 edge new_dest = e->aux;
314
315 next = e->pred_next;
316
317 /* E was not threaded, then there is nothing to do. */
318 if (!new_dest)
319 continue;
320
321 /* Go ahead and clear E->aux. It's not needed anymore and failure
322 to clear it will cause all kinds of unpleasant problems later. */
323 e->aux = NULL;
324
325 /* We know E is an edge we want to thread. Find the entry associated
326 with E's new destination in the REDIRECTION_DATA array. */
327 for (i = 0; i < VARRAY_ACTIVE_SIZE (redirection_data); i++)
328 {
329 struct redirection_data *rd;
330
331 rd = VARRAY_GENERIC_PTR (redirection_data, i);
332
333 /* We have found the right entry if the outgoing edge in this
334 entry matches E's new destination. Note that if we have not
335 created a duplicate block (rd->dup_block is NULL), then we
336 are going to re-use BB as a duplicate and we do not need
337 to create PHI nodes or redirect the edge. */
338 if (rd->outgoing_edge == new_dest && rd->dup_block)
339 {
340 edge e2;
341 copy_phis_to_block (rd->dup_block, bb, e);
342
343 if (dump_file && (dump_flags & TDF_DETAILS))
344 fprintf (dump_file, " Threaded jump %d --> %d to %d\n",
345 e->src->index, e->dest->index, rd->dup_block->index);
346
347 e2 = redirect_edge_and_branch (e, rd->dup_block);
348 PENDING_STMT (e2) = NULL;
349
350 if ((dump_file && (dump_flags & TDF_DETAILS))
351 && e->src != e2->src)
352 fprintf (dump_file, " basic block %d created\n",
353 e2->src->index);
354 break;
355 }
356 }
357 }
358
359 /* If all the incoming edges where threaded, then we used BB as one
360 of the duplicate blocks. We need to fixup BB in that case so that
361 it no longer has a COND_EXPR or SWITCH_EXPR and reaches one destination
362 unconditionally. */
363 if (all)
364 {
365 struct redirection_data *rd;
366
367 rd = VARRAY_GENERIC_PTR (redirection_data, 0);
368
369 if (dump_file && (dump_flags & TDF_DETAILS))
370 fprintf (dump_file, " Threaded jump %d --> %d to %d\n",
371 bb->pred->src->index, bb->index, bb->succ->dest->index);
372
373 remove_last_stmt_and_useless_edges (bb, rd->outgoing_edge->dest);
374 }
375
376 /* Done with this block. Clear REDIRECTION_DATA. */
377 VARRAY_CLEAR (redirection_data);
378 }
379
380 /* Walk through all blocks and thread incoming edges to the block's
381 destinations as requested. This is the only entry point into this
382 file.
383
384 Blocks which have one or more incoming edges have INCOMING_EDGE_THREADED
385 set in the block's annotation.
386 this routine.
387
388 Each edge that should be threaded has the new destination edge stored in
389 the original edge's AUX field.
390
391 This routine (or one of its callees) will clear INCOMING_EDGE_THREADED
392 in the block annotations and the AUX field in the edges.
393
394 It is the caller's responsibility to fix the dominance information
395 and rewrite duplicated SSA_NAMEs back into SSA form.
396
397 Returns true if one or more edges were threaded, false otherwise. */
398
399 bool
400 thread_through_all_blocks (void)
401 {
402 basic_block bb;
403 bool retval = false;
404
405 FOR_EACH_BB (bb)
406 {
407 if (bb_ann (bb)->incoming_edge_threaded)
408 {
409 thread_block (bb);
410 retval = true;
411 bb_ann (bb)->incoming_edge_threaded = false;
412 }
413 }
414 return retval;
415 }