]>
Commit | Line | Data |
---|---|---|
6de9cd9a | 1 | /* Inline functions for tree-flow.h |
f93089d2 | 2 | Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. |
6de9cd9a DN |
3 | Contributed by Diego Novillo <dnovillo@redhat.com> |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING. If not, write to | |
366ccddb KC |
19 | the Free Software Foundation, 51 Franklin Street, Fifth Floor, |
20 | Boston, MA 02110-1301, USA. */ | |
6de9cd9a DN |
21 | |
22 | #ifndef _TREE_FLOW_INLINE_H | |
23 | #define _TREE_FLOW_INLINE_H 1 | |
24 | ||
25 | /* Inline functions for manipulating various data structures defined in | |
26 | tree-flow.h. See tree-flow.h for documentation. */ | |
27 | ||
a3648cfc DB |
28 | /* Initialize the hashtable iterator HTI to point to hashtable TABLE */ |
29 | ||
30 | static inline void * | |
31 | first_htab_element (htab_iterator *hti, htab_t table) | |
32 | { | |
33 | hti->htab = table; | |
34 | hti->slot = table->entries; | |
35 | hti->limit = hti->slot + htab_size (table); | |
36 | do | |
37 | { | |
38 | PTR x = *(hti->slot); | |
39 | if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY) | |
40 | break; | |
41 | } while (++(hti->slot) < hti->limit); | |
42 | ||
43 | if (hti->slot < hti->limit) | |
44 | return *(hti->slot); | |
45 | return NULL; | |
46 | } | |
47 | ||
48 | /* Return current non-empty/deleted slot of the hashtable pointed to by HTI, | |
49 | or NULL if we have reached the end. */ | |
50 | ||
51 | static inline bool | |
52 | end_htab_p (htab_iterator *hti) | |
53 | { | |
54 | if (hti->slot >= hti->limit) | |
55 | return true; | |
56 | return false; | |
57 | } | |
58 | ||
206048bd | 59 | /* Advance the hashtable iterator pointed to by HTI to the next element of the |
a3648cfc DB |
60 | hashtable. */ |
61 | ||
62 | static inline void * | |
63 | next_htab_element (htab_iterator *hti) | |
64 | { | |
65 | while (++(hti->slot) < hti->limit) | |
66 | { | |
67 | PTR x = *(hti->slot); | |
68 | if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY) | |
69 | return x; | |
70 | }; | |
71 | return NULL; | |
72 | } | |
73 | ||
74 | /* Initialize ITER to point to the first referenced variable in the | |
75 | referenced_vars hashtable, and return that variable. */ | |
76 | ||
77 | static inline tree | |
78 | first_referenced_var (referenced_var_iterator *iter) | |
79 | { | |
80 | struct int_tree_map *itm; | |
81 | itm = first_htab_element (&iter->hti, referenced_vars); | |
82 | if (!itm) | |
83 | return NULL; | |
84 | return itm->to; | |
85 | } | |
86 | ||
87 | /* Return true if we have hit the end of the referenced variables ITER is | |
88 | iterating through. */ | |
89 | ||
90 | static inline bool | |
91 | end_referenced_vars_p (referenced_var_iterator *iter) | |
92 | { | |
93 | return end_htab_p (&iter->hti); | |
94 | } | |
95 | ||
96 | /* Make ITER point to the next referenced_var in the referenced_var hashtable, | |
97 | and return that variable. */ | |
98 | ||
99 | static inline tree | |
100 | next_referenced_var (referenced_var_iterator *iter) | |
101 | { | |
102 | struct int_tree_map *itm; | |
103 | itm = next_htab_element (&iter->hti); | |
104 | if (!itm) | |
105 | return NULL; | |
106 | return itm->to; | |
107 | } | |
b9d33488 DB |
108 | |
109 | /* Fill up VEC with the variables in the referenced vars hashtable. */ | |
110 | ||
111 | static inline void | |
112 | fill_referenced_var_vec (VEC (tree, heap) **vec) | |
113 | { | |
114 | referenced_var_iterator rvi; | |
115 | tree var; | |
116 | *vec = NULL; | |
117 | FOR_EACH_REFERENCED_VAR (var, rvi) | |
118 | VEC_safe_push (tree, heap, *vec, var); | |
119 | } | |
120 | ||
0566b51e DB |
121 | /* Return the variable annotation for T, which must be a _DECL node. |
122 | Return NULL if the variable annotation doesn't already exist. */ | |
6de9cd9a DN |
123 | static inline var_ann_t |
124 | var_ann (tree t) | |
125 | { | |
1e128c5f GB |
126 | gcc_assert (t); |
127 | gcc_assert (DECL_P (t)); | |
128 | gcc_assert (!t->common.ann || t->common.ann->common.type == VAR_ANN); | |
6de9cd9a DN |
129 | |
130 | return (var_ann_t) t->common.ann; | |
131 | } | |
132 | ||
0566b51e DB |
133 | /* Return the variable annotation for T, which must be a _DECL node. |
134 | Create the variable annotation if it doesn't exist. */ | |
6de9cd9a DN |
135 | static inline var_ann_t |
136 | get_var_ann (tree var) | |
137 | { | |
138 | var_ann_t ann = var_ann (var); | |
139 | return (ann) ? ann : create_var_ann (var); | |
140 | } | |
141 | ||
0566b51e DB |
142 | /* Return the statement annotation for T, which must be a statement |
143 | node. Return NULL if the statement annotation doesn't exist. */ | |
6de9cd9a DN |
144 | static inline stmt_ann_t |
145 | stmt_ann (tree t) | |
146 | { | |
1e128c5f GB |
147 | #ifdef ENABLE_CHECKING |
148 | gcc_assert (is_gimple_stmt (t)); | |
6de9cd9a | 149 | #endif |
6de9cd9a DN |
150 | return (stmt_ann_t) t->common.ann; |
151 | } | |
152 | ||
0566b51e DB |
153 | /* Return the statement annotation for T, which must be a statement |
154 | node. Create the statement annotation if it doesn't exist. */ | |
6de9cd9a DN |
155 | static inline stmt_ann_t |
156 | get_stmt_ann (tree stmt) | |
157 | { | |
158 | stmt_ann_t ann = stmt_ann (stmt); | |
159 | return (ann) ? ann : create_stmt_ann (stmt); | |
160 | } | |
161 | ||
0566b51e | 162 | /* Return the annotation type for annotation ANN. */ |
6de9cd9a | 163 | static inline enum tree_ann_type |
06d72ee6 | 164 | ann_type (tree_ann_t ann) |
6de9cd9a DN |
165 | { |
166 | return ann->common.type; | |
167 | } | |
168 | ||
0566b51e | 169 | /* Return the basic block for statement T. */ |
6de9cd9a DN |
170 | static inline basic_block |
171 | bb_for_stmt (tree t) | |
172 | { | |
30d396e3 ZD |
173 | stmt_ann_t ann; |
174 | ||
175 | if (TREE_CODE (t) == PHI_NODE) | |
176 | return PHI_BB (t); | |
177 | ||
178 | ann = stmt_ann (t); | |
6de9cd9a DN |
179 | return ann ? ann->bb : NULL; |
180 | } | |
181 | ||
0566b51e DB |
182 | /* Return the may_aliases varray for variable VAR, or NULL if it has |
183 | no may aliases. */ | |
6de9cd9a DN |
184 | static inline varray_type |
185 | may_aliases (tree var) | |
186 | { | |
187 | var_ann_t ann = var_ann (var); | |
188 | return ann ? ann->may_aliases : NULL; | |
189 | } | |
190 | ||
0566b51e DB |
191 | /* Return the line number for EXPR, or return -1 if we have no line |
192 | number information for it. */ | |
6de9cd9a DN |
193 | static inline int |
194 | get_lineno (tree expr) | |
195 | { | |
196 | if (expr == NULL_TREE) | |
197 | return -1; | |
198 | ||
199 | if (TREE_CODE (expr) == COMPOUND_EXPR) | |
200 | expr = TREE_OPERAND (expr, 0); | |
201 | ||
9506ac2b | 202 | if (! EXPR_HAS_LOCATION (expr)) |
6de9cd9a DN |
203 | return -1; |
204 | ||
205 | return EXPR_LINENO (expr); | |
206 | } | |
207 | ||
0566b51e DB |
208 | /* Return the file name for EXPR, or return "???" if we have no |
209 | filename information. */ | |
6de9cd9a DN |
210 | static inline const char * |
211 | get_filename (tree expr) | |
212 | { | |
9506ac2b | 213 | const char *filename; |
6de9cd9a DN |
214 | if (expr == NULL_TREE) |
215 | return "???"; | |
216 | ||
217 | if (TREE_CODE (expr) == COMPOUND_EXPR) | |
218 | expr = TREE_OPERAND (expr, 0); | |
219 | ||
9506ac2b PB |
220 | if (EXPR_HAS_LOCATION (expr) && (filename = EXPR_FILENAME (expr))) |
221 | return filename; | |
6de9cd9a DN |
222 | else |
223 | return "???"; | |
224 | } | |
225 | ||
7ded35b4 RS |
226 | /* Return true if T is a noreturn call. */ |
227 | static inline bool | |
228 | noreturn_call_p (tree t) | |
229 | { | |
230 | tree call = get_call_expr_in (t); | |
231 | return call != 0 && (call_expr_flags (call) & ECF_NORETURN) != 0; | |
232 | } | |
233 | ||
0566b51e | 234 | /* Mark statement T as modified. */ |
6de9cd9a | 235 | static inline void |
f430bae8 | 236 | mark_stmt_modified (tree t) |
6de9cd9a | 237 | { |
f430bae8 AM |
238 | stmt_ann_t ann; |
239 | if (TREE_CODE (t) == PHI_NODE) | |
240 | return; | |
241 | ||
242 | ann = stmt_ann (t); | |
6de9cd9a DN |
243 | if (ann == NULL) |
244 | ann = create_stmt_ann (t); | |
7ded35b4 | 245 | else if (noreturn_call_p (t)) |
d4e6fecb | 246 | VEC_safe_push (tree, gc, modified_noreturn_calls, t); |
6de9cd9a DN |
247 | ann->modified = 1; |
248 | } | |
249 | ||
f430bae8 | 250 | /* Mark statement T as modified, and update it. */ |
6de9cd9a | 251 | static inline void |
f430bae8 | 252 | update_stmt (tree t) |
6de9cd9a | 253 | { |
f430bae8 AM |
254 | if (TREE_CODE (t) == PHI_NODE) |
255 | return; | |
256 | mark_stmt_modified (t); | |
257 | update_stmt_operands (t); | |
258 | } | |
259 | ||
260 | static inline void | |
261 | update_stmt_if_modified (tree t) | |
262 | { | |
263 | if (stmt_modified_p (t)) | |
264 | update_stmt_operands (t); | |
265 | } | |
266 | ||
0566b51e | 267 | /* Return true if T is marked as modified, false otherwise. */ |
6de9cd9a DN |
268 | static inline bool |
269 | stmt_modified_p (tree t) | |
270 | { | |
271 | stmt_ann_t ann = stmt_ann (t); | |
272 | ||
273 | /* Note that if the statement doesn't yet have an annotation, we consider it | |
f430bae8 AM |
274 | modified. This will force the next call to update_stmt_operands to scan |
275 | the statement. */ | |
6de9cd9a DN |
276 | return ann ? ann->modified : true; |
277 | } | |
278 | ||
f430bae8 AM |
279 | /* Delink an immediate_uses node from its chain. */ |
280 | static inline void | |
f47c96aa | 281 | delink_imm_use (ssa_use_operand_t *linknode) |
f430bae8 AM |
282 | { |
283 | /* Return if this node is not in a list. */ | |
284 | if (linknode->prev == NULL) | |
285 | return; | |
286 | ||
287 | linknode->prev->next = linknode->next; | |
288 | linknode->next->prev = linknode->prev; | |
289 | linknode->prev = NULL; | |
290 | linknode->next = NULL; | |
291 | } | |
292 | ||
293 | /* Link ssa_imm_use node LINKNODE into the chain for LIST. */ | |
294 | static inline void | |
f47c96aa | 295 | link_imm_use_to_list (ssa_use_operand_t *linknode, ssa_use_operand_t *list) |
f430bae8 AM |
296 | { |
297 | /* Link the new node at the head of the list. If we are in the process of | |
be12e697 | 298 | traversing the list, we won't visit any new nodes added to it. */ |
f430bae8 AM |
299 | linknode->prev = list; |
300 | linknode->next = list->next; | |
301 | list->next->prev = linknode; | |
302 | list->next = linknode; | |
303 | } | |
304 | ||
305 | /* Link ssa_imm_use node LINKNODE into the chain for DEF. */ | |
306 | static inline void | |
f47c96aa | 307 | link_imm_use (ssa_use_operand_t *linknode, tree def) |
f430bae8 | 308 | { |
f47c96aa | 309 | ssa_use_operand_t *root; |
f430bae8 AM |
310 | |
311 | if (!def || TREE_CODE (def) != SSA_NAME) | |
312 | linknode->prev = NULL; | |
313 | else | |
314 | { | |
315 | root = &(SSA_NAME_IMM_USE_NODE (def)); | |
316 | #ifdef ENABLE_CHECKING | |
317 | if (linknode->use) | |
318 | gcc_assert (*(linknode->use) == def); | |
319 | #endif | |
320 | link_imm_use_to_list (linknode, root); | |
321 | } | |
322 | } | |
323 | ||
206048bd | 324 | /* Set the value of a use pointed to by USE to VAL. */ |
f430bae8 AM |
325 | static inline void |
326 | set_ssa_use_from_ptr (use_operand_p use, tree val) | |
327 | { | |
328 | delink_imm_use (use); | |
329 | *(use->use) = val; | |
330 | link_imm_use (use, val); | |
331 | } | |
332 | ||
0fa2e4df | 333 | /* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occurring |
f430bae8 AM |
334 | in STMT. */ |
335 | static inline void | |
f47c96aa | 336 | link_imm_use_stmt (ssa_use_operand_t *linknode, tree def, tree stmt) |
f430bae8 AM |
337 | { |
338 | if (stmt) | |
339 | link_imm_use (linknode, def); | |
340 | else | |
341 | link_imm_use (linknode, NULL); | |
342 | linknode->stmt = stmt; | |
343 | } | |
344 | ||
345 | /* Relink a new node in place of an old node in the list. */ | |
346 | static inline void | |
f47c96aa | 347 | relink_imm_use (ssa_use_operand_t *node, ssa_use_operand_t *old) |
f430bae8 | 348 | { |
f430bae8 | 349 | /* The node one had better be in the same list. */ |
0e61db61 | 350 | gcc_assert (*(old->use) == *(node->use)); |
f430bae8 AM |
351 | node->prev = old->prev; |
352 | node->next = old->next; | |
353 | if (old->prev) | |
354 | { | |
355 | old->prev->next = node; | |
356 | old->next->prev = node; | |
357 | /* Remove the old node from the list. */ | |
358 | old->prev = NULL; | |
359 | } | |
f430bae8 AM |
360 | } |
361 | ||
0fa2e4df | 362 | /* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occurring |
f430bae8 AM |
363 | in STMT. */ |
364 | static inline void | |
f47c96aa | 365 | relink_imm_use_stmt (ssa_use_operand_t *linknode, ssa_use_operand_t *old, tree stmt) |
f430bae8 AM |
366 | { |
367 | if (stmt) | |
368 | relink_imm_use (linknode, old); | |
369 | else | |
370 | link_imm_use (linknode, NULL); | |
371 | linknode->stmt = stmt; | |
372 | } | |
373 | ||
374 | /* Finished the traverse of an immediate use list IMM by removing it from | |
375 | the list. */ | |
376 | static inline void | |
377 | end_safe_imm_use_traverse (imm_use_iterator *imm) | |
378 | { | |
379 | delink_imm_use (&(imm->iter_node)); | |
380 | } | |
381 | ||
382 | /* Return true if IMM is at the end of the list. */ | |
383 | static inline bool | |
384 | end_safe_imm_use_p (imm_use_iterator *imm) | |
385 | { | |
386 | return (imm->imm_use == imm->end_p); | |
387 | } | |
388 | ||
389 | /* Initialize iterator IMM to process the list for VAR. */ | |
390 | static inline use_operand_p | |
391 | first_safe_imm_use (imm_use_iterator *imm, tree var) | |
392 | { | |
393 | /* Set up and link the iterator node into the linked list for VAR. */ | |
394 | imm->iter_node.use = NULL; | |
395 | imm->iter_node.stmt = NULL_TREE; | |
396 | imm->end_p = &(SSA_NAME_IMM_USE_NODE (var)); | |
397 | /* Check if there are 0 elements. */ | |
398 | if (imm->end_p->next == imm->end_p) | |
399 | { | |
400 | imm->imm_use = imm->end_p; | |
401 | return NULL_USE_OPERAND_P; | |
402 | } | |
403 | ||
404 | link_imm_use (&(imm->iter_node), var); | |
405 | imm->imm_use = imm->iter_node.next; | |
406 | return imm->imm_use; | |
407 | } | |
408 | ||
d566f6ef | 409 | /* Bump IMM to the next use in the list. */ |
f430bae8 AM |
410 | static inline use_operand_p |
411 | next_safe_imm_use (imm_use_iterator *imm) | |
412 | { | |
f47c96aa | 413 | ssa_use_operand_t *ptr; |
f430bae8 AM |
414 | use_operand_p old; |
415 | ||
416 | old = imm->imm_use; | |
f652d14b KH |
417 | /* If the next node following the iter_node is still the one referred to by |
418 | imm_use, then the list hasn't changed, go to the next node. */ | |
f430bae8 AM |
419 | if (imm->iter_node.next == imm->imm_use) |
420 | { | |
421 | ptr = &(imm->iter_node); | |
f652d14b | 422 | /* Remove iternode from the list. */ |
f430bae8 AM |
423 | delink_imm_use (ptr); |
424 | imm->imm_use = imm->imm_use->next; | |
425 | if (! end_safe_imm_use_p (imm)) | |
426 | { | |
d566f6ef | 427 | /* This isn't the end, link iternode before the next use. */ |
f430bae8 AM |
428 | ptr->prev = imm->imm_use->prev; |
429 | ptr->next = imm->imm_use; | |
430 | imm->imm_use->prev->next = ptr; | |
431 | imm->imm_use->prev = ptr; | |
432 | } | |
433 | else | |
434 | return old; | |
435 | } | |
436 | else | |
437 | { | |
438 | /* If the 'next' value after the iterator isn't the same as it was, then | |
f652d14b | 439 | a node has been deleted, so we simply proceed to the node following |
f430bae8 AM |
440 | where the iterator is in the list. */ |
441 | imm->imm_use = imm->iter_node.next; | |
442 | if (end_safe_imm_use_p (imm)) | |
443 | { | |
444 | end_safe_imm_use_traverse (imm); | |
445 | return old; | |
446 | } | |
447 | } | |
448 | ||
449 | return imm->imm_use; | |
450 | } | |
451 | ||
f652d14b | 452 | /* Return true is IMM has reached the end of the immediate use list. */ |
f430bae8 AM |
453 | static inline bool |
454 | end_readonly_imm_use_p (imm_use_iterator *imm) | |
455 | { | |
456 | return (imm->imm_use == imm->end_p); | |
457 | } | |
458 | ||
459 | /* Initialize iterator IMM to process the list for VAR. */ | |
460 | static inline use_operand_p | |
461 | first_readonly_imm_use (imm_use_iterator *imm, tree var) | |
462 | { | |
463 | gcc_assert (TREE_CODE (var) == SSA_NAME); | |
464 | ||
465 | imm->end_p = &(SSA_NAME_IMM_USE_NODE (var)); | |
466 | imm->imm_use = imm->end_p->next; | |
467 | #ifdef ENABLE_CHECKING | |
468 | imm->iter_node.next = imm->imm_use->next; | |
469 | #endif | |
470 | if (end_readonly_imm_use_p (imm)) | |
471 | return NULL_USE_OPERAND_P; | |
472 | return imm->imm_use; | |
473 | } | |
474 | ||
d566f6ef | 475 | /* Bump IMM to the next use in the list. */ |
f430bae8 AM |
476 | static inline use_operand_p |
477 | next_readonly_imm_use (imm_use_iterator *imm) | |
478 | { | |
479 | use_operand_p old = imm->imm_use; | |
480 | ||
481 | #ifdef ENABLE_CHECKING | |
482 | /* If this assertion fails, it indicates the 'next' pointer has changed | |
483 | since we the last bump. This indicates that the list is being modified | |
484 | via stmt changes, or SET_USE, or somesuch thing, and you need to be | |
485 | using the SAFE version of the iterator. */ | |
486 | gcc_assert (imm->iter_node.next == old->next); | |
487 | imm->iter_node.next = old->next->next; | |
488 | #endif | |
489 | ||
490 | imm->imm_use = old->next; | |
491 | if (end_readonly_imm_use_p (imm)) | |
492 | return old; | |
493 | return imm->imm_use; | |
494 | } | |
495 | ||
496 | /* Return true if VAR has no uses. */ | |
497 | static inline bool | |
498 | has_zero_uses (tree var) | |
499 | { | |
f47c96aa | 500 | ssa_use_operand_t *ptr; |
f430bae8 AM |
501 | ptr = &(SSA_NAME_IMM_USE_NODE (var)); |
502 | /* A single use means there is no items in the list. */ | |
503 | return (ptr == ptr->next); | |
504 | } | |
505 | ||
506 | /* Return true if VAR has a single use. */ | |
507 | static inline bool | |
508 | has_single_use (tree var) | |
509 | { | |
f47c96aa | 510 | ssa_use_operand_t *ptr; |
f430bae8 AM |
511 | ptr = &(SSA_NAME_IMM_USE_NODE (var)); |
512 | /* A single use means there is one item in the list. */ | |
513 | return (ptr != ptr->next && ptr == ptr->next->next); | |
514 | } | |
515 | ||
516 | /* If VAR has only a single immediate use, return true, and set USE_P and STMT | |
f652d14b | 517 | to the use pointer and stmt of occurrence. */ |
f430bae8 AM |
518 | static inline bool |
519 | single_imm_use (tree var, use_operand_p *use_p, tree *stmt) | |
520 | { | |
f47c96aa | 521 | ssa_use_operand_t *ptr; |
f430bae8 AM |
522 | |
523 | ptr = &(SSA_NAME_IMM_USE_NODE (var)); | |
524 | if (ptr != ptr->next && ptr == ptr->next->next) | |
525 | { | |
526 | *use_p = ptr->next; | |
527 | *stmt = ptr->next->stmt; | |
528 | return true; | |
529 | } | |
530 | *use_p = NULL_USE_OPERAND_P; | |
531 | *stmt = NULL_TREE; | |
532 | return false; | |
533 | } | |
534 | ||
535 | /* Return the number of immediate uses of VAR. */ | |
536 | static inline unsigned int | |
537 | num_imm_uses (tree var) | |
538 | { | |
f47c96aa | 539 | ssa_use_operand_t *ptr, *start; |
f430bae8 AM |
540 | unsigned int num; |
541 | ||
542 | start = &(SSA_NAME_IMM_USE_NODE (var)); | |
543 | num = 0; | |
544 | for (ptr = start->next; ptr != start; ptr = ptr->next) | |
545 | num++; | |
546 | ||
547 | return num; | |
548 | } | |
549 | ||
a32b97a2 | 550 | |
d00ad49b AM |
551 | /* Return the tree pointer to by USE. */ |
552 | static inline tree | |
553 | get_use_from_ptr (use_operand_p use) | |
554 | { | |
f430bae8 | 555 | return *(use->use); |
d00ad49b AM |
556 | } |
557 | ||
558 | /* Return the tree pointer to by DEF. */ | |
559 | static inline tree | |
560 | get_def_from_ptr (def_operand_p def) | |
561 | { | |
f47c96aa | 562 | return *def; |
d00ad49b AM |
563 | } |
564 | ||
565 | /* Return a def_operand_p pointer for the result of PHI. */ | |
566 | static inline def_operand_p | |
567 | get_phi_result_ptr (tree phi) | |
568 | { | |
f47c96aa | 569 | return &(PHI_RESULT_TREE (phi)); |
a32b97a2 BB |
570 | } |
571 | ||
d00ad49b AM |
572 | /* Return a use_operand_p pointer for argument I of phinode PHI. */ |
573 | static inline use_operand_p | |
574 | get_phi_arg_def_ptr (tree phi, int i) | |
575 | { | |
f430bae8 | 576 | return &(PHI_ARG_IMM_USE_NODE (phi,i)); |
6de9cd9a DN |
577 | } |
578 | ||
e54d0214 | 579 | |
f430bae8 AM |
580 | /* Return the bitmap of addresses taken by STMT, or NULL if it takes |
581 | no addresses. */ | |
582 | static inline bitmap | |
583 | addresses_taken (tree stmt) | |
584 | { | |
585 | stmt_ann_t ann = stmt_ann (stmt); | |
586 | return ann ? ann->addresses_taken : NULL; | |
6de9cd9a DN |
587 | } |
588 | ||
0566b51e DB |
589 | /* Return the PHI nodes for basic block BB, or NULL if there are no |
590 | PHI nodes. */ | |
6de9cd9a DN |
591 | static inline tree |
592 | phi_nodes (basic_block bb) | |
593 | { | |
4aab792d | 594 | return bb->phi_nodes; |
6de9cd9a DN |
595 | } |
596 | ||
597 | /* Set list of phi nodes of a basic block BB to L. */ | |
598 | ||
599 | static inline void | |
600 | set_phi_nodes (basic_block bb, tree l) | |
601 | { | |
602 | tree phi; | |
603 | ||
4aab792d | 604 | bb->phi_nodes = l; |
17192884 | 605 | for (phi = l; phi; phi = PHI_CHAIN (phi)) |
6de9cd9a DN |
606 | set_bb_for_stmt (phi, bb); |
607 | } | |
608 | ||
f430bae8 AM |
609 | /* Return the phi argument which contains the specified use. */ |
610 | ||
611 | static inline int | |
612 | phi_arg_index_from_use (use_operand_p use) | |
613 | { | |
614 | struct phi_arg_d *element, *root; | |
615 | int index; | |
616 | tree phi; | |
617 | ||
f652d14b | 618 | /* Since the use is the first thing in a PHI argument element, we can |
f430bae8 AM |
619 | calculate its index based on casting it to an argument, and performing |
620 | pointer arithmetic. */ | |
621 | ||
622 | phi = USE_STMT (use); | |
623 | gcc_assert (TREE_CODE (phi) == PHI_NODE); | |
624 | ||
625 | element = (struct phi_arg_d *)use; | |
626 | root = &(PHI_ARG_ELT (phi, 0)); | |
627 | index = element - root; | |
628 | ||
629 | #ifdef ENABLE_CHECKING | |
630 | /* Make sure the calculation doesn't have any leftover bytes. If it does, | |
f652d14b | 631 | then imm_use is likely not the first element in phi_arg_d. */ |
f430bae8 AM |
632 | gcc_assert ( |
633 | (((char *)element - (char *)root) % sizeof (struct phi_arg_d)) == 0); | |
634 | gcc_assert (index >= 0 && index < PHI_ARG_CAPACITY (phi)); | |
635 | #endif | |
636 | ||
637 | return index; | |
638 | } | |
639 | ||
727a31fa RH |
640 | /* Mark VAR as used, so that it'll be preserved during rtl expansion. */ |
641 | ||
642 | static inline void | |
643 | set_is_used (tree var) | |
644 | { | |
645 | var_ann_t ann = get_var_ann (var); | |
646 | ann->used = 1; | |
647 | } | |
648 | ||
649 | ||
6de9cd9a DN |
650 | /* ----------------------------------------------------------------------- */ |
651 | ||
0566b51e | 652 | /* Return true if T is an executable statement. */ |
6de9cd9a DN |
653 | static inline bool |
654 | is_exec_stmt (tree t) | |
655 | { | |
656 | return (t && !IS_EMPTY_STMT (t) && t != error_mark_node); | |
657 | } | |
658 | ||
659 | ||
660 | /* Return true if this stmt can be the target of a control transfer stmt such | |
661 | as a goto. */ | |
662 | static inline bool | |
663 | is_label_stmt (tree t) | |
664 | { | |
665 | if (t) | |
666 | switch (TREE_CODE (t)) | |
667 | { | |
668 | case LABEL_DECL: | |
669 | case LABEL_EXPR: | |
670 | case CASE_LABEL_EXPR: | |
671 | return true; | |
672 | default: | |
673 | return false; | |
674 | } | |
675 | return false; | |
676 | } | |
677 | ||
6de9cd9a DN |
678 | /* PHI nodes should contain only ssa_names and invariants. A test |
679 | for ssa_name is definitely simpler; don't let invalid contents | |
680 | slip in in the meantime. */ | |
681 | ||
682 | static inline bool | |
683 | phi_ssa_name_p (tree t) | |
684 | { | |
685 | if (TREE_CODE (t) == SSA_NAME) | |
686 | return true; | |
687 | #ifdef ENABLE_CHECKING | |
1e128c5f | 688 | gcc_assert (is_gimple_min_invariant (t)); |
6de9cd9a DN |
689 | #endif |
690 | return false; | |
691 | } | |
692 | ||
693 | /* ----------------------------------------------------------------------- */ | |
694 | ||
0566b51e DB |
695 | /* Return a block_stmt_iterator that points to beginning of basic |
696 | block BB. */ | |
6de9cd9a DN |
697 | static inline block_stmt_iterator |
698 | bsi_start (basic_block bb) | |
699 | { | |
700 | block_stmt_iterator bsi; | |
701 | if (bb->stmt_list) | |
702 | bsi.tsi = tsi_start (bb->stmt_list); | |
703 | else | |
704 | { | |
24bd1a0b | 705 | gcc_assert (bb->index < NUM_FIXED_BLOCKS); |
6de9cd9a DN |
706 | bsi.tsi.ptr = NULL; |
707 | bsi.tsi.container = NULL; | |
708 | } | |
709 | bsi.bb = bb; | |
710 | return bsi; | |
711 | } | |
712 | ||
93954fcc | 713 | /* Return a block statement iterator that points to the first non-label |
d7621d3c ZD |
714 | block BB. */ |
715 | ||
716 | static inline block_stmt_iterator | |
717 | bsi_after_labels (basic_block bb) | |
718 | { | |
719 | block_stmt_iterator bsi; | |
720 | tree_stmt_iterator next; | |
721 | ||
722 | bsi.bb = bb; | |
723 | ||
724 | if (!bb->stmt_list) | |
725 | { | |
24bd1a0b | 726 | gcc_assert (bb->index < NUM_FIXED_BLOCKS); |
d7621d3c ZD |
727 | bsi.tsi.ptr = NULL; |
728 | bsi.tsi.container = NULL; | |
729 | return bsi; | |
730 | } | |
731 | ||
732 | bsi.tsi = tsi_start (bb->stmt_list); | |
733 | if (tsi_end_p (bsi.tsi)) | |
734 | return bsi; | |
735 | ||
d7621d3c ZD |
736 | next = bsi.tsi; |
737 | tsi_next (&next); | |
738 | ||
739 | while (!tsi_end_p (next) | |
740 | && TREE_CODE (tsi_stmt (next)) == LABEL_EXPR) | |
741 | { | |
742 | bsi.tsi = next; | |
743 | tsi_next (&next); | |
744 | } | |
745 | ||
746 | return bsi; | |
747 | } | |
748 | ||
0566b51e DB |
749 | /* Return a block statement iterator that points to the end of basic |
750 | block BB. */ | |
6de9cd9a DN |
751 | static inline block_stmt_iterator |
752 | bsi_last (basic_block bb) | |
753 | { | |
754 | block_stmt_iterator bsi; | |
755 | if (bb->stmt_list) | |
756 | bsi.tsi = tsi_last (bb->stmt_list); | |
757 | else | |
758 | { | |
24bd1a0b | 759 | gcc_assert (bb->index < NUM_FIXED_BLOCKS); |
6de9cd9a DN |
760 | bsi.tsi.ptr = NULL; |
761 | bsi.tsi.container = NULL; | |
762 | } | |
763 | bsi.bb = bb; | |
764 | return bsi; | |
765 | } | |
766 | ||
0566b51e DB |
767 | /* Return true if block statement iterator I has reached the end of |
768 | the basic block. */ | |
6de9cd9a DN |
769 | static inline bool |
770 | bsi_end_p (block_stmt_iterator i) | |
771 | { | |
772 | return tsi_end_p (i.tsi); | |
773 | } | |
774 | ||
0566b51e DB |
775 | /* Modify block statement iterator I so that it is at the next |
776 | statement in the basic block. */ | |
6de9cd9a DN |
777 | static inline void |
778 | bsi_next (block_stmt_iterator *i) | |
779 | { | |
780 | tsi_next (&i->tsi); | |
781 | } | |
782 | ||
0566b51e DB |
783 | /* Modify block statement iterator I so that it is at the previous |
784 | statement in the basic block. */ | |
6de9cd9a DN |
785 | static inline void |
786 | bsi_prev (block_stmt_iterator *i) | |
787 | { | |
788 | tsi_prev (&i->tsi); | |
789 | } | |
790 | ||
0566b51e DB |
791 | /* Return the statement that block statement iterator I is currently |
792 | at. */ | |
6de9cd9a DN |
793 | static inline tree |
794 | bsi_stmt (block_stmt_iterator i) | |
795 | { | |
796 | return tsi_stmt (i.tsi); | |
797 | } | |
798 | ||
0566b51e DB |
799 | /* Return a pointer to the statement that block statement iterator I |
800 | is currently at. */ | |
6de9cd9a DN |
801 | static inline tree * |
802 | bsi_stmt_ptr (block_stmt_iterator i) | |
803 | { | |
804 | return tsi_stmt_ptr (i.tsi); | |
805 | } | |
806 | ||
9baba81b SP |
807 | /* Returns the loop of the statement STMT. */ |
808 | ||
809 | static inline struct loop * | |
810 | loop_containing_stmt (tree stmt) | |
811 | { | |
812 | basic_block bb = bb_for_stmt (stmt); | |
813 | if (!bb) | |
814 | return NULL; | |
815 | ||
816 | return bb->loop_father; | |
817 | } | |
818 | ||
0566b51e | 819 | /* Return true if VAR is a clobbered by function calls. */ |
6de9cd9a DN |
820 | static inline bool |
821 | is_call_clobbered (tree var) | |
822 | { | |
c597ef4e | 823 | return is_global_var (var) |
a3648cfc | 824 | || bitmap_bit_p (call_clobbered_vars, DECL_UID (var)); |
6de9cd9a DN |
825 | } |
826 | ||
0566b51e | 827 | /* Mark variable VAR as being clobbered by function calls. */ |
6de9cd9a DN |
828 | static inline void |
829 | mark_call_clobbered (tree var) | |
830 | { | |
c597ef4e DN |
831 | /* If VAR is a memory tag, then we need to consider it a global |
832 | variable. This is because the pointer that VAR represents has | |
833 | been found to point to either an arbitrary location or to a known | |
834 | location in global memory. */ | |
326eda4b DB |
835 | if (MTAG_P (var) && TREE_CODE (var) != STRUCT_FIELD_TAG) |
836 | MTAG_GLOBAL (var) = 1; | |
a3648cfc | 837 | bitmap_set_bit (call_clobbered_vars, DECL_UID (var)); |
e288e2f5 AM |
838 | ssa_call_clobbered_cache_valid = false; |
839 | ssa_ro_call_cache_valid = false; | |
6de9cd9a DN |
840 | } |
841 | ||
90e34bd6 DN |
842 | /* Clear the call-clobbered attribute from variable VAR. */ |
843 | static inline void | |
844 | clear_call_clobbered (tree var) | |
845 | { | |
326eda4b DB |
846 | if (MTAG_P (var) && TREE_CODE (var) != STRUCT_FIELD_TAG) |
847 | MTAG_GLOBAL (var) = 0; | |
a3648cfc | 848 | bitmap_clear_bit (call_clobbered_vars, DECL_UID (var)); |
90e34bd6 DN |
849 | ssa_call_clobbered_cache_valid = false; |
850 | ssa_ro_call_cache_valid = false; | |
851 | } | |
852 | ||
0566b51e | 853 | /* Mark variable VAR as being non-addressable. */ |
6de9cd9a DN |
854 | static inline void |
855 | mark_non_addressable (tree var) | |
856 | { | |
a3648cfc | 857 | bitmap_clear_bit (call_clobbered_vars, DECL_UID (var)); |
6de9cd9a | 858 | TREE_ADDRESSABLE (var) = 0; |
e288e2f5 AM |
859 | ssa_call_clobbered_cache_valid = false; |
860 | ssa_ro_call_cache_valid = false; | |
6de9cd9a DN |
861 | } |
862 | ||
06d72ee6 DB |
863 | /* Return the common annotation for T. Return NULL if the annotation |
864 | doesn't already exist. */ | |
865 | static inline tree_ann_t | |
866 | tree_ann (tree t) | |
867 | { | |
868 | return t->common.ann; | |
869 | } | |
870 | ||
871 | /* Return a common annotation for T. Create the constant annotation if it | |
872 | doesn't exist. */ | |
873 | static inline tree_ann_t | |
874 | get_tree_ann (tree t) | |
875 | { | |
876 | tree_ann_t ann = tree_ann (t); | |
877 | return (ann) ? ann : create_tree_ann (t); | |
878 | } | |
879 | ||
4c124b4c AM |
880 | /* ----------------------------------------------------------------------- */ |
881 | ||
882 | /* The following set of routines are used to iterator over various type of | |
883 | SSA operands. */ | |
884 | ||
885 | /* Return true if PTR is finished iterating. */ | |
886 | static inline bool | |
887 | op_iter_done (ssa_op_iter *ptr) | |
888 | { | |
889 | return ptr->done; | |
890 | } | |
891 | ||
892 | /* Get the next iterator use value for PTR. */ | |
893 | static inline use_operand_p | |
894 | op_iter_next_use (ssa_op_iter *ptr) | |
895 | { | |
f47c96aa AM |
896 | use_operand_p use_p; |
897 | #ifdef ENABLE_CHECKING | |
898 | gcc_assert (ptr->iter_type == ssa_op_iter_use); | |
899 | #endif | |
900 | if (ptr->uses) | |
4c124b4c | 901 | { |
f47c96aa AM |
902 | use_p = USE_OP_PTR (ptr->uses); |
903 | ptr->uses = ptr->uses->next; | |
904 | return use_p; | |
4c124b4c | 905 | } |
f47c96aa | 906 | if (ptr->vuses) |
4c124b4c | 907 | { |
f47c96aa AM |
908 | use_p = VUSE_OP_PTR (ptr->vuses); |
909 | ptr->vuses = ptr->vuses->next; | |
910 | return use_p; | |
4c124b4c | 911 | } |
f47c96aa | 912 | if (ptr->mayuses) |
4c124b4c | 913 | { |
f47c96aa AM |
914 | use_p = MAYDEF_OP_PTR (ptr->mayuses); |
915 | ptr->mayuses = ptr->mayuses->next; | |
916 | return use_p; | |
52328bf6 | 917 | } |
f47c96aa | 918 | if (ptr->mustkills) |
52328bf6 | 919 | { |
f47c96aa AM |
920 | use_p = MUSTDEF_KILL_PTR (ptr->mustkills); |
921 | ptr->mustkills = ptr->mustkills->next; | |
922 | return use_p; | |
923 | } | |
924 | if (ptr->phi_i < ptr->num_phi) | |
925 | { | |
926 | return PHI_ARG_DEF_PTR (ptr->phi_stmt, (ptr->phi_i)++); | |
4c124b4c AM |
927 | } |
928 | ptr->done = true; | |
929 | return NULL_USE_OPERAND_P; | |
930 | } | |
931 | ||
932 | /* Get the next iterator def value for PTR. */ | |
933 | static inline def_operand_p | |
934 | op_iter_next_def (ssa_op_iter *ptr) | |
935 | { | |
f47c96aa AM |
936 | def_operand_p def_p; |
937 | #ifdef ENABLE_CHECKING | |
938 | gcc_assert (ptr->iter_type == ssa_op_iter_def); | |
939 | #endif | |
940 | if (ptr->defs) | |
4c124b4c | 941 | { |
f47c96aa AM |
942 | def_p = DEF_OP_PTR (ptr->defs); |
943 | ptr->defs = ptr->defs->next; | |
944 | return def_p; | |
4c124b4c | 945 | } |
f47c96aa | 946 | if (ptr->mustdefs) |
4c124b4c | 947 | { |
f47c96aa AM |
948 | def_p = MUSTDEF_RESULT_PTR (ptr->mustdefs); |
949 | ptr->mustdefs = ptr->mustdefs->next; | |
950 | return def_p; | |
4c124b4c | 951 | } |
f47c96aa | 952 | if (ptr->maydefs) |
4c124b4c | 953 | { |
f47c96aa AM |
954 | def_p = MAYDEF_RESULT_PTR (ptr->maydefs); |
955 | ptr->maydefs = ptr->maydefs->next; | |
956 | return def_p; | |
4c124b4c AM |
957 | } |
958 | ptr->done = true; | |
959 | return NULL_DEF_OPERAND_P; | |
960 | } | |
961 | ||
962 | /* Get the next iterator tree value for PTR. */ | |
963 | static inline tree | |
964 | op_iter_next_tree (ssa_op_iter *ptr) | |
965 | { | |
f47c96aa AM |
966 | tree val; |
967 | #ifdef ENABLE_CHECKING | |
968 | gcc_assert (ptr->iter_type == ssa_op_iter_tree); | |
969 | #endif | |
970 | if (ptr->uses) | |
4c124b4c | 971 | { |
f47c96aa AM |
972 | val = USE_OP (ptr->uses); |
973 | ptr->uses = ptr->uses->next; | |
974 | return val; | |
4c124b4c | 975 | } |
f47c96aa | 976 | if (ptr->vuses) |
4c124b4c | 977 | { |
f47c96aa AM |
978 | val = VUSE_OP (ptr->vuses); |
979 | ptr->vuses = ptr->vuses->next; | |
980 | return val; | |
4c124b4c | 981 | } |
f47c96aa | 982 | if (ptr->mayuses) |
4c124b4c | 983 | { |
f47c96aa AM |
984 | val = MAYDEF_OP (ptr->mayuses); |
985 | ptr->mayuses = ptr->mayuses->next; | |
986 | return val; | |
4c124b4c | 987 | } |
f47c96aa | 988 | if (ptr->mustkills) |
52328bf6 | 989 | { |
f47c96aa AM |
990 | val = MUSTDEF_KILL (ptr->mustkills); |
991 | ptr->mustkills = ptr->mustkills->next; | |
992 | return val; | |
52328bf6 | 993 | } |
f47c96aa | 994 | if (ptr->defs) |
4c124b4c | 995 | { |
f47c96aa AM |
996 | val = DEF_OP (ptr->defs); |
997 | ptr->defs = ptr->defs->next; | |
998 | return val; | |
4c124b4c | 999 | } |
f47c96aa | 1000 | if (ptr->mustdefs) |
4c124b4c | 1001 | { |
f47c96aa AM |
1002 | val = MUSTDEF_RESULT (ptr->mustdefs); |
1003 | ptr->mustdefs = ptr->mustdefs->next; | |
1004 | return val; | |
4c124b4c | 1005 | } |
f47c96aa | 1006 | if (ptr->maydefs) |
4c124b4c | 1007 | { |
f47c96aa AM |
1008 | val = MAYDEF_RESULT (ptr->maydefs); |
1009 | ptr->maydefs = ptr->maydefs->next; | |
1010 | return val; | |
4c124b4c | 1011 | } |
f47c96aa AM |
1012 | |
1013 | ptr->done = true; | |
1014 | return NULL_TREE; | |
1015 | ||
1016 | } | |
1017 | ||
1018 | ||
395bda42 | 1019 | /* This functions clears the iterator PTR, and marks it done. This is normally |
c83eecad | 1020 | used to prevent warnings in the compile about might be uninitialized |
f47c96aa AM |
1021 | components. */ |
1022 | ||
1023 | static inline void | |
1024 | clear_and_done_ssa_iter (ssa_op_iter *ptr) | |
1025 | { | |
1026 | ptr->defs = NULL; | |
1027 | ptr->uses = NULL; | |
1028 | ptr->vuses = NULL; | |
1029 | ptr->maydefs = NULL; | |
1030 | ptr->mayuses = NULL; | |
1031 | ptr->mustdefs = NULL; | |
1032 | ptr->mustkills = NULL; | |
1033 | ptr->iter_type = ssa_op_iter_none; | |
1034 | ptr->phi_i = 0; | |
1035 | ptr->num_phi = 0; | |
1036 | ptr->phi_stmt = NULL_TREE; | |
4c124b4c | 1037 | ptr->done = true; |
4c124b4c AM |
1038 | } |
1039 | ||
1040 | /* Initialize the iterator PTR to the virtual defs in STMT. */ | |
1041 | static inline void | |
1042 | op_iter_init (ssa_op_iter *ptr, tree stmt, int flags) | |
1043 | { | |
f47c96aa AM |
1044 | #ifdef ENABLE_CHECKING |
1045 | gcc_assert (stmt_ann (stmt)); | |
1046 | #endif | |
4c124b4c | 1047 | |
f47c96aa AM |
1048 | ptr->defs = (flags & SSA_OP_DEF) ? DEF_OPS (stmt) : NULL; |
1049 | ptr->uses = (flags & SSA_OP_USE) ? USE_OPS (stmt) : NULL; | |
1050 | ptr->vuses = (flags & SSA_OP_VUSE) ? VUSE_OPS (stmt) : NULL; | |
1051 | ptr->maydefs = (flags & SSA_OP_VMAYDEF) ? MAYDEF_OPS (stmt) : NULL; | |
1052 | ptr->mayuses = (flags & SSA_OP_VMAYUSE) ? MAYDEF_OPS (stmt) : NULL; | |
1053 | ptr->mustdefs = (flags & SSA_OP_VMUSTDEF) ? MUSTDEF_OPS (stmt) : NULL; | |
1054 | ptr->mustkills = (flags & SSA_OP_VMUSTKILL) ? MUSTDEF_OPS (stmt) : NULL; | |
4c124b4c | 1055 | ptr->done = false; |
f47c96aa AM |
1056 | |
1057 | ptr->phi_i = 0; | |
1058 | ptr->num_phi = 0; | |
1059 | ptr->phi_stmt = NULL_TREE; | |
4c124b4c AM |
1060 | } |
1061 | ||
1062 | /* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return | |
1063 | the first use. */ | |
1064 | static inline use_operand_p | |
1065 | op_iter_init_use (ssa_op_iter *ptr, tree stmt, int flags) | |
1066 | { | |
66d3fe47 | 1067 | gcc_assert ((flags & SSA_OP_ALL_DEFS) == 0); |
4c124b4c | 1068 | op_iter_init (ptr, stmt, flags); |
f47c96aa | 1069 | ptr->iter_type = ssa_op_iter_use; |
4c124b4c AM |
1070 | return op_iter_next_use (ptr); |
1071 | } | |
1072 | ||
1073 | /* Initialize iterator PTR to the def operands in STMT based on FLAGS. Return | |
1074 | the first def. */ | |
1075 | static inline def_operand_p | |
1076 | op_iter_init_def (ssa_op_iter *ptr, tree stmt, int flags) | |
1077 | { | |
66d3fe47 | 1078 | gcc_assert ((flags & (SSA_OP_ALL_USES | SSA_OP_VIRTUAL_KILLS)) == 0); |
4c124b4c | 1079 | op_iter_init (ptr, stmt, flags); |
f47c96aa | 1080 | ptr->iter_type = ssa_op_iter_def; |
4c124b4c AM |
1081 | return op_iter_next_def (ptr); |
1082 | } | |
1083 | ||
1084 | /* Initialize iterator PTR to the operands in STMT based on FLAGS. Return | |
1085 | the first operand as a tree. */ | |
1086 | static inline tree | |
1087 | op_iter_init_tree (ssa_op_iter *ptr, tree stmt, int flags) | |
1088 | { | |
1089 | op_iter_init (ptr, stmt, flags); | |
f47c96aa | 1090 | ptr->iter_type = ssa_op_iter_tree; |
4c124b4c AM |
1091 | return op_iter_next_tree (ptr); |
1092 | } | |
1093 | ||
52328bf6 DB |
1094 | /* Get the next iterator mustdef value for PTR, returning the mustdef values in |
1095 | KILL and DEF. */ | |
1096 | static inline void | |
f47c96aa AM |
1097 | op_iter_next_maymustdef (use_operand_p *use, def_operand_p *def, |
1098 | ssa_op_iter *ptr) | |
52328bf6 | 1099 | { |
f47c96aa AM |
1100 | #ifdef ENABLE_CHECKING |
1101 | gcc_assert (ptr->iter_type == ssa_op_iter_maymustdef); | |
1102 | #endif | |
1103 | if (ptr->mayuses) | |
52328bf6 | 1104 | { |
f47c96aa AM |
1105 | *def = MAYDEF_RESULT_PTR (ptr->mayuses); |
1106 | *use = MAYDEF_OP_PTR (ptr->mayuses); | |
1107 | ptr->mayuses = ptr->mayuses->next; | |
52328bf6 DB |
1108 | return; |
1109 | } | |
db30731a | 1110 | |
f47c96aa | 1111 | if (ptr->mustkills) |
4c124b4c | 1112 | { |
f47c96aa AM |
1113 | *def = MUSTDEF_RESULT_PTR (ptr->mustkills); |
1114 | *use = MUSTDEF_KILL_PTR (ptr->mustkills); | |
1115 | ptr->mustkills = ptr->mustkills->next; | |
4c124b4c AM |
1116 | return; |
1117 | } | |
4c124b4c | 1118 | |
f47c96aa AM |
1119 | *def = NULL_DEF_OPERAND_P; |
1120 | *use = NULL_USE_OPERAND_P; | |
db30731a JL |
1121 | ptr->done = true; |
1122 | return; | |
1123 | } | |
1124 | ||
f47c96aa | 1125 | |
4c124b4c AM |
1126 | /* Initialize iterator PTR to the operands in STMT. Return the first operands |
1127 | in USE and DEF. */ | |
1128 | static inline void | |
1129 | op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, use_operand_p *use, | |
1130 | def_operand_p *def) | |
1131 | { | |
f47c96aa AM |
1132 | gcc_assert (TREE_CODE (stmt) != PHI_NODE); |
1133 | ||
4c124b4c | 1134 | op_iter_init (ptr, stmt, SSA_OP_VMAYUSE); |
f47c96aa AM |
1135 | ptr->iter_type = ssa_op_iter_maymustdef; |
1136 | op_iter_next_maymustdef (use, def, ptr); | |
4c124b4c | 1137 | } |
52328bf6 | 1138 | |
0bca51f0 | 1139 | |
52328bf6 DB |
1140 | /* Initialize iterator PTR to the operands in STMT. Return the first operands |
1141 | in KILL and DEF. */ | |
1142 | static inline void | |
1143 | op_iter_init_mustdef (ssa_op_iter *ptr, tree stmt, use_operand_p *kill, | |
1144 | def_operand_p *def) | |
1145 | { | |
f47c96aa AM |
1146 | gcc_assert (TREE_CODE (stmt) != PHI_NODE); |
1147 | ||
1148 | op_iter_init (ptr, stmt, SSA_OP_VMUSTKILL); | |
1149 | ptr->iter_type = ssa_op_iter_maymustdef; | |
1150 | op_iter_next_maymustdef (kill, def, ptr); | |
52328bf6 | 1151 | } |
c75ab022 | 1152 | |
db30731a JL |
1153 | /* Initialize iterator PTR to the operands in STMT. Return the first operands |
1154 | in KILL and DEF. */ | |
1155 | static inline void | |
1156 | op_iter_init_must_and_may_def (ssa_op_iter *ptr, tree stmt, | |
1157 | use_operand_p *kill, def_operand_p *def) | |
1158 | { | |
f47c96aa AM |
1159 | gcc_assert (TREE_CODE (stmt) != PHI_NODE); |
1160 | ||
1161 | op_iter_init (ptr, stmt, SSA_OP_VMUSTKILL|SSA_OP_VMAYUSE); | |
1162 | ptr->iter_type = ssa_op_iter_maymustdef; | |
1163 | op_iter_next_maymustdef (kill, def, ptr); | |
1164 | } | |
1165 | ||
1166 | ||
395bda42 | 1167 | /* If there is a single operand in STMT matching FLAGS, return it. Otherwise |
d7770457 | 1168 | return NULL. */ |
f47c96aa AM |
1169 | static inline tree |
1170 | single_ssa_tree_operand (tree stmt, int flags) | |
1171 | { | |
1172 | tree var; | |
1173 | ssa_op_iter iter; | |
1174 | ||
1175 | var = op_iter_init_tree (&iter, stmt, flags); | |
1176 | if (op_iter_done (&iter)) | |
1177 | return NULL_TREE; | |
1178 | op_iter_next_tree (&iter); | |
1179 | if (op_iter_done (&iter)) | |
1180 | return var; | |
1181 | return NULL_TREE; | |
1182 | } | |
1183 | ||
1184 | ||
395bda42 | 1185 | /* If there is a single operand in STMT matching FLAGS, return it. Otherwise |
d7770457 | 1186 | return NULL. */ |
f47c96aa AM |
1187 | static inline use_operand_p |
1188 | single_ssa_use_operand (tree stmt, int flags) | |
1189 | { | |
1190 | use_operand_p var; | |
1191 | ssa_op_iter iter; | |
1192 | ||
1193 | var = op_iter_init_use (&iter, stmt, flags); | |
1194 | if (op_iter_done (&iter)) | |
1195 | return NULL_USE_OPERAND_P; | |
1196 | op_iter_next_use (&iter); | |
1197 | if (op_iter_done (&iter)) | |
1198 | return var; | |
1199 | return NULL_USE_OPERAND_P; | |
1200 | } | |
1201 | ||
1202 | ||
1203 | ||
395bda42 | 1204 | /* If there is a single operand in STMT matching FLAGS, return it. Otherwise |
d7770457 | 1205 | return NULL. */ |
f47c96aa AM |
1206 | static inline def_operand_p |
1207 | single_ssa_def_operand (tree stmt, int flags) | |
1208 | { | |
1209 | def_operand_p var; | |
1210 | ssa_op_iter iter; | |
1211 | ||
1212 | var = op_iter_init_def (&iter, stmt, flags); | |
1213 | if (op_iter_done (&iter)) | |
1214 | return NULL_DEF_OPERAND_P; | |
1215 | op_iter_next_def (&iter); | |
1216 | if (op_iter_done (&iter)) | |
1217 | return var; | |
1218 | return NULL_DEF_OPERAND_P; | |
1219 | } | |
1220 | ||
1221 | ||
395bda42 | 1222 | /* If there is a single operand in STMT matching FLAGS, return it. Otherwise |
d7770457 | 1223 | return NULL. */ |
f47c96aa AM |
1224 | static inline bool |
1225 | zero_ssa_operands (tree stmt, int flags) | |
1226 | { | |
1227 | ssa_op_iter iter; | |
1228 | ||
1229 | op_iter_init_tree (&iter, stmt, flags); | |
1230 | return op_iter_done (&iter); | |
db30731a JL |
1231 | } |
1232 | ||
f47c96aa | 1233 | |
395bda42 | 1234 | /* Return the number of operands matching FLAGS in STMT. */ |
f47c96aa AM |
1235 | static inline int |
1236 | num_ssa_operands (tree stmt, int flags) | |
1237 | { | |
1238 | ssa_op_iter iter; | |
66d3fe47 | 1239 | tree t; |
f47c96aa AM |
1240 | int num = 0; |
1241 | ||
66d3fe47 | 1242 | FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, flags) |
f47c96aa | 1243 | num++; |
f47c96aa AM |
1244 | return num; |
1245 | } | |
1246 | ||
1247 | ||
1248 | /* Delink all immediate_use information for STMT. */ | |
1249 | static inline void | |
1250 | delink_stmt_imm_use (tree stmt) | |
1251 | { | |
1252 | ssa_op_iter iter; | |
1253 | use_operand_p use_p; | |
1254 | ||
1255 | if (ssa_operands_active ()) | |
1256 | FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, | |
1257 | (SSA_OP_ALL_USES | SSA_OP_ALL_KILLS)) | |
1258 | delink_imm_use (use_p); | |
1259 | } | |
1260 | ||
1261 | ||
1262 | /* This routine will compare all the operands matching FLAGS in STMT1 to those | |
1263 | in STMT2. TRUE is returned if they are the same. STMTs can be NULL. */ | |
1264 | static inline bool | |
1265 | compare_ssa_operands_equal (tree stmt1, tree stmt2, int flags) | |
1266 | { | |
1267 | ssa_op_iter iter1, iter2; | |
1268 | tree op1 = NULL_TREE; | |
1269 | tree op2 = NULL_TREE; | |
1270 | bool look1, look2; | |
1271 | ||
1272 | if (stmt1 == stmt2) | |
1273 | return true; | |
1274 | ||
1275 | look1 = stmt1 && stmt_ann (stmt1); | |
1276 | look2 = stmt2 && stmt_ann (stmt2); | |
1277 | ||
1278 | if (look1) | |
1279 | { | |
1280 | op1 = op_iter_init_tree (&iter1, stmt1, flags); | |
1281 | if (!look2) | |
1282 | return op_iter_done (&iter1); | |
1283 | } | |
1284 | else | |
1285 | clear_and_done_ssa_iter (&iter1); | |
1286 | ||
1287 | if (look2) | |
1288 | { | |
1289 | op2 = op_iter_init_tree (&iter2, stmt2, flags); | |
1290 | if (!look1) | |
1291 | return op_iter_done (&iter2); | |
1292 | } | |
1293 | else | |
1294 | clear_and_done_ssa_iter (&iter2); | |
1295 | ||
1296 | while (!op_iter_done (&iter1) && !op_iter_done (&iter2)) | |
1297 | { | |
1298 | if (op1 != op2) | |
1299 | return false; | |
1300 | op1 = op_iter_next_tree (&iter1); | |
1301 | op2 = op_iter_next_tree (&iter2); | |
1302 | } | |
1303 | ||
1304 | return (op_iter_done (&iter1) && op_iter_done (&iter2)); | |
1305 | } | |
1306 | ||
1307 | ||
1308 | /* If there is a single DEF in the PHI node which matches FLAG, return it. | |
1309 | Otherwise return NULL_DEF_OPERAND_P. */ | |
1310 | static inline tree | |
1311 | single_phi_def (tree stmt, int flags) | |
1312 | { | |
1313 | tree def = PHI_RESULT (stmt); | |
1314 | if ((flags & SSA_OP_DEF) && is_gimple_reg (def)) | |
1315 | return def; | |
1316 | if ((flags & SSA_OP_VIRTUAL_DEFS) && !is_gimple_reg (def)) | |
1317 | return def; | |
1318 | return NULL_TREE; | |
1319 | } | |
1320 | ||
1321 | /* Initialize the iterator PTR for uses matching FLAGS in PHI. FLAGS should | |
1322 | be either SSA_OP_USES or SAS_OP_VIRTUAL_USES. */ | |
1323 | static inline use_operand_p | |
1324 | op_iter_init_phiuse (ssa_op_iter *ptr, tree phi, int flags) | |
1325 | { | |
1326 | tree phi_def = PHI_RESULT (phi); | |
1327 | int comp; | |
1328 | ||
1329 | clear_and_done_ssa_iter (ptr); | |
1330 | ptr->done = false; | |
1331 | ||
1332 | gcc_assert ((flags & (SSA_OP_USE | SSA_OP_VIRTUAL_USES)) != 0); | |
1333 | ||
1334 | comp = (is_gimple_reg (phi_def) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES); | |
1335 | ||
395bda42 | 1336 | /* If the PHI node doesn't the operand type we care about, we're done. */ |
f47c96aa AM |
1337 | if ((flags & comp) == 0) |
1338 | { | |
1339 | ptr->done = true; | |
1340 | return NULL_USE_OPERAND_P; | |
1341 | } | |
1342 | ||
1343 | ptr->phi_stmt = phi; | |
1344 | ptr->num_phi = PHI_NUM_ARGS (phi); | |
1345 | ptr->iter_type = ssa_op_iter_use; | |
1346 | return op_iter_next_use (ptr); | |
1347 | } | |
1348 | ||
1349 | ||
395bda42 | 1350 | /* Start an iterator for a PHI definition. */ |
f47c96aa AM |
1351 | |
1352 | static inline def_operand_p | |
1353 | op_iter_init_phidef (ssa_op_iter *ptr, tree phi, int flags) | |
1354 | { | |
1355 | tree phi_def = PHI_RESULT (phi); | |
1356 | int comp; | |
1357 | ||
1358 | clear_and_done_ssa_iter (ptr); | |
1359 | ptr->done = false; | |
1360 | ||
1361 | gcc_assert ((flags & (SSA_OP_DEF | SSA_OP_VIRTUAL_DEFS)) != 0); | |
1362 | ||
1363 | comp = (is_gimple_reg (phi_def) ? SSA_OP_DEF : SSA_OP_VIRTUAL_DEFS); | |
1364 | ||
395bda42 | 1365 | /* If the PHI node doesn't the operand type we care about, we're done. */ |
f47c96aa AM |
1366 | if ((flags & comp) == 0) |
1367 | { | |
1368 | ptr->done = true; | |
1369 | return NULL_USE_OPERAND_P; | |
1370 | } | |
1371 | ||
1372 | ptr->iter_type = ssa_op_iter_def; | |
1373 | /* The first call to op_iter_next_def will terminate the iterator since | |
1374 | all the fields are NULL. Simply return the result here as the first and | |
1375 | therefore only result. */ | |
1376 | return PHI_RESULT_PTR (phi); | |
1377 | } | |
1378 | ||
1379 | ||
1380 | ||
db30731a JL |
1381 | /* Return true if VAR cannot be modified by the program. */ |
1382 | ||
1383 | static inline bool | |
1384 | unmodifiable_var_p (tree var) | |
1385 | { | |
1386 | if (TREE_CODE (var) == SSA_NAME) | |
1387 | var = SSA_NAME_VAR (var); | |
326eda4b DB |
1388 | |
1389 | if (MTAG_P (var)) | |
1390 | return TREE_READONLY (var) && (TREE_STATIC (var) || MTAG_GLOBAL (var)); | |
1391 | ||
db30731a JL |
1392 | return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var)); |
1393 | } | |
1394 | ||
8d66aeca | 1395 | /* Return true if REF, an ARRAY_REF, has an INDIRECT_REF somewhere in it. */ |
b1347638 DB |
1396 | |
1397 | static inline bool | |
8d66aeca | 1398 | array_ref_contains_indirect_ref (tree ref) |
b1347638 | 1399 | { |
8d66aeca RG |
1400 | gcc_assert (TREE_CODE (ref) == ARRAY_REF); |
1401 | ||
1402 | do { | |
1403 | ref = TREE_OPERAND (ref, 0); | |
1404 | } while (handled_component_p (ref)); | |
1405 | ||
1406 | return TREE_CODE (ref) == INDIRECT_REF; | |
b1347638 DB |
1407 | } |
1408 | ||
8d66aeca RG |
1409 | /* Return true if REF, a handled component reference, has an ARRAY_REF |
1410 | somewhere in it. */ | |
c75ab022 DB |
1411 | |
1412 | static inline bool | |
1413 | ref_contains_array_ref (tree ref) | |
1414 | { | |
8d66aeca RG |
1415 | gcc_assert (handled_component_p (ref)); |
1416 | ||
1417 | do { | |
1418 | if (TREE_CODE (ref) == ARRAY_REF) | |
1419 | return true; | |
1420 | ref = TREE_OPERAND (ref, 0); | |
1421 | } while (handled_component_p (ref)); | |
1422 | ||
c75ab022 DB |
1423 | return false; |
1424 | } | |
1425 | ||
1426 | /* Given a variable VAR, lookup and return a pointer to the list of | |
1427 | subvariables for it. */ | |
1428 | ||
1429 | static inline subvar_t * | |
1430 | lookup_subvars_for_var (tree var) | |
1431 | { | |
1432 | var_ann_t ann = var_ann (var); | |
1433 | gcc_assert (ann); | |
1434 | return &ann->subvars; | |
1435 | } | |
1436 | ||
1437 | /* Given a variable VAR, return a linked list of subvariables for VAR, or | |
1438 | NULL, if there are no subvariables. */ | |
1439 | ||
1440 | static inline subvar_t | |
1441 | get_subvars_for_var (tree var) | |
1442 | { | |
1443 | subvar_t subvars; | |
1444 | ||
1445 | gcc_assert (SSA_VAR_P (var)); | |
1446 | ||
1447 | if (TREE_CODE (var) == SSA_NAME) | |
1448 | subvars = *(lookup_subvars_for_var (SSA_NAME_VAR (var))); | |
1449 | else | |
1450 | subvars = *(lookup_subvars_for_var (var)); | |
1451 | return subvars; | |
1452 | } | |
1453 | ||
e8ca4159 DN |
1454 | /* Return the subvariable of VAR at offset OFFSET. */ |
1455 | ||
1456 | static inline tree | |
1457 | get_subvar_at (tree var, unsigned HOST_WIDE_INT offset) | |
1458 | { | |
1459 | subvar_t sv; | |
1460 | ||
1461 | for (sv = get_subvars_for_var (var); sv; sv = sv->next) | |
1462 | if (sv->offset == offset) | |
1463 | return sv->var; | |
1464 | ||
1465 | return NULL_TREE; | |
1466 | } | |
1467 | ||
c75ab022 DB |
1468 | /* Return true if V is a tree that we can have subvars for. |
1469 | Normally, this is any aggregate type, however, due to implementation | |
1470 | limitations ATM, we exclude array types as well. */ | |
1471 | ||
1472 | static inline bool | |
1473 | var_can_have_subvars (tree v) | |
1474 | { | |
1475 | return (AGGREGATE_TYPE_P (TREE_TYPE (v)) && | |
1476 | TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE); | |
1477 | } | |
1478 | ||
1479 | ||
013cc86f DB |
1480 | /* Return true if OFFSET and SIZE define a range that overlaps with some |
1481 | portion of the range of SV, a subvar. If there was an exact overlap, | |
1482 | *EXACT will be set to true upon return. */ | |
1483 | ||
1484 | static inline bool | |
e8ca4159 | 1485 | overlap_subvar (unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, |
013cc86f DB |
1486 | subvar_t sv, bool *exact) |
1487 | { | |
1488 | /* There are three possible cases of overlap. | |
1489 | 1. We can have an exact overlap, like so: | |
1490 | |offset, offset + size | | |
1491 | |sv->offset, sv->offset + sv->size | | |
1492 | ||
1493 | 2. We can have offset starting after sv->offset, like so: | |
1494 | ||
1495 | |offset, offset + size | | |
1496 | |sv->offset, sv->offset + sv->size | | |
1497 | ||
1498 | 3. We can have offset starting before sv->offset, like so: | |
1499 | ||
1500 | |offset, offset + size | | |
1501 | |sv->offset, sv->offset + sv->size| | |
1502 | */ | |
1503 | ||
1504 | if (exact) | |
1505 | *exact = false; | |
1506 | if (offset == sv->offset && size == sv->size) | |
1507 | { | |
1508 | if (exact) | |
1509 | *exact = true; | |
1510 | return true; | |
1511 | } | |
1512 | else if (offset >= sv->offset && offset < (sv->offset + sv->size)) | |
1513 | { | |
1514 | return true; | |
1515 | } | |
5c97e2de | 1516 | else if (offset < sv->offset && (size > sv->offset - offset)) |
013cc86f DB |
1517 | { |
1518 | return true; | |
1519 | } | |
1520 | return false; | |
1521 | ||
1522 | } | |
c75ab022 | 1523 | |
6de9cd9a | 1524 | #endif /* _TREE_FLOW_INLINE_H */ |