]>
Commit | Line | Data |
---|---|---|
6de9cd9a | 1 | /* Generic routines for manipulating PHIs |
8d9254fc | 2 | Copyright (C) 2003-2020 Free Software Foundation, Inc. |
50d895a7 | 3 | |
6de9cd9a | 4 | This file is part of GCC. |
50d895a7 | 5 | |
6de9cd9a DN |
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 | |
9dcd6f09 | 8 | the Free Software Foundation; either version 3, or (at your option) |
6de9cd9a | 9 | any later version. |
50d895a7 | 10 | |
6de9cd9a DN |
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. | |
50d895a7 | 15 | |
6de9cd9a | 16 | You should have received a copy of the GNU General Public License |
9dcd6f09 NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
50d895a7 | 19 | |
6de9cd9a DN |
20 | #include "config.h" |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
c7131fb2 | 23 | #include "backend.h" |
40e23961 | 24 | #include "tree.h" |
c7131fb2 | 25 | #include "gimple.h" |
c7131fb2 | 26 | #include "ssa.h" |
c7131fb2 | 27 | #include "fold-const.h" |
5be5c238 | 28 | #include "gimple-iterator.h" |
7a300452 | 29 | #include "tree-ssa.h" |
6de9cd9a DN |
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 | |
50d895a7 | 33 | were threaded through PHI nodes. |
6de9cd9a DN |
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 | ||
6de9cd9a DN |
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 | |
50d895a7 | 64 | than .1% additional reusable PHI nodes. |
6de9cd9a DN |
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 | |
355fe088 | 70 | static GTY ((deletable (""))) vec<gimple *, va_gc> *free_phinodes[NUM_BUCKETS - 2]; |
6de9cd9a DN |
71 | static unsigned long free_phinode_count; |
72 | ||
73 | static int ideal_phi_node_len (int); | |
6de9cd9a | 74 | |
6de9cd9a DN |
75 | unsigned int phi_nodes_reused; |
76 | unsigned int phi_nodes_created; | |
6de9cd9a | 77 | |
6de9cd9a DN |
78 | /* Dump some simple statistics regarding the re-use of PHI nodes. */ |
79 | ||
6de9cd9a DN |
80 | void |
81 | phinodes_print_statistics (void) | |
82 | { | |
60448173 | 83 | fprintf (stderr, "%-32s" PRsa (11) "\n", "PHI nodes allocated:", |
40ce7fa6 | 84 | SIZE_AMOUNT (phi_nodes_created)); |
60448173 | 85 | fprintf (stderr, "%-32s" PRsa (11) "\n", "PHI nodes reused:", |
a0b48080 | 86 | SIZE_AMOUNT (phi_nodes_reused)); |
6de9cd9a | 87 | } |
6de9cd9a | 88 | |
8c3babed KH |
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 | ||
538dd0b7 | 93 | static inline gphi * |
726a989a | 94 | allocate_phi_node (size_t len) |
8c3babed | 95 | { |
538dd0b7 | 96 | gphi *phi; |
726a989a | 97 | size_t bucket = NUM_BUCKETS - 2; |
538dd0b7 | 98 | size_t size = sizeof (struct gphi) |
726a989a | 99 | + (len - 1) * sizeof (struct phi_arg_d); |
8c3babed KH |
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 | |
9771b263 | 108 | && gimple_phi_capacity ((*free_phinodes[bucket])[0]) >= len) |
8c3babed KH |
109 | { |
110 | free_phinode_count--; | |
538dd0b7 | 111 | phi = as_a <gphi *> (free_phinodes[bucket]->pop ()); |
9771b263 DN |
112 | if (free_phinodes[bucket]->is_empty ()) |
113 | vec_free (free_phinodes[bucket]); | |
7aa6d18a SB |
114 | if (GATHER_STATISTICS) |
115 | phi_nodes_reused++; | |
8c3babed KH |
116 | } |
117 | else | |
118 | { | |
538dd0b7 | 119 | phi = static_cast <gphi *> (ggc_internal_alloc (size)); |
7aa6d18a | 120 | if (GATHER_STATISTICS) |
726a989a RB |
121 | { |
122 | enum gimple_alloc_kind kind = gimple_alloc_kind (GIMPLE_PHI); | |
7aa6d18a SB |
123 | phi_nodes_created++; |
124 | gimple_alloc_counts[(int) kind]++; | |
125 | gimple_alloc_sizes[(int) kind] += size; | |
726a989a | 126 | } |
8c3babed KH |
127 | } |
128 | ||
129 | return phi; | |
130 | } | |
131 | ||
6de9cd9a DN |
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. */ | |
538dd0b7 | 153 | size = sizeof (struct gphi) |
726a989a | 154 | + (len - 1) * sizeof (struct phi_arg_d); |
6de9cd9a DN |
155 | |
156 | /* Round it up to the next power of two. */ | |
157 | log2 = ceil_log2 (size); | |
158 | new_size = 1 << log2; | |
50d895a7 KH |
159 | |
160 | /* Now compute and return the number of PHI argument slots given an | |
6de9cd9a DN |
161 | ideal size allocation. */ |
162 | new_len = len + (new_size - size) / sizeof (struct phi_arg_d); | |
163 | return new_len; | |
164 | } | |
165 | ||
0bca51f0 | 166 | /* Return a PHI node with LEN argument slots for variable VAR. */ |
6de9cd9a | 167 | |
538dd0b7 | 168 | static gphi * |
6de9cd9a DN |
169 | make_phi_node (tree var, int len) |
170 | { | |
538dd0b7 | 171 | gphi *phi; |
f430bae8 | 172 | int capacity, i; |
6de9cd9a | 173 | |
405f403a | 174 | capacity = ideal_phi_node_len (len); |
6de9cd9a | 175 | |
405f403a | 176 | phi = allocate_phi_node (capacity); |
6de9cd9a | 177 | |
6b66c718 KH |
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. */ | |
538dd0b7 | 181 | memset (phi, 0, (sizeof (struct gphi) |
726a989a | 182 | - sizeof (struct phi_arg_d) |
6b66c718 | 183 | + sizeof (struct phi_arg_d) * len)); |
daa6e488 | 184 | phi->code = GIMPLE_PHI; |
355a7673 | 185 | gimple_init_singleton (phi); |
daa6e488 DM |
186 | phi->nargs = len; |
187 | phi->capacity = capacity; | |
dcc748dd RG |
188 | if (!var) |
189 | ; | |
190 | else if (TREE_CODE (var) == SSA_NAME) | |
726a989a | 191 | gimple_phi_set_result (phi, var); |
6de9cd9a | 192 | else |
726a989a | 193 | gimple_phi_set_result (phi, make_ssa_name (var, phi)); |
6de9cd9a | 194 | |
3fa4fad4 | 195 | for (i = 0; i < len; i++) |
f430bae8 | 196 | { |
f47c96aa | 197 | use_operand_p imm; |
f5045c96 AM |
198 | |
199 | gimple_phi_arg_set_location (phi, i, UNKNOWN_LOCATION); | |
726a989a RB |
200 | imm = gimple_phi_arg_imm_use_ptr (phi, i); |
201 | imm->use = gimple_phi_arg_def_ptr (phi, i); | |
f430bae8 AM |
202 | imm->prev = NULL; |
203 | imm->next = NULL; | |
726a989a | 204 | imm->loc.stmt = phi; |
f430bae8 | 205 | } |
9b3b55a1 | 206 | |
6de9cd9a DN |
207 | return phi; |
208 | } | |
209 | ||
210 | /* We no longer need PHI, release it so that it may be reused. */ | |
211 | ||
eeead3a6 | 212 | static void |
355fe088 | 213 | release_phi_node (gimple *phi) |
6de9cd9a | 214 | { |
726a989a RB |
215 | size_t bucket; |
216 | size_t len = gimple_phi_capacity (phi); | |
217 | size_t x; | |
f430bae8 | 218 | |
726a989a | 219 | for (x = 0; x < gimple_phi_num_args (phi); x++) |
f430bae8 | 220 | { |
f47c96aa | 221 | use_operand_p imm; |
726a989a | 222 | imm = gimple_phi_arg_imm_use_ptr (phi, x); |
f430bae8 AM |
223 | delink_imm_use (imm); |
224 | } | |
6de9cd9a DN |
225 | |
226 | bucket = len > NUM_BUCKETS - 1 ? NUM_BUCKETS - 1 : len; | |
227 | bucket -= 2; | |
9771b263 | 228 | vec_safe_push (free_phinodes[bucket], phi); |
6de9cd9a DN |
229 | free_phinode_count++; |
230 | } | |
231 | ||
726a989a | 232 | |
6de9cd9a DN |
233 | /* Resize an existing PHI node. The only way is up. Return the |
234 | possibly relocated phi. */ | |
50d895a7 | 235 | |
538dd0b7 DM |
236 | static gphi * |
237 | resize_phi_node (gphi *phi, size_t len) | |
6de9cd9a | 238 | { |
726a989a | 239 | size_t old_size, i; |
538dd0b7 | 240 | gphi *new_phi; |
1e128c5f | 241 | |
355a7673 | 242 | gcc_assert (len > gimple_phi_capacity (phi)); |
1e128c5f | 243 | |
57f60923 KH |
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. */ | |
538dd0b7 | 247 | old_size = sizeof (struct gphi) |
355a7673 | 248 | + (gimple_phi_num_args (phi) - 1) * sizeof (struct phi_arg_d); |
6de9cd9a | 249 | |
8c3babed | 250 | new_phi = allocate_phi_node (len); |
6de9cd9a | 251 | |
355a7673 | 252 | memcpy (new_phi, phi, old_size); |
3fa4fad4 RB |
253 | memset ((char *)new_phi + old_size, 0, |
254 | (sizeof (struct gphi) | |
255 | - sizeof (struct phi_arg_d) | |
256 | + sizeof (struct phi_arg_d) * len) - old_size); | |
6de9cd9a | 257 | |
726a989a | 258 | for (i = 0; i < gimple_phi_num_args (new_phi); i++) |
f430bae8 | 259 | { |
f47c96aa | 260 | use_operand_p imm, old_imm; |
726a989a | 261 | imm = gimple_phi_arg_imm_use_ptr (new_phi, i); |
355a7673 | 262 | old_imm = gimple_phi_arg_imm_use_ptr (phi, i); |
726a989a | 263 | imm->use = gimple_phi_arg_def_ptr (new_phi, i); |
f430bae8 AM |
264 | relink_imm_use_stmt (imm, old_imm, new_phi); |
265 | } | |
266 | ||
daa6e488 | 267 | new_phi->capacity = len; |
50d895a7 | 268 | |
355a7673 | 269 | return new_phi; |
6de9cd9a DN |
270 | } |
271 | ||
a100ac1e KH |
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 | { | |
726a989a RB |
277 | size_t len = EDGE_COUNT (bb->preds); |
278 | size_t cap = ideal_phi_node_len (len + 4); | |
538dd0b7 | 279 | gphi_iterator gsi; |
a100ac1e | 280 | |
726a989a | 281 | for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
a100ac1e | 282 | { |
538dd0b7 | 283 | gphi *stmt = gsi.phi (); |
726a989a | 284 | |
355a7673 | 285 | if (len > gimple_phi_capacity (stmt)) |
a100ac1e | 286 | { |
538dd0b7 | 287 | gphi *new_phi = resize_phi_node (stmt, cap); |
a100ac1e | 288 | |
726a989a | 289 | /* The result of the PHI is defined by this PHI node. */ |
355a7673 MM |
290 | SSA_NAME_DEF_STMT (gimple_phi_result (new_phi)) = new_phi; |
291 | gsi_set_stmt (&gsi, new_phi); | |
a100ac1e | 292 | |
355a7673 MM |
293 | release_phi_node (stmt); |
294 | stmt = new_phi; | |
a100ac1e | 295 | } |
6b66c718 | 296 | |
3fa4fad4 RB |
297 | stmt->nargs++; |
298 | ||
6b66c718 KH |
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. */ | |
3fa4fad4 RB |
306 | use_operand_p imm = gimple_phi_arg_imm_use_ptr (stmt, len - 1); |
307 | imm->use = gimple_phi_arg_def_ptr (stmt, len - 1); | |
308 | imm->prev = NULL; | |
309 | imm->next = NULL; | |
310 | imm->loc.stmt = stmt; | |
355a7673 | 311 | SET_PHI_ARG_DEF (stmt, len - 1, NULL_TREE); |
e300ec2d | 312 | gimple_phi_arg_set_location (stmt, len - 1, UNKNOWN_LOCATION); |
a100ac1e KH |
313 | } |
314 | } | |
315 | ||
f8bf9252 | 316 | /* Adds PHI to BB. */ |
9b3b55a1 | 317 | |
b8698a0f | 318 | void |
538dd0b7 | 319 | add_phi_node_to_bb (gphi *phi, basic_block bb) |
6de9cd9a | 320 | { |
355a7673 | 321 | gimple_seq seq = phi_nodes (bb); |
6de9cd9a | 322 | /* Add the new PHI node to the list of PHI nodes for block BB. */ |
355a7673 MM |
323 | if (seq == NULL) |
324 | set_phi_nodes (bb, gimple_seq_alloc_with_stmt (phi)); | |
325 | else | |
326 | { | |
327 | gimple_seq_add_stmt (&seq, phi); | |
328 | gcc_assert (seq == phi_nodes (bb)); | |
329 | } | |
6de9cd9a DN |
330 | |
331 | /* Associate BB to the PHI node. */ | |
726a989a | 332 | gimple_set_bb (phi, bb); |
6de9cd9a | 333 | |
f8bf9252 SP |
334 | } |
335 | ||
336 | /* Create a new PHI node for variable VAR at basic block BB. */ | |
337 | ||
538dd0b7 | 338 | gphi * |
f8bf9252 SP |
339 | create_phi_node (tree var, basic_block bb) |
340 | { | |
538dd0b7 | 341 | gphi *phi = make_phi_node (var, EDGE_COUNT (bb->preds)); |
f8bf9252 SP |
342 | |
343 | add_phi_node_to_bb (phi, bb); | |
6de9cd9a DN |
344 | return phi; |
345 | } | |
346 | ||
9b3b55a1 | 347 | |
6de9cd9a DN |
348 | /* Add a new argument to PHI node PHI. DEF is the incoming reaching |
349 | definition and E is the edge through which DEF reaches PHI. The new | |
350 | argument is added at the end of the argument list. | |
351 | If PHI has reached its maximum capacity, add a few slots. In this case, | |
352 | PHI points to the reallocated phi node when we return. */ | |
353 | ||
354 | void | |
620e594b | 355 | add_phi_arg (gphi *phi, tree def, edge e, location_t locus) |
6de9cd9a | 356 | { |
bc2dce32 | 357 | basic_block bb = e->dest; |
6de9cd9a | 358 | |
726a989a | 359 | gcc_assert (bb == gimple_bb (phi)); |
bc2dce32 | 360 | |
a100ac1e KH |
361 | /* We resize PHI nodes upon edge creation. We should always have |
362 | enough room at this point. */ | |
726a989a | 363 | gcc_assert (gimple_phi_num_args (phi) <= gimple_phi_capacity (phi)); |
6b66c718 KH |
364 | |
365 | /* We resize PHI nodes upon edge creation. We should always have | |
366 | enough room at this point. */ | |
726a989a | 367 | gcc_assert (e->dest_idx < gimple_phi_num_args (phi)); |
6de9cd9a DN |
368 | |
369 | /* Copy propagation needs to know what object occur in abnormal | |
370 | PHI nodes. This is a convenient place to record such information. */ | |
371 | if (e->flags & EDGE_ABNORMAL) | |
372 | { | |
373 | SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def) = 1; | |
d2e398df | 374 | SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)) = 1; |
6de9cd9a DN |
375 | } |
376 | ||
d2e398df | 377 | SET_PHI_ARG_DEF (phi, e->dest_idx, def); |
f5045c96 | 378 | gimple_phi_arg_set_location (phi, e->dest_idx, locus); |
6de9cd9a DN |
379 | } |
380 | ||
9b3b55a1 | 381 | |
8930ce20 KH |
382 | /* Remove the Ith argument from PHI's argument list. This routine |
383 | implements removal by swapping the last alternative with the | |
384 | alternative we want to delete and then shrinking the vector, which | |
385 | is consistent with how we remove an edge from the edge vector. */ | |
6de9cd9a | 386 | |
61ea20f5 | 387 | static void |
538dd0b7 | 388 | remove_phi_arg_num (gphi *phi, int i) |
6de9cd9a | 389 | { |
726a989a | 390 | int num_elem = gimple_phi_num_args (phi); |
6de9cd9a | 391 | |
40b554a3 SB |
392 | gcc_assert (i < num_elem); |
393 | ||
afd83fe4 | 394 | /* Delink the item which is being removed. */ |
726a989a | 395 | delink_imm_use (gimple_phi_arg_imm_use_ptr (phi, i)); |
afd83fe4 AM |
396 | |
397 | /* If it is not the last element, move the last element | |
398 | to the element we want to delete, resetting all the links. */ | |
6de9cd9a DN |
399 | if (i != num_elem - 1) |
400 | { | |
afd83fe4 | 401 | use_operand_p old_p, new_p; |
726a989a RB |
402 | old_p = gimple_phi_arg_imm_use_ptr (phi, num_elem - 1); |
403 | new_p = gimple_phi_arg_imm_use_ptr (phi, i); | |
bca50406 | 404 | /* Set use on new node, and link into last element's place. */ |
afd83fe4 AM |
405 | *(new_p->use) = *(old_p->use); |
406 | relink_imm_use (new_p, old_p); | |
f5045c96 | 407 | /* Move the location as well. */ |
b8698a0f | 408 | gimple_phi_arg_set_location (phi, i, |
f5045c96 | 409 | gimple_phi_arg_location (phi, num_elem - 1)); |
6de9cd9a DN |
410 | } |
411 | ||
54699c02 | 412 | /* Shrink the vector and return. Note that we do not have to clear |
357e7a82 JL |
413 | PHI_ARG_DEF because the garbage collector will not look at those |
414 | elements beyond the first PHI_NUM_ARGS elements of the array. */ | |
daa6e488 | 415 | phi->nargs--; |
6de9cd9a DN |
416 | } |
417 | ||
9b3b55a1 | 418 | |
b31997c0 KH |
419 | /* Remove all PHI arguments associated with edge E. */ |
420 | ||
421 | void | |
422 | remove_phi_args (edge e) | |
423 | { | |
538dd0b7 | 424 | gphi_iterator gsi; |
b31997c0 | 425 | |
726a989a | 426 | for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi)) |
538dd0b7 | 427 | remove_phi_arg_num (gsi.phi (), |
daa6e488 | 428 | e->dest_idx); |
b31997c0 KH |
429 | } |
430 | ||
9b3b55a1 | 431 | |
726a989a RB |
432 | /* Remove the PHI node pointed-to by iterator GSI from basic block BB. After |
433 | removal, iterator GSI is updated to point to the next PHI node in the | |
434 | sequence. If RELEASE_LHS_P is true, the LHS of this PHI node is released | |
435 | into the free pool of SSA names. */ | |
6de9cd9a DN |
436 | |
437 | void | |
726a989a | 438 | remove_phi_node (gimple_stmt_iterator *gsi, bool release_lhs_p) |
6de9cd9a | 439 | { |
355fe088 | 440 | gimple *phi = gsi_stmt (*gsi); |
cd6549e8 AO |
441 | |
442 | if (release_lhs_p) | |
443 | insert_debug_temps_for_defs (gsi); | |
444 | ||
726a989a | 445 | gsi_remove (gsi, false); |
4430da7f KH |
446 | |
447 | /* If we are deleting the PHI node, then we should release the | |
448 | SSA_NAME node so that it can be reused. */ | |
4430da7f | 449 | release_phi_node (phi); |
9b3b55a1 | 450 | if (release_lhs_p) |
726a989a | 451 | release_ssa_name (gimple_phi_result (phi)); |
5ae71719 | 452 | } |
6de9cd9a | 453 | |
81b822d5 SP |
454 | /* Remove all the phi nodes from BB. */ |
455 | ||
456 | void | |
457 | remove_phi_nodes (basic_block bb) | |
458 | { | |
538dd0b7 | 459 | gphi_iterator gsi; |
81b822d5 SP |
460 | |
461 | for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); ) | |
462 | remove_phi_node (&gsi, true); | |
463 | ||
464 | set_phi_nodes (bb, NULL); | |
465 | } | |
466 | ||
4484a35a AM |
467 | /* Given PHI, return its RHS if the PHI is a degenerate, otherwise return |
468 | NULL. */ | |
469 | ||
470 | tree | |
538dd0b7 | 471 | degenerate_phi_result (gphi *phi) |
4484a35a AM |
472 | { |
473 | tree lhs = gimple_phi_result (phi); | |
474 | tree val = NULL; | |
475 | size_t i; | |
476 | ||
477 | /* Ignoring arguments which are the same as LHS, if all the remaining | |
478 | arguments are the same, then the PHI is a degenerate and has the | |
479 | value of that common argument. */ | |
480 | for (i = 0; i < gimple_phi_num_args (phi); i++) | |
481 | { | |
482 | tree arg = gimple_phi_arg_def (phi, i); | |
483 | ||
484 | if (arg == lhs) | |
485 | continue; | |
486 | else if (!arg) | |
487 | break; | |
488 | else if (!val) | |
489 | val = arg; | |
490 | else if (arg == val) | |
491 | continue; | |
492 | /* We bring in some of operand_equal_p not only to speed things | |
493 | up, but also to avoid crashing when dereferencing the type of | |
494 | a released SSA name. */ | |
495 | else if (TREE_CODE (val) != TREE_CODE (arg) | |
496 | || TREE_CODE (val) == SSA_NAME | |
497 | || !operand_equal_p (arg, val, 0)) | |
498 | break; | |
499 | } | |
500 | return (i == gimple_phi_num_args (phi) ? val : NULL); | |
501 | } | |
502 | ||
5be5c238 AM |
503 | /* Set PHI nodes of a basic block BB to SEQ. */ |
504 | ||
505 | void | |
506 | set_phi_nodes (basic_block bb, gimple_seq seq) | |
507 | { | |
508 | gimple_stmt_iterator i; | |
509 | ||
510 | gcc_checking_assert (!(bb->flags & BB_RTL)); | |
511 | bb->il.gimple.phi_nodes = seq; | |
512 | if (seq) | |
513 | for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i)) | |
514 | gimple_set_bb (gsi_stmt (i), bb); | |
515 | } | |
4484a35a | 516 | |
6de9cd9a | 517 | #include "gt-tree-phinodes.h" |