Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-phinodes.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
rev | line source |
---|---|
0 | 1 /* Generic routines for manipulating PHIs |
2 Copyright (C) 2003, 2005, 2007, 2008 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 3, 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 COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
23 #include "tm.h" | |
24 #include "tree.h" | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
25 #include "rtl.h" /* FIXME: Only for ceil_log2, of all things... */ |
0 | 26 #include "ggc.h" |
27 #include "basic-block.h" | |
28 #include "tree-flow.h" | |
29 #include "toplev.h" | |
30 #include "gimple.h" | |
31 | |
32 /* Rewriting a function into SSA form can create a huge number of PHIs | |
33 many of which may be thrown away shortly after their creation if jumps | |
34 were threaded through PHI nodes. | |
35 | |
36 While our garbage collection mechanisms will handle this situation, it | |
37 is extremely wasteful to create nodes and throw them away, especially | |
38 when the nodes can be reused. | |
39 | |
40 For PR 8361, we can significantly reduce the number of nodes allocated | |
41 and thus the total amount of memory allocated by managing PHIs a | |
42 little. This additionally helps reduce the amount of work done by the | |
43 garbage collector. Similar results have been seen on a wider variety | |
44 of tests (such as the compiler itself). | |
45 | |
46 Right now we maintain our free list on a per-function basis. It may | |
47 or may not make sense to maintain the free list for the duration of | |
48 a compilation unit. | |
49 | |
50 We could also use a zone allocator for these objects since they have | |
51 a very well defined lifetime. If someone wants to experiment with that | |
52 this is the place to try it. | |
53 | |
54 PHI nodes have different sizes, so we can't have a single list of all | |
55 the PHI nodes as it would be too expensive to walk down that list to | |
56 find a PHI of a suitable size. | |
57 | |
58 Instead we have an array of lists of free PHI nodes. The array is | |
59 indexed by the number of PHI alternatives that PHI node can hold. | |
60 Except for the last array member, which holds all remaining PHI | |
61 nodes. | |
62 | |
63 So to find a free PHI node, we compute its index into the free PHI | |
64 node array and see if there are any elements with an exact match. | |
65 If so, then we are done. Otherwise, we test the next larger size | |
66 up and continue until we are in the last array element. | |
67 | |
68 We do not actually walk members of the last array element. While it | |
69 might allow us to pick up a few reusable PHI nodes, it could potentially | |
70 be very expensive if the program has released a bunch of large PHI nodes, | |
71 but keeps asking for even larger PHI nodes. Experiments have shown that | |
72 walking the elements of the last array entry would result in finding less | |
73 than .1% additional reusable PHI nodes. | |
74 | |
75 Note that we can never have less than two PHI argument slots. Thus, | |
76 the -2 on all the calculations below. */ | |
77 | |
78 #define NUM_BUCKETS 10 | |
79 static GTY ((deletable (""))) VEC(gimple,gc) *free_phinodes[NUM_BUCKETS - 2]; | |
80 static unsigned long free_phinode_count; | |
81 | |
82 static int ideal_phi_node_len (int); | |
83 | |
84 #ifdef GATHER_STATISTICS | |
85 unsigned int phi_nodes_reused; | |
86 unsigned int phi_nodes_created; | |
87 #endif | |
88 | |
89 /* Initialize management of PHIs. */ | |
90 | |
91 void | |
92 init_phinodes (void) | |
93 { | |
94 int i; | |
95 | |
96 for (i = 0; i < NUM_BUCKETS - 2; i++) | |
97 free_phinodes[i] = NULL; | |
98 free_phinode_count = 0; | |
99 } | |
100 | |
101 /* Finalize management of PHIs. */ | |
102 | |
103 void | |
104 fini_phinodes (void) | |
105 { | |
106 int i; | |
107 | |
108 for (i = 0; i < NUM_BUCKETS - 2; i++) | |
109 free_phinodes[i] = NULL; | |
110 free_phinode_count = 0; | |
111 } | |
112 | |
113 /* Dump some simple statistics regarding the re-use of PHI nodes. */ | |
114 | |
115 #ifdef GATHER_STATISTICS | |
116 void | |
117 phinodes_print_statistics (void) | |
118 { | |
119 fprintf (stderr, "PHI nodes allocated: %u\n", phi_nodes_created); | |
120 fprintf (stderr, "PHI nodes reused: %u\n", phi_nodes_reused); | |
121 } | |
122 #endif | |
123 | |
124 /* Allocate a PHI node with at least LEN arguments. If the free list | |
125 happens to contain a PHI node with LEN arguments or more, return | |
126 that one. */ | |
127 | |
128 static inline gimple | |
129 allocate_phi_node (size_t len) | |
130 { | |
131 gimple phi; | |
132 size_t bucket = NUM_BUCKETS - 2; | |
133 size_t size = sizeof (struct gimple_statement_phi) | |
134 + (len - 1) * sizeof (struct phi_arg_d); | |
135 | |
136 if (free_phinode_count) | |
137 for (bucket = len - 2; bucket < NUM_BUCKETS - 2; bucket++) | |
138 if (free_phinodes[bucket]) | |
139 break; | |
140 | |
141 /* If our free list has an element, then use it. */ | |
142 if (bucket < NUM_BUCKETS - 2 | |
143 && gimple_phi_capacity (VEC_index (gimple, free_phinodes[bucket], 0)) | |
144 >= len) | |
145 { | |
146 free_phinode_count--; | |
147 phi = VEC_pop (gimple, free_phinodes[bucket]); | |
148 if (VEC_empty (gimple, free_phinodes[bucket])) | |
149 VEC_free (gimple, gc, free_phinodes[bucket]); | |
150 #ifdef GATHER_STATISTICS | |
151 phi_nodes_reused++; | |
152 #endif | |
153 } | |
154 else | |
155 { | |
156 phi = (gimple) ggc_alloc (size); | |
157 #ifdef GATHER_STATISTICS | |
158 phi_nodes_created++; | |
159 { | |
160 enum gimple_alloc_kind kind = gimple_alloc_kind (GIMPLE_PHI); | |
161 gimple_alloc_counts[(int) kind]++; | |
162 gimple_alloc_sizes[(int) kind] += size; | |
163 } | |
164 #endif | |
165 } | |
166 | |
167 return phi; | |
168 } | |
169 | |
170 /* Given LEN, the original number of requested PHI arguments, return | |
171 a new, "ideal" length for the PHI node. The "ideal" length rounds | |
172 the total size of the PHI node up to the next power of two bytes. | |
173 | |
174 Rounding up will not result in wasting any memory since the size request | |
175 will be rounded up by the GC system anyway. [ Note this is not entirely | |
176 true since the original length might have fit on one of the special | |
177 GC pages. ] By rounding up, we may avoid the need to reallocate the | |
178 PHI node later if we increase the number of arguments for the PHI. */ | |
179 | |
180 static int | |
181 ideal_phi_node_len (int len) | |
182 { | |
183 size_t size, new_size; | |
184 int log2, new_len; | |
185 | |
186 /* We do not support allocations of less than two PHI argument slots. */ | |
187 if (len < 2) | |
188 len = 2; | |
189 | |
190 /* Compute the number of bytes of the original request. */ | |
191 size = sizeof (struct gimple_statement_phi) | |
192 + (len - 1) * sizeof (struct phi_arg_d); | |
193 | |
194 /* Round it up to the next power of two. */ | |
195 log2 = ceil_log2 (size); | |
196 new_size = 1 << log2; | |
197 | |
198 /* Now compute and return the number of PHI argument slots given an | |
199 ideal size allocation. */ | |
200 new_len = len + (new_size - size) / sizeof (struct phi_arg_d); | |
201 return new_len; | |
202 } | |
203 | |
204 /* Return a PHI node with LEN argument slots for variable VAR. */ | |
205 | |
206 gimple | |
207 make_phi_node (tree var, int len) | |
208 { | |
209 gimple phi; | |
210 int capacity, i; | |
211 | |
212 capacity = ideal_phi_node_len (len); | |
213 | |
214 phi = allocate_phi_node (capacity); | |
215 | |
216 /* We need to clear the entire PHI node, including the argument | |
217 portion, because we represent a "missing PHI argument" by placing | |
218 NULL_TREE in PHI_ARG_DEF. */ | |
219 memset (phi, 0, (sizeof (struct gimple_statement_phi) | |
220 - sizeof (struct phi_arg_d) | |
221 + sizeof (struct phi_arg_d) * len)); | |
222 phi->gsbase.code = GIMPLE_PHI; | |
223 phi->gimple_phi.nargs = len; | |
224 phi->gimple_phi.capacity = capacity; | |
225 if (TREE_CODE (var) == SSA_NAME) | |
226 gimple_phi_set_result (phi, var); | |
227 else | |
228 gimple_phi_set_result (phi, make_ssa_name (var, phi)); | |
229 | |
230 for (i = 0; i < capacity; i++) | |
231 { | |
232 use_operand_p imm; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
233 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
234 gimple_phi_arg_set_location (phi, i, UNKNOWN_LOCATION); |
0 | 235 imm = gimple_phi_arg_imm_use_ptr (phi, i); |
236 imm->use = gimple_phi_arg_def_ptr (phi, i); | |
237 imm->prev = NULL; | |
238 imm->next = NULL; | |
239 imm->loc.stmt = phi; | |
240 } | |
241 | |
242 return phi; | |
243 } | |
244 | |
245 /* We no longer need PHI, release it so that it may be reused. */ | |
246 | |
247 void | |
248 release_phi_node (gimple phi) | |
249 { | |
250 size_t bucket; | |
251 size_t len = gimple_phi_capacity (phi); | |
252 size_t x; | |
253 | |
254 for (x = 0; x < gimple_phi_num_args (phi); x++) | |
255 { | |
256 use_operand_p imm; | |
257 imm = gimple_phi_arg_imm_use_ptr (phi, x); | |
258 delink_imm_use (imm); | |
259 } | |
260 | |
261 bucket = len > NUM_BUCKETS - 1 ? NUM_BUCKETS - 1 : len; | |
262 bucket -= 2; | |
263 VEC_safe_push (gimple, gc, free_phinodes[bucket], phi); | |
264 free_phinode_count++; | |
265 } | |
266 | |
267 | |
268 /* Resize an existing PHI node. The only way is up. Return the | |
269 possibly relocated phi. */ | |
270 | |
271 static void | |
272 resize_phi_node (gimple *phi, size_t len) | |
273 { | |
274 size_t old_size, i; | |
275 gimple new_phi; | |
276 | |
277 gcc_assert (len > gimple_phi_capacity (*phi)); | |
278 | |
279 /* The garbage collector will not look at the PHI node beyond the | |
280 first PHI_NUM_ARGS elements. Therefore, all we have to copy is a | |
281 portion of the PHI node currently in use. */ | |
282 old_size = sizeof (struct gimple_statement_phi) | |
283 + (gimple_phi_num_args (*phi) - 1) * sizeof (struct phi_arg_d); | |
284 | |
285 new_phi = allocate_phi_node (len); | |
286 | |
287 memcpy (new_phi, *phi, old_size); | |
288 | |
289 for (i = 0; i < gimple_phi_num_args (new_phi); i++) | |
290 { | |
291 use_operand_p imm, old_imm; | |
292 imm = gimple_phi_arg_imm_use_ptr (new_phi, i); | |
293 old_imm = gimple_phi_arg_imm_use_ptr (*phi, i); | |
294 imm->use = gimple_phi_arg_def_ptr (new_phi, i); | |
295 relink_imm_use_stmt (imm, old_imm, new_phi); | |
296 } | |
297 | |
298 new_phi->gimple_phi.capacity = len; | |
299 | |
300 for (i = gimple_phi_num_args (new_phi); i < len; i++) | |
301 { | |
302 use_operand_p imm; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
303 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
304 gimple_phi_arg_set_location (new_phi, i, UNKNOWN_LOCATION); |
0 | 305 imm = gimple_phi_arg_imm_use_ptr (new_phi, i); |
306 imm->use = gimple_phi_arg_def_ptr (new_phi, i); | |
307 imm->prev = NULL; | |
308 imm->next = NULL; | |
309 imm->loc.stmt = new_phi; | |
310 } | |
311 | |
312 *phi = new_phi; | |
313 } | |
314 | |
315 /* Reserve PHI arguments for a new edge to basic block BB. */ | |
316 | |
317 void | |
318 reserve_phi_args_for_new_edge (basic_block bb) | |
319 { | |
320 size_t len = EDGE_COUNT (bb->preds); | |
321 size_t cap = ideal_phi_node_len (len + 4); | |
322 gimple_stmt_iterator gsi; | |
323 | |
324 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |
325 { | |
326 gimple *loc = gsi_stmt_ptr (&gsi); | |
327 | |
328 if (len > gimple_phi_capacity (*loc)) | |
329 { | |
330 gimple old_phi = *loc; | |
331 | |
332 resize_phi_node (loc, cap); | |
333 | |
334 /* The result of the PHI is defined by this PHI node. */ | |
335 SSA_NAME_DEF_STMT (gimple_phi_result (*loc)) = *loc; | |
336 | |
337 release_phi_node (old_phi); | |
338 } | |
339 | |
340 /* We represent a "missing PHI argument" by placing NULL_TREE in | |
341 the corresponding slot. If PHI arguments were added | |
342 immediately after an edge is created, this zeroing would not | |
343 be necessary, but unfortunately this is not the case. For | |
344 example, the loop optimizer duplicates several basic blocks, | |
345 redirects edges, and then fixes up PHI arguments later in | |
346 batch. */ | |
347 SET_PHI_ARG_DEF (*loc, len - 1, NULL_TREE); | |
348 | |
349 (*loc)->gimple_phi.nargs++; | |
350 } | |
351 } | |
352 | |
353 /* Adds PHI to BB. */ | |
354 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
355 void |
0 | 356 add_phi_node_to_bb (gimple phi, basic_block bb) |
357 { | |
358 gimple_stmt_iterator gsi; | |
359 /* Add the new PHI node to the list of PHI nodes for block BB. */ | |
360 if (phi_nodes (bb) == NULL) | |
361 set_phi_nodes (bb, gimple_seq_alloc ()); | |
362 | |
363 gsi = gsi_last (phi_nodes (bb)); | |
364 gsi_insert_after (&gsi, phi, GSI_NEW_STMT); | |
365 | |
366 /* Associate BB to the PHI node. */ | |
367 gimple_set_bb (phi, bb); | |
368 | |
369 } | |
370 | |
371 /* Create a new PHI node for variable VAR at basic block BB. */ | |
372 | |
373 gimple | |
374 create_phi_node (tree var, basic_block bb) | |
375 { | |
376 gimple phi = make_phi_node (var, EDGE_COUNT (bb->preds)); | |
377 | |
378 add_phi_node_to_bb (phi, bb); | |
379 return phi; | |
380 } | |
381 | |
382 | |
383 /* Add a new argument to PHI node PHI. DEF is the incoming reaching | |
384 definition and E is the edge through which DEF reaches PHI. The new | |
385 argument is added at the end of the argument list. | |
386 If PHI has reached its maximum capacity, add a few slots. In this case, | |
387 PHI points to the reallocated phi node when we return. */ | |
388 | |
389 void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
390 add_phi_arg (gimple phi, tree def, edge e, source_location locus) |
0 | 391 { |
392 basic_block bb = e->dest; | |
393 | |
394 gcc_assert (bb == gimple_bb (phi)); | |
395 | |
396 /* We resize PHI nodes upon edge creation. We should always have | |
397 enough room at this point. */ | |
398 gcc_assert (gimple_phi_num_args (phi) <= gimple_phi_capacity (phi)); | |
399 | |
400 /* We resize PHI nodes upon edge creation. We should always have | |
401 enough room at this point. */ | |
402 gcc_assert (e->dest_idx < gimple_phi_num_args (phi)); | |
403 | |
404 /* Copy propagation needs to know what object occur in abnormal | |
405 PHI nodes. This is a convenient place to record such information. */ | |
406 if (e->flags & EDGE_ABNORMAL) | |
407 { | |
408 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def) = 1; | |
409 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)) = 1; | |
410 } | |
411 | |
412 SET_PHI_ARG_DEF (phi, e->dest_idx, def); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
413 gimple_phi_arg_set_location (phi, e->dest_idx, locus); |
0 | 414 } |
415 | |
416 | |
417 /* Remove the Ith argument from PHI's argument list. This routine | |
418 implements removal by swapping the last alternative with the | |
419 alternative we want to delete and then shrinking the vector, which | |
420 is consistent with how we remove an edge from the edge vector. */ | |
421 | |
422 static void | |
423 remove_phi_arg_num (gimple phi, int i) | |
424 { | |
425 int num_elem = gimple_phi_num_args (phi); | |
426 | |
427 gcc_assert (i < num_elem); | |
428 | |
429 /* Delink the item which is being removed. */ | |
430 delink_imm_use (gimple_phi_arg_imm_use_ptr (phi, i)); | |
431 | |
432 /* If it is not the last element, move the last element | |
433 to the element we want to delete, resetting all the links. */ | |
434 if (i != num_elem - 1) | |
435 { | |
436 use_operand_p old_p, new_p; | |
437 old_p = gimple_phi_arg_imm_use_ptr (phi, num_elem - 1); | |
438 new_p = gimple_phi_arg_imm_use_ptr (phi, i); | |
439 /* Set use on new node, and link into last element's place. */ | |
440 *(new_p->use) = *(old_p->use); | |
441 relink_imm_use (new_p, old_p); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
442 /* Move the location as well. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
443 gimple_phi_arg_set_location (phi, i, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
444 gimple_phi_arg_location (phi, num_elem - 1)); |
0 | 445 } |
446 | |
447 /* Shrink the vector and return. Note that we do not have to clear | |
448 PHI_ARG_DEF because the garbage collector will not look at those | |
449 elements beyond the first PHI_NUM_ARGS elements of the array. */ | |
450 phi->gimple_phi.nargs--; | |
451 } | |
452 | |
453 | |
454 /* Remove all PHI arguments associated with edge E. */ | |
455 | |
456 void | |
457 remove_phi_args (edge e) | |
458 { | |
459 gimple_stmt_iterator gsi; | |
460 | |
461 for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi)) | |
462 remove_phi_arg_num (gsi_stmt (gsi), e->dest_idx); | |
463 } | |
464 | |
465 | |
466 /* Remove the PHI node pointed-to by iterator GSI from basic block BB. After | |
467 removal, iterator GSI is updated to point to the next PHI node in the | |
468 sequence. If RELEASE_LHS_P is true, the LHS of this PHI node is released | |
469 into the free pool of SSA names. */ | |
470 | |
471 void | |
472 remove_phi_node (gimple_stmt_iterator *gsi, bool release_lhs_p) | |
473 { | |
474 gimple phi = gsi_stmt (*gsi); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
475 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
476 if (release_lhs_p) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
477 insert_debug_temps_for_defs (gsi); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
478 |
0 | 479 gsi_remove (gsi, false); |
480 | |
481 /* If we are deleting the PHI node, then we should release the | |
482 SSA_NAME node so that it can be reused. */ | |
483 release_phi_node (phi); | |
484 if (release_lhs_p) | |
485 release_ssa_name (gimple_phi_result (phi)); | |
486 } | |
487 | |
488 /* Remove all the phi nodes from BB. */ | |
489 | |
490 void | |
491 remove_phi_nodes (basic_block bb) | |
492 { | |
493 gimple_stmt_iterator gsi; | |
494 | |
495 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); ) | |
496 remove_phi_node (&gsi, true); | |
497 | |
498 set_phi_nodes (bb, NULL); | |
499 } | |
500 | |
501 #include "gt-tree-phinodes.h" |