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