]>
Commit | Line | Data |
---|---|---|
6de9cd9a | 1 | /* Inline functions for tree-flow.h |
263bb8fb | 2 | Copyright (C) 2001, 2003, 2005, 2006 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 | ||
5cd4ec7f JH |
28 | /* Return true when gimple SSA form was built. |
29 | gimple_in_ssa_p is queried by gimplifier in various early stages before SSA | |
30 | infrastructure is initialized. Check for presence of the datastructures | |
31 | at first place. */ | |
32 | static inline bool | |
33 | gimple_in_ssa_p (struct function *fun) | |
34 | { | |
35 | return fun && fun->gimple_df && fun->gimple_df->in_ssa_p; | |
36 | } | |
37 | ||
38 | /* 'true' after aliases have been computed (see compute_may_aliases). */ | |
39 | static inline bool | |
40 | gimple_aliases_computed_p (struct function *fun) | |
41 | { | |
42 | gcc_assert (fun && fun->gimple_df); | |
43 | return fun->gimple_df->aliases_computed_p; | |
44 | } | |
45 | ||
46 | /* Addressable variables in the function. If bit I is set, then | |
47 | REFERENCED_VARS (I) has had its address taken. Note that | |
48 | CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related. An | |
49 | addressable variable is not necessarily call-clobbered (e.g., a | |
50 | local addressable whose address does not escape) and not all | |
51 | call-clobbered variables are addressable (e.g., a local static | |
52 | variable). */ | |
53 | static inline bitmap | |
54 | gimple_addressable_vars (struct function *fun) | |
55 | { | |
56 | gcc_assert (fun && fun->gimple_df); | |
57 | return fun->gimple_df->addressable_vars; | |
58 | } | |
59 | ||
60 | /* Call clobbered variables in the function. If bit I is set, then | |
61 | REFERENCED_VARS (I) is call-clobbered. */ | |
62 | static inline bitmap | |
63 | gimple_call_clobbered_vars (struct function *fun) | |
64 | { | |
65 | gcc_assert (fun && fun->gimple_df); | |
66 | return fun->gimple_df->call_clobbered_vars; | |
67 | } | |
68 | ||
69 | /* Array of all variables referenced in the function. */ | |
70 | static inline htab_t | |
71 | gimple_referenced_vars (struct function *fun) | |
72 | { | |
73 | if (!fun->gimple_df) | |
74 | return NULL; | |
75 | return fun->gimple_df->referenced_vars; | |
76 | } | |
77 | ||
78 | /* Artificial variable used to model the effects of function calls. */ | |
79 | static inline tree | |
80 | gimple_global_var (struct function *fun) | |
81 | { | |
82 | gcc_assert (fun && fun->gimple_df); | |
83 | return fun->gimple_df->global_var; | |
84 | } | |
85 | ||
86 | /* Artificial variable used to model the effects of nonlocal | |
87 | variables. */ | |
88 | static inline tree | |
89 | gimple_nonlocal_all (struct function *fun) | |
90 | { | |
91 | gcc_assert (fun && fun->gimple_df); | |
92 | return fun->gimple_df->nonlocal_all; | |
93 | } | |
adb6509f JH |
94 | |
95 | /* Hashtable of variables annotations. Used for static variables only; | |
96 | local variables have direct pointer in the tree node. */ | |
97 | static inline htab_t | |
98 | gimple_var_anns (struct function *fun) | |
99 | { | |
100 | return fun->gimple_df->var_anns; | |
101 | } | |
102 | ||
a3648cfc DB |
103 | /* Initialize the hashtable iterator HTI to point to hashtable TABLE */ |
104 | ||
105 | static inline void * | |
106 | first_htab_element (htab_iterator *hti, htab_t table) | |
107 | { | |
108 | hti->htab = table; | |
109 | hti->slot = table->entries; | |
110 | hti->limit = hti->slot + htab_size (table); | |
111 | do | |
112 | { | |
113 | PTR x = *(hti->slot); | |
114 | if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY) | |
115 | break; | |
116 | } while (++(hti->slot) < hti->limit); | |
117 | ||
118 | if (hti->slot < hti->limit) | |
119 | return *(hti->slot); | |
120 | return NULL; | |
121 | } | |
122 | ||
123 | /* Return current non-empty/deleted slot of the hashtable pointed to by HTI, | |
124 | or NULL if we have reached the end. */ | |
125 | ||
126 | static inline bool | |
127 | end_htab_p (htab_iterator *hti) | |
128 | { | |
129 | if (hti->slot >= hti->limit) | |
130 | return true; | |
131 | return false; | |
132 | } | |
133 | ||
206048bd | 134 | /* Advance the hashtable iterator pointed to by HTI to the next element of the |
a3648cfc DB |
135 | hashtable. */ |
136 | ||
137 | static inline void * | |
138 | next_htab_element (htab_iterator *hti) | |
139 | { | |
140 | while (++(hti->slot) < hti->limit) | |
141 | { | |
142 | PTR x = *(hti->slot); | |
143 | if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY) | |
144 | return x; | |
145 | }; | |
146 | return NULL; | |
147 | } | |
148 | ||
149 | /* Initialize ITER to point to the first referenced variable in the | |
150 | referenced_vars hashtable, and return that variable. */ | |
151 | ||
152 | static inline tree | |
153 | first_referenced_var (referenced_var_iterator *iter) | |
154 | { | |
155 | struct int_tree_map *itm; | |
cceb1885 | 156 | itm = (struct int_tree_map *) first_htab_element (&iter->hti, |
5cd4ec7f JH |
157 | gimple_referenced_vars |
158 | (cfun)); | |
a3648cfc DB |
159 | if (!itm) |
160 | return NULL; | |
161 | return itm->to; | |
162 | } | |
163 | ||
164 | /* Return true if we have hit the end of the referenced variables ITER is | |
165 | iterating through. */ | |
166 | ||
167 | static inline bool | |
168 | end_referenced_vars_p (referenced_var_iterator *iter) | |
169 | { | |
170 | return end_htab_p (&iter->hti); | |
171 | } | |
172 | ||
173 | /* Make ITER point to the next referenced_var in the referenced_var hashtable, | |
174 | and return that variable. */ | |
175 | ||
176 | static inline tree | |
177 | next_referenced_var (referenced_var_iterator *iter) | |
178 | { | |
179 | struct int_tree_map *itm; | |
cceb1885 | 180 | itm = (struct int_tree_map *) next_htab_element (&iter->hti); |
a3648cfc DB |
181 | if (!itm) |
182 | return NULL; | |
183 | return itm->to; | |
184 | } | |
b9d33488 DB |
185 | |
186 | /* Fill up VEC with the variables in the referenced vars hashtable. */ | |
187 | ||
188 | static inline void | |
189 | fill_referenced_var_vec (VEC (tree, heap) **vec) | |
190 | { | |
191 | referenced_var_iterator rvi; | |
192 | tree var; | |
193 | *vec = NULL; | |
194 | FOR_EACH_REFERENCED_VAR (var, rvi) | |
195 | VEC_safe_push (tree, heap, *vec, var); | |
196 | } | |
197 | ||
0566b51e DB |
198 | /* Return the variable annotation for T, which must be a _DECL node. |
199 | Return NULL if the variable annotation doesn't already exist. */ | |
6de9cd9a DN |
200 | static inline var_ann_t |
201 | var_ann (tree t) | |
202 | { | |
1e128c5f GB |
203 | gcc_assert (t); |
204 | gcc_assert (DECL_P (t)); | |
3bfdb124 | 205 | gcc_assert (TREE_CODE (t) != FUNCTION_DECL); |
6ac5a246 | 206 | if (!MTAG_P (t) && (TREE_STATIC (t) || DECL_EXTERNAL (t))) |
adb6509f JH |
207 | { |
208 | struct static_var_ann_d *sann | |
209 | = ((struct static_var_ann_d *) | |
210 | htab_find_with_hash (gimple_var_anns (cfun), t, DECL_UID (t))); | |
211 | if (!sann) | |
212 | return NULL; | |
213 | gcc_assert (sann->ann.common.type = VAR_ANN); | |
214 | return &sann->ann; | |
215 | } | |
07beea0d AH |
216 | gcc_assert (!t->base.ann |
217 | || t->base.ann->common.type == VAR_ANN); | |
6de9cd9a | 218 | |
07beea0d | 219 | return (var_ann_t) t->base.ann; |
6de9cd9a DN |
220 | } |
221 | ||
0566b51e DB |
222 | /* Return the variable annotation for T, which must be a _DECL node. |
223 | Create the variable annotation if it doesn't exist. */ | |
6de9cd9a DN |
224 | static inline var_ann_t |
225 | get_var_ann (tree var) | |
226 | { | |
227 | var_ann_t ann = var_ann (var); | |
228 | return (ann) ? ann : create_var_ann (var); | |
229 | } | |
230 | ||
3bfdb124 DB |
231 | /* Return the function annotation for T, which must be a FUNCTION_DECL node. |
232 | Return NULL if the function annotation doesn't already exist. */ | |
233 | static inline function_ann_t | |
234 | function_ann (tree t) | |
235 | { | |
236 | gcc_assert (t); | |
237 | gcc_assert (TREE_CODE (t) == FUNCTION_DECL); | |
07beea0d AH |
238 | gcc_assert (!t->base.ann |
239 | || t->base.ann->common.type == FUNCTION_ANN); | |
3bfdb124 | 240 | |
07beea0d | 241 | return (function_ann_t) t->base.ann; |
3bfdb124 DB |
242 | } |
243 | ||
244 | /* Return the function annotation for T, which must be a FUNCTION_DECL node. | |
245 | Create the function annotation if it doesn't exist. */ | |
246 | static inline function_ann_t | |
247 | get_function_ann (tree var) | |
248 | { | |
249 | function_ann_t ann = function_ann (var); | |
07beea0d | 250 | gcc_assert (!var->base.ann || var->base.ann->common.type == FUNCTION_ANN); |
3bfdb124 DB |
251 | return (ann) ? ann : create_function_ann (var); |
252 | } | |
253 | ||
83737db2 DB |
254 | /* Return true if T has a statement annotation attached to it. */ |
255 | ||
256 | static inline bool | |
257 | has_stmt_ann (tree t) | |
258 | { | |
259 | #ifdef ENABLE_CHECKING | |
260 | gcc_assert (is_gimple_stmt (t)); | |
261 | #endif | |
07beea0d | 262 | return t->base.ann && t->base.ann->common.type == STMT_ANN; |
83737db2 DB |
263 | } |
264 | ||
0566b51e DB |
265 | /* Return the statement annotation for T, which must be a statement |
266 | node. Return NULL if the statement annotation doesn't exist. */ | |
6de9cd9a DN |
267 | static inline stmt_ann_t |
268 | stmt_ann (tree t) | |
269 | { | |
1e128c5f GB |
270 | #ifdef ENABLE_CHECKING |
271 | gcc_assert (is_gimple_stmt (t)); | |
6de9cd9a | 272 | #endif |
07beea0d AH |
273 | gcc_assert (!t->base.ann || t->base.ann->common.type == STMT_ANN); |
274 | return (stmt_ann_t) t->base.ann; | |
6de9cd9a DN |
275 | } |
276 | ||
0566b51e DB |
277 | /* Return the statement annotation for T, which must be a statement |
278 | node. Create the statement annotation if it doesn't exist. */ | |
6de9cd9a DN |
279 | static inline stmt_ann_t |
280 | get_stmt_ann (tree stmt) | |
281 | { | |
282 | stmt_ann_t ann = stmt_ann (stmt); | |
283 | return (ann) ? ann : create_stmt_ann (stmt); | |
284 | } | |
285 | ||
0566b51e | 286 | /* Return the annotation type for annotation ANN. */ |
6de9cd9a | 287 | static inline enum tree_ann_type |
06d72ee6 | 288 | ann_type (tree_ann_t ann) |
6de9cd9a DN |
289 | { |
290 | return ann->common.type; | |
291 | } | |
292 | ||
0566b51e | 293 | /* Return the basic block for statement T. */ |
6de9cd9a DN |
294 | static inline basic_block |
295 | bb_for_stmt (tree t) | |
296 | { | |
30d396e3 ZD |
297 | stmt_ann_t ann; |
298 | ||
299 | if (TREE_CODE (t) == PHI_NODE) | |
300 | return PHI_BB (t); | |
301 | ||
302 | ann = stmt_ann (t); | |
6de9cd9a DN |
303 | return ann ? ann->bb : NULL; |
304 | } | |
305 | ||
306219a2 | 306 | /* Return the may_aliases bitmap for variable VAR, or NULL if it has |
0566b51e | 307 | no may aliases. */ |
306219a2 | 308 | static inline bitmap |
6de9cd9a DN |
309 | may_aliases (tree var) |
310 | { | |
306219a2 | 311 | return MTAG_ALIASES (var); |
6de9cd9a DN |
312 | } |
313 | ||
0566b51e DB |
314 | /* Return the line number for EXPR, or return -1 if we have no line |
315 | number information for it. */ | |
6de9cd9a DN |
316 | static inline int |
317 | get_lineno (tree expr) | |
318 | { | |
319 | if (expr == NULL_TREE) | |
320 | return -1; | |
321 | ||
322 | if (TREE_CODE (expr) == COMPOUND_EXPR) | |
323 | expr = TREE_OPERAND (expr, 0); | |
324 | ||
9506ac2b | 325 | if (! EXPR_HAS_LOCATION (expr)) |
6de9cd9a DN |
326 | return -1; |
327 | ||
328 | return EXPR_LINENO (expr); | |
329 | } | |
330 | ||
0566b51e DB |
331 | /* Return the file name for EXPR, or return "???" if we have no |
332 | filename information. */ | |
6de9cd9a DN |
333 | static inline const char * |
334 | get_filename (tree expr) | |
335 | { | |
9506ac2b | 336 | const char *filename; |
6de9cd9a DN |
337 | if (expr == NULL_TREE) |
338 | return "???"; | |
339 | ||
340 | if (TREE_CODE (expr) == COMPOUND_EXPR) | |
341 | expr = TREE_OPERAND (expr, 0); | |
342 | ||
9506ac2b PB |
343 | if (EXPR_HAS_LOCATION (expr) && (filename = EXPR_FILENAME (expr))) |
344 | return filename; | |
6de9cd9a DN |
345 | else |
346 | return "???"; | |
347 | } | |
348 | ||
7ded35b4 RS |
349 | /* Return true if T is a noreturn call. */ |
350 | static inline bool | |
351 | noreturn_call_p (tree t) | |
352 | { | |
353 | tree call = get_call_expr_in (t); | |
354 | return call != 0 && (call_expr_flags (call) & ECF_NORETURN) != 0; | |
355 | } | |
356 | ||
0566b51e | 357 | /* Mark statement T as modified. */ |
6de9cd9a | 358 | static inline void |
f430bae8 | 359 | mark_stmt_modified (tree t) |
6de9cd9a | 360 | { |
f430bae8 AM |
361 | stmt_ann_t ann; |
362 | if (TREE_CODE (t) == PHI_NODE) | |
363 | return; | |
364 | ||
365 | ann = stmt_ann (t); | |
6de9cd9a DN |
366 | if (ann == NULL) |
367 | ann = create_stmt_ann (t); | |
5cd4ec7f JH |
368 | else if (noreturn_call_p (t) && cfun->gimple_df) |
369 | VEC_safe_push (tree, gc, MODIFIED_NORETURN_CALLS (cfun), t); | |
6de9cd9a DN |
370 | ann->modified = 1; |
371 | } | |
372 | ||
f430bae8 | 373 | /* Mark statement T as modified, and update it. */ |
6de9cd9a | 374 | static inline void |
f430bae8 | 375 | update_stmt (tree t) |
6de9cd9a | 376 | { |
f430bae8 AM |
377 | if (TREE_CODE (t) == PHI_NODE) |
378 | return; | |
379 | mark_stmt_modified (t); | |
380 | update_stmt_operands (t); | |
381 | } | |
382 | ||
383 | static inline void | |
384 | update_stmt_if_modified (tree t) | |
385 | { | |
386 | if (stmt_modified_p (t)) | |
387 | update_stmt_operands (t); | |
388 | } | |
389 | ||
0566b51e | 390 | /* Return true if T is marked as modified, false otherwise. */ |
6de9cd9a DN |
391 | static inline bool |
392 | stmt_modified_p (tree t) | |
393 | { | |
394 | stmt_ann_t ann = stmt_ann (t); | |
395 | ||
396 | /* Note that if the statement doesn't yet have an annotation, we consider it | |
f430bae8 AM |
397 | modified. This will force the next call to update_stmt_operands to scan |
398 | the statement. */ | |
6de9cd9a DN |
399 | return ann ? ann->modified : true; |
400 | } | |
401 | ||
f430bae8 AM |
402 | /* Delink an immediate_uses node from its chain. */ |
403 | static inline void | |
f47c96aa | 404 | delink_imm_use (ssa_use_operand_t *linknode) |
f430bae8 AM |
405 | { |
406 | /* Return if this node is not in a list. */ | |
407 | if (linknode->prev == NULL) | |
408 | return; | |
409 | ||
410 | linknode->prev->next = linknode->next; | |
411 | linknode->next->prev = linknode->prev; | |
412 | linknode->prev = NULL; | |
413 | linknode->next = NULL; | |
414 | } | |
415 | ||
416 | /* Link ssa_imm_use node LINKNODE into the chain for LIST. */ | |
417 | static inline void | |
f47c96aa | 418 | link_imm_use_to_list (ssa_use_operand_t *linknode, ssa_use_operand_t *list) |
f430bae8 AM |
419 | { |
420 | /* Link the new node at the head of the list. If we are in the process of | |
be12e697 | 421 | traversing the list, we won't visit any new nodes added to it. */ |
f430bae8 AM |
422 | linknode->prev = list; |
423 | linknode->next = list->next; | |
424 | list->next->prev = linknode; | |
425 | list->next = linknode; | |
426 | } | |
427 | ||
428 | /* Link ssa_imm_use node LINKNODE into the chain for DEF. */ | |
429 | static inline void | |
f47c96aa | 430 | link_imm_use (ssa_use_operand_t *linknode, tree def) |
f430bae8 | 431 | { |
f47c96aa | 432 | ssa_use_operand_t *root; |
f430bae8 AM |
433 | |
434 | if (!def || TREE_CODE (def) != SSA_NAME) | |
435 | linknode->prev = NULL; | |
436 | else | |
437 | { | |
438 | root = &(SSA_NAME_IMM_USE_NODE (def)); | |
439 | #ifdef ENABLE_CHECKING | |
440 | if (linknode->use) | |
441 | gcc_assert (*(linknode->use) == def); | |
442 | #endif | |
443 | link_imm_use_to_list (linknode, root); | |
444 | } | |
445 | } | |
446 | ||
206048bd | 447 | /* Set the value of a use pointed to by USE to VAL. */ |
f430bae8 AM |
448 | static inline void |
449 | set_ssa_use_from_ptr (use_operand_p use, tree val) | |
450 | { | |
451 | delink_imm_use (use); | |
452 | *(use->use) = val; | |
453 | link_imm_use (use, val); | |
454 | } | |
455 | ||
0fa2e4df | 456 | /* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occurring |
f430bae8 AM |
457 | in STMT. */ |
458 | static inline void | |
f47c96aa | 459 | link_imm_use_stmt (ssa_use_operand_t *linknode, tree def, tree stmt) |
f430bae8 AM |
460 | { |
461 | if (stmt) | |
462 | link_imm_use (linknode, def); | |
463 | else | |
464 | link_imm_use (linknode, NULL); | |
465 | linknode->stmt = stmt; | |
466 | } | |
467 | ||
468 | /* Relink a new node in place of an old node in the list. */ | |
469 | static inline void | |
f47c96aa | 470 | relink_imm_use (ssa_use_operand_t *node, ssa_use_operand_t *old) |
f430bae8 | 471 | { |
f430bae8 | 472 | /* The node one had better be in the same list. */ |
0e61db61 | 473 | gcc_assert (*(old->use) == *(node->use)); |
f430bae8 AM |
474 | node->prev = old->prev; |
475 | node->next = old->next; | |
476 | if (old->prev) | |
477 | { | |
478 | old->prev->next = node; | |
479 | old->next->prev = node; | |
480 | /* Remove the old node from the list. */ | |
481 | old->prev = NULL; | |
482 | } | |
f430bae8 AM |
483 | } |
484 | ||
0fa2e4df | 485 | /* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occurring |
f430bae8 AM |
486 | in STMT. */ |
487 | static inline void | |
f47c96aa | 488 | relink_imm_use_stmt (ssa_use_operand_t *linknode, ssa_use_operand_t *old, tree stmt) |
f430bae8 AM |
489 | { |
490 | if (stmt) | |
491 | relink_imm_use (linknode, old); | |
492 | else | |
493 | link_imm_use (linknode, NULL); | |
494 | linknode->stmt = stmt; | |
495 | } | |
496 | ||
f430bae8 | 497 | |
f652d14b | 498 | /* Return true is IMM has reached the end of the immediate use list. */ |
f430bae8 AM |
499 | static inline bool |
500 | end_readonly_imm_use_p (imm_use_iterator *imm) | |
501 | { | |
502 | return (imm->imm_use == imm->end_p); | |
503 | } | |
504 | ||
505 | /* Initialize iterator IMM to process the list for VAR. */ | |
506 | static inline use_operand_p | |
507 | first_readonly_imm_use (imm_use_iterator *imm, tree var) | |
508 | { | |
509 | gcc_assert (TREE_CODE (var) == SSA_NAME); | |
510 | ||
511 | imm->end_p = &(SSA_NAME_IMM_USE_NODE (var)); | |
512 | imm->imm_use = imm->end_p->next; | |
513 | #ifdef ENABLE_CHECKING | |
514 | imm->iter_node.next = imm->imm_use->next; | |
515 | #endif | |
516 | if (end_readonly_imm_use_p (imm)) | |
517 | return NULL_USE_OPERAND_P; | |
518 | return imm->imm_use; | |
519 | } | |
520 | ||
d566f6ef | 521 | /* Bump IMM to the next use in the list. */ |
f430bae8 AM |
522 | static inline use_operand_p |
523 | next_readonly_imm_use (imm_use_iterator *imm) | |
524 | { | |
525 | use_operand_p old = imm->imm_use; | |
526 | ||
527 | #ifdef ENABLE_CHECKING | |
528 | /* If this assertion fails, it indicates the 'next' pointer has changed | |
529 | since we the last bump. This indicates that the list is being modified | |
530 | via stmt changes, or SET_USE, or somesuch thing, and you need to be | |
531 | using the SAFE version of the iterator. */ | |
532 | gcc_assert (imm->iter_node.next == old->next); | |
533 | imm->iter_node.next = old->next->next; | |
534 | #endif | |
535 | ||
536 | imm->imm_use = old->next; | |
537 | if (end_readonly_imm_use_p (imm)) | |
538 | return old; | |
539 | return imm->imm_use; | |
540 | } | |
541 | ||
542 | /* Return true if VAR has no uses. */ | |
543 | static inline bool | |
544 | has_zero_uses (tree var) | |
545 | { | |
f47c96aa | 546 | ssa_use_operand_t *ptr; |
f430bae8 AM |
547 | ptr = &(SSA_NAME_IMM_USE_NODE (var)); |
548 | /* A single use means there is no items in the list. */ | |
549 | return (ptr == ptr->next); | |
550 | } | |
551 | ||
552 | /* Return true if VAR has a single use. */ | |
553 | static inline bool | |
554 | has_single_use (tree var) | |
555 | { | |
f47c96aa | 556 | ssa_use_operand_t *ptr; |
f430bae8 AM |
557 | ptr = &(SSA_NAME_IMM_USE_NODE (var)); |
558 | /* A single use means there is one item in the list. */ | |
559 | return (ptr != ptr->next && ptr == ptr->next->next); | |
560 | } | |
561 | ||
7290d709 | 562 | |
f430bae8 | 563 | /* If VAR has only a single immediate use, return true, and set USE_P and STMT |
f652d14b | 564 | to the use pointer and stmt of occurrence. */ |
f430bae8 AM |
565 | static inline bool |
566 | single_imm_use (tree var, use_operand_p *use_p, tree *stmt) | |
567 | { | |
f47c96aa | 568 | ssa_use_operand_t *ptr; |
f430bae8 AM |
569 | |
570 | ptr = &(SSA_NAME_IMM_USE_NODE (var)); | |
571 | if (ptr != ptr->next && ptr == ptr->next->next) | |
572 | { | |
573 | *use_p = ptr->next; | |
574 | *stmt = ptr->next->stmt; | |
575 | return true; | |
576 | } | |
577 | *use_p = NULL_USE_OPERAND_P; | |
578 | *stmt = NULL_TREE; | |
579 | return false; | |
580 | } | |
581 | ||
582 | /* Return the number of immediate uses of VAR. */ | |
583 | static inline unsigned int | |
584 | num_imm_uses (tree var) | |
585 | { | |
f47c96aa | 586 | ssa_use_operand_t *ptr, *start; |
f430bae8 AM |
587 | unsigned int num; |
588 | ||
589 | start = &(SSA_NAME_IMM_USE_NODE (var)); | |
590 | num = 0; | |
591 | for (ptr = start->next; ptr != start; ptr = ptr->next) | |
592 | num++; | |
593 | ||
594 | return num; | |
595 | } | |
596 | ||
d00ad49b AM |
597 | /* Return the tree pointer to by USE. */ |
598 | static inline tree | |
599 | get_use_from_ptr (use_operand_p use) | |
600 | { | |
f430bae8 | 601 | return *(use->use); |
d00ad49b AM |
602 | } |
603 | ||
604 | /* Return the tree pointer to by DEF. */ | |
605 | static inline tree | |
606 | get_def_from_ptr (def_operand_p def) | |
607 | { | |
f47c96aa | 608 | return *def; |
d00ad49b AM |
609 | } |
610 | ||
611 | /* Return a def_operand_p pointer for the result of PHI. */ | |
612 | static inline def_operand_p | |
613 | get_phi_result_ptr (tree phi) | |
614 | { | |
f47c96aa | 615 | return &(PHI_RESULT_TREE (phi)); |
a32b97a2 BB |
616 | } |
617 | ||
d00ad49b AM |
618 | /* Return a use_operand_p pointer for argument I of phinode PHI. */ |
619 | static inline use_operand_p | |
620 | get_phi_arg_def_ptr (tree phi, int i) | |
621 | { | |
f430bae8 | 622 | return &(PHI_ARG_IMM_USE_NODE (phi,i)); |
6de9cd9a DN |
623 | } |
624 | ||
e54d0214 | 625 | |
f430bae8 AM |
626 | /* Return the bitmap of addresses taken by STMT, or NULL if it takes |
627 | no addresses. */ | |
628 | static inline bitmap | |
629 | addresses_taken (tree stmt) | |
630 | { | |
631 | stmt_ann_t ann = stmt_ann (stmt); | |
632 | return ann ? ann->addresses_taken : NULL; | |
6de9cd9a DN |
633 | } |
634 | ||
0566b51e DB |
635 | /* Return the PHI nodes for basic block BB, or NULL if there are no |
636 | PHI nodes. */ | |
6de9cd9a DN |
637 | static inline tree |
638 | phi_nodes (basic_block bb) | |
639 | { | |
4aab792d | 640 | return bb->phi_nodes; |
6de9cd9a DN |
641 | } |
642 | ||
643 | /* Set list of phi nodes of a basic block BB to L. */ | |
644 | ||
645 | static inline void | |
646 | set_phi_nodes (basic_block bb, tree l) | |
647 | { | |
648 | tree phi; | |
649 | ||
4aab792d | 650 | bb->phi_nodes = l; |
17192884 | 651 | for (phi = l; phi; phi = PHI_CHAIN (phi)) |
6de9cd9a DN |
652 | set_bb_for_stmt (phi, bb); |
653 | } | |
654 | ||
f430bae8 AM |
655 | /* Return the phi argument which contains the specified use. */ |
656 | ||
657 | static inline int | |
658 | phi_arg_index_from_use (use_operand_p use) | |
659 | { | |
660 | struct phi_arg_d *element, *root; | |
661 | int index; | |
662 | tree phi; | |
663 | ||
f652d14b | 664 | /* Since the use is the first thing in a PHI argument element, we can |
f430bae8 AM |
665 | calculate its index based on casting it to an argument, and performing |
666 | pointer arithmetic. */ | |
667 | ||
668 | phi = USE_STMT (use); | |
669 | gcc_assert (TREE_CODE (phi) == PHI_NODE); | |
670 | ||
671 | element = (struct phi_arg_d *)use; | |
672 | root = &(PHI_ARG_ELT (phi, 0)); | |
673 | index = element - root; | |
674 | ||
675 | #ifdef ENABLE_CHECKING | |
676 | /* Make sure the calculation doesn't have any leftover bytes. If it does, | |
f652d14b | 677 | then imm_use is likely not the first element in phi_arg_d. */ |
f430bae8 AM |
678 | gcc_assert ( |
679 | (((char *)element - (char *)root) % sizeof (struct phi_arg_d)) == 0); | |
680 | gcc_assert (index >= 0 && index < PHI_ARG_CAPACITY (phi)); | |
681 | #endif | |
682 | ||
683 | return index; | |
684 | } | |
685 | ||
727a31fa RH |
686 | /* Mark VAR as used, so that it'll be preserved during rtl expansion. */ |
687 | ||
688 | static inline void | |
689 | set_is_used (tree var) | |
690 | { | |
691 | var_ann_t ann = get_var_ann (var); | |
692 | ann->used = 1; | |
693 | } | |
694 | ||
0566b51e | 695 | /* Return true if T is an executable statement. */ |
6de9cd9a DN |
696 | static inline bool |
697 | is_exec_stmt (tree t) | |
698 | { | |
699 | return (t && !IS_EMPTY_STMT (t) && t != error_mark_node); | |
700 | } | |
701 | ||
702 | ||
703 | /* Return true if this stmt can be the target of a control transfer stmt such | |
704 | as a goto. */ | |
705 | static inline bool | |
706 | is_label_stmt (tree t) | |
707 | { | |
708 | if (t) | |
709 | switch (TREE_CODE (t)) | |
710 | { | |
711 | case LABEL_DECL: | |
712 | case LABEL_EXPR: | |
713 | case CASE_LABEL_EXPR: | |
714 | return true; | |
715 | default: | |
716 | return false; | |
717 | } | |
718 | return false; | |
719 | } | |
720 | ||
6de9cd9a DN |
721 | /* PHI nodes should contain only ssa_names and invariants. A test |
722 | for ssa_name is definitely simpler; don't let invalid contents | |
723 | slip in in the meantime. */ | |
724 | ||
725 | static inline bool | |
726 | phi_ssa_name_p (tree t) | |
727 | { | |
728 | if (TREE_CODE (t) == SSA_NAME) | |
729 | return true; | |
730 | #ifdef ENABLE_CHECKING | |
1e128c5f | 731 | gcc_assert (is_gimple_min_invariant (t)); |
6de9cd9a DN |
732 | #endif |
733 | return false; | |
734 | } | |
735 | ||
736 | /* ----------------------------------------------------------------------- */ | |
737 | ||
0566b51e DB |
738 | /* Return a block_stmt_iterator that points to beginning of basic |
739 | block BB. */ | |
6de9cd9a DN |
740 | static inline block_stmt_iterator |
741 | bsi_start (basic_block bb) | |
742 | { | |
743 | block_stmt_iterator bsi; | |
744 | if (bb->stmt_list) | |
745 | bsi.tsi = tsi_start (bb->stmt_list); | |
746 | else | |
747 | { | |
24bd1a0b | 748 | gcc_assert (bb->index < NUM_FIXED_BLOCKS); |
6de9cd9a DN |
749 | bsi.tsi.ptr = NULL; |
750 | bsi.tsi.container = NULL; | |
751 | } | |
752 | bsi.bb = bb; | |
753 | return bsi; | |
754 | } | |
755 | ||
93954fcc | 756 | /* Return a block statement iterator that points to the first non-label |
35771d34 | 757 | statement in block BB. */ |
d7621d3c ZD |
758 | |
759 | static inline block_stmt_iterator | |
760 | bsi_after_labels (basic_block bb) | |
761 | { | |
35771d34 | 762 | block_stmt_iterator bsi = bsi_start (bb); |
d7621d3c | 763 | |
35771d34 PB |
764 | while (!bsi_end_p (bsi) && TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR) |
765 | bsi_next (&bsi); | |
d7621d3c ZD |
766 | |
767 | return bsi; | |
768 | } | |
769 | ||
0566b51e DB |
770 | /* Return a block statement iterator that points to the end of basic |
771 | block BB. */ | |
6de9cd9a DN |
772 | static inline block_stmt_iterator |
773 | bsi_last (basic_block bb) | |
774 | { | |
775 | block_stmt_iterator bsi; | |
776 | if (bb->stmt_list) | |
777 | bsi.tsi = tsi_last (bb->stmt_list); | |
778 | else | |
779 | { | |
24bd1a0b | 780 | gcc_assert (bb->index < NUM_FIXED_BLOCKS); |
6de9cd9a DN |
781 | bsi.tsi.ptr = NULL; |
782 | bsi.tsi.container = NULL; | |
783 | } | |
784 | bsi.bb = bb; | |
785 | return bsi; | |
786 | } | |
787 | ||
0566b51e DB |
788 | /* Return true if block statement iterator I has reached the end of |
789 | the basic block. */ | |
6de9cd9a DN |
790 | static inline bool |
791 | bsi_end_p (block_stmt_iterator i) | |
792 | { | |
793 | return tsi_end_p (i.tsi); | |
794 | } | |
795 | ||
0566b51e DB |
796 | /* Modify block statement iterator I so that it is at the next |
797 | statement in the basic block. */ | |
6de9cd9a DN |
798 | static inline void |
799 | bsi_next (block_stmt_iterator *i) | |
800 | { | |
801 | tsi_next (&i->tsi); | |
802 | } | |
803 | ||
0566b51e DB |
804 | /* Modify block statement iterator I so that it is at the previous |
805 | statement in the basic block. */ | |
6de9cd9a DN |
806 | static inline void |
807 | bsi_prev (block_stmt_iterator *i) | |
808 | { | |
809 | tsi_prev (&i->tsi); | |
810 | } | |
811 | ||
0566b51e DB |
812 | /* Return the statement that block statement iterator I is currently |
813 | at. */ | |
6de9cd9a DN |
814 | static inline tree |
815 | bsi_stmt (block_stmt_iterator i) | |
816 | { | |
817 | return tsi_stmt (i.tsi); | |
818 | } | |
819 | ||
0566b51e DB |
820 | /* Return a pointer to the statement that block statement iterator I |
821 | is currently at. */ | |
6de9cd9a DN |
822 | static inline tree * |
823 | bsi_stmt_ptr (block_stmt_iterator i) | |
824 | { | |
825 | return tsi_stmt_ptr (i.tsi); | |
826 | } | |
827 | ||
9baba81b SP |
828 | /* Returns the loop of the statement STMT. */ |
829 | ||
830 | static inline struct loop * | |
831 | loop_containing_stmt (tree stmt) | |
832 | { | |
833 | basic_block bb = bb_for_stmt (stmt); | |
834 | if (!bb) | |
835 | return NULL; | |
836 | ||
837 | return bb->loop_father; | |
838 | } | |
839 | ||
38635499 DN |
840 | |
841 | /* Return the memory partition tag associated with symbol SYM. */ | |
842 | ||
843 | static inline tree | |
844 | memory_partition (tree sym) | |
845 | { | |
846 | tree tag; | |
847 | ||
848 | /* MPTs belong to their own partition. */ | |
849 | if (TREE_CODE (sym) == MEMORY_PARTITION_TAG) | |
850 | return sym; | |
851 | ||
852 | gcc_assert (!is_gimple_reg (sym)); | |
853 | tag = get_var_ann (sym)->mpt; | |
854 | ||
855 | #if defined ENABLE_CHECKING | |
856 | if (tag) | |
857 | gcc_assert (TREE_CODE (tag) == MEMORY_PARTITION_TAG); | |
858 | #endif | |
859 | ||
860 | return tag; | |
861 | } | |
862 | ||
863 | ||
864 | /* Set MPT to be the memory partition associated with symbol SYM. */ | |
865 | ||
866 | static inline void | |
867 | set_memory_partition (tree sym, tree mpt) | |
868 | { | |
869 | #if defined ENABLE_CHECKING | |
870 | if (mpt) | |
871 | gcc_assert (TREE_CODE (mpt) == MEMORY_PARTITION_TAG | |
872 | && !is_gimple_reg (sym)); | |
873 | #endif | |
874 | var_ann (sym)->mpt = mpt; | |
875 | if (mpt) | |
876 | { | |
877 | bitmap_set_bit (MPT_SYMBOLS (mpt), DECL_UID (sym)); | |
878 | ||
879 | /* MPT inherits the call-clobbering attributes from SYM. */ | |
880 | if (is_call_clobbered (sym)) | |
881 | { | |
882 | MTAG_GLOBAL (mpt) = 1; | |
883 | mark_call_clobbered (mpt, ESCAPE_IS_GLOBAL); | |
884 | } | |
885 | } | |
886 | } | |
887 | ||
888 | /* Return true if NAME is a memory factoring SSA name (i.e., an SSA | |
889 | name for a memory partition. */ | |
890 | ||
891 | static inline bool | |
892 | factoring_name_p (tree name) | |
893 | { | |
894 | return TREE_CODE (SSA_NAME_VAR (name)) == MEMORY_PARTITION_TAG; | |
895 | } | |
896 | ||
0566b51e | 897 | /* Return true if VAR is a clobbered by function calls. */ |
6de9cd9a DN |
898 | static inline bool |
899 | is_call_clobbered (tree var) | |
900 | { | |
fe1f8f44 | 901 | if (!MTAG_P (var)) |
b730fa61 | 902 | return var_ann (var)->call_clobbered; |
fe1f8f44 | 903 | else |
5cd4ec7f | 904 | return bitmap_bit_p (gimple_call_clobbered_vars (cfun), DECL_UID (var)); |
6de9cd9a DN |
905 | } |
906 | ||
0566b51e | 907 | /* Mark variable VAR as being clobbered by function calls. */ |
6de9cd9a | 908 | static inline void |
d16a5e36 | 909 | mark_call_clobbered (tree var, unsigned int escape_type) |
6de9cd9a | 910 | { |
d16a5e36 | 911 | var_ann (var)->escape_mask |= escape_type; |
fe1f8f44 | 912 | if (!MTAG_P (var)) |
b730fa61 | 913 | var_ann (var)->call_clobbered = true; |
5cd4ec7f | 914 | bitmap_set_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var)); |
6de9cd9a DN |
915 | } |
916 | ||
90e34bd6 DN |
917 | /* Clear the call-clobbered attribute from variable VAR. */ |
918 | static inline void | |
919 | clear_call_clobbered (tree var) | |
920 | { | |
d16a5e36 DB |
921 | var_ann_t ann = var_ann (var); |
922 | ann->escape_mask = 0; | |
326eda4b DB |
923 | if (MTAG_P (var) && TREE_CODE (var) != STRUCT_FIELD_TAG) |
924 | MTAG_GLOBAL (var) = 0; | |
fe1f8f44 | 925 | if (!MTAG_P (var)) |
b730fa61 | 926 | var_ann (var)->call_clobbered = false; |
5cd4ec7f | 927 | bitmap_clear_bit (gimple_call_clobbered_vars (cfun), DECL_UID (var)); |
90e34bd6 DN |
928 | } |
929 | ||
06d72ee6 DB |
930 | /* Return the common annotation for T. Return NULL if the annotation |
931 | doesn't already exist. */ | |
93c094b5 JH |
932 | static inline tree_ann_common_t |
933 | tree_common_ann (tree t) | |
06d72ee6 | 934 | { |
6ac5a246 JH |
935 | /* Watch out static variables with unshared annotations. */ |
936 | if (DECL_P (t) && TREE_CODE (t) == VAR_DECL) | |
937 | return &var_ann (t)->common; | |
07beea0d | 938 | return &t->base.ann->common; |
06d72ee6 DB |
939 | } |
940 | ||
941 | /* Return a common annotation for T. Create the constant annotation if it | |
942 | doesn't exist. */ | |
93c094b5 JH |
943 | static inline tree_ann_common_t |
944 | get_tree_common_ann (tree t) | |
06d72ee6 | 945 | { |
93c094b5 JH |
946 | tree_ann_common_t ann = tree_common_ann (t); |
947 | return (ann) ? ann : create_tree_common_ann (t); | |
06d72ee6 DB |
948 | } |
949 | ||
4c124b4c AM |
950 | /* ----------------------------------------------------------------------- */ |
951 | ||
952 | /* The following set of routines are used to iterator over various type of | |
953 | SSA operands. */ | |
954 | ||
955 | /* Return true if PTR is finished iterating. */ | |
956 | static inline bool | |
957 | op_iter_done (ssa_op_iter *ptr) | |
958 | { | |
959 | return ptr->done; | |
960 | } | |
961 | ||
962 | /* Get the next iterator use value for PTR. */ | |
963 | static inline use_operand_p | |
964 | op_iter_next_use (ssa_op_iter *ptr) | |
965 | { | |
f47c96aa AM |
966 | use_operand_p use_p; |
967 | #ifdef ENABLE_CHECKING | |
968 | gcc_assert (ptr->iter_type == ssa_op_iter_use); | |
969 | #endif | |
970 | if (ptr->uses) | |
4c124b4c | 971 | { |
f47c96aa AM |
972 | use_p = USE_OP_PTR (ptr->uses); |
973 | ptr->uses = ptr->uses->next; | |
974 | return use_p; | |
4c124b4c | 975 | } |
f47c96aa | 976 | if (ptr->vuses) |
4c124b4c | 977 | { |
38635499 DN |
978 | use_p = VUSE_OP_PTR (ptr->vuses, ptr->vuse_index); |
979 | if (++(ptr->vuse_index) >= VUSE_NUM (ptr->vuses)) | |
980 | { | |
981 | ptr->vuse_index = 0; | |
982 | ptr->vuses = ptr->vuses->next; | |
983 | } | |
f47c96aa | 984 | return use_p; |
4c124b4c | 985 | } |
f47c96aa | 986 | if (ptr->mayuses) |
4c124b4c | 987 | { |
38635499 DN |
988 | use_p = VDEF_OP_PTR (ptr->mayuses, ptr->mayuse_index); |
989 | if (++(ptr->mayuse_index) >= VDEF_NUM (ptr->mayuses)) | |
990 | { | |
991 | ptr->mayuse_index = 0; | |
992 | ptr->mayuses = ptr->mayuses->next; | |
993 | } | |
f47c96aa AM |
994 | return use_p; |
995 | } | |
996 | if (ptr->phi_i < ptr->num_phi) | |
997 | { | |
998 | return PHI_ARG_DEF_PTR (ptr->phi_stmt, (ptr->phi_i)++); | |
4c124b4c AM |
999 | } |
1000 | ptr->done = true; | |
1001 | return NULL_USE_OPERAND_P; | |
1002 | } | |
1003 | ||
1004 | /* Get the next iterator def value for PTR. */ | |
1005 | static inline def_operand_p | |
1006 | op_iter_next_def (ssa_op_iter *ptr) | |
1007 | { | |
f47c96aa AM |
1008 | def_operand_p def_p; |
1009 | #ifdef ENABLE_CHECKING | |
1010 | gcc_assert (ptr->iter_type == ssa_op_iter_def); | |
1011 | #endif | |
1012 | if (ptr->defs) | |
4c124b4c | 1013 | { |
f47c96aa AM |
1014 | def_p = DEF_OP_PTR (ptr->defs); |
1015 | ptr->defs = ptr->defs->next; | |
1016 | return def_p; | |
4c124b4c | 1017 | } |
38635499 | 1018 | if (ptr->vdefs) |
4c124b4c | 1019 | { |
38635499 DN |
1020 | def_p = VDEF_RESULT_PTR (ptr->vdefs); |
1021 | ptr->vdefs = ptr->vdefs->next; | |
f47c96aa | 1022 | return def_p; |
4c124b4c AM |
1023 | } |
1024 | ptr->done = true; | |
1025 | return NULL_DEF_OPERAND_P; | |
1026 | } | |
1027 | ||
1028 | /* Get the next iterator tree value for PTR. */ | |
1029 | static inline tree | |
1030 | op_iter_next_tree (ssa_op_iter *ptr) | |
1031 | { | |
f47c96aa AM |
1032 | tree val; |
1033 | #ifdef ENABLE_CHECKING | |
1034 | gcc_assert (ptr->iter_type == ssa_op_iter_tree); | |
1035 | #endif | |
1036 | if (ptr->uses) | |
4c124b4c | 1037 | { |
f47c96aa AM |
1038 | val = USE_OP (ptr->uses); |
1039 | ptr->uses = ptr->uses->next; | |
1040 | return val; | |
4c124b4c | 1041 | } |
f47c96aa | 1042 | if (ptr->vuses) |
4c124b4c | 1043 | { |
38635499 DN |
1044 | val = VUSE_OP (ptr->vuses, ptr->vuse_index); |
1045 | if (++(ptr->vuse_index) >= VUSE_NUM (ptr->vuses)) | |
1046 | { | |
1047 | ptr->vuse_index = 0; | |
1048 | ptr->vuses = ptr->vuses->next; | |
1049 | } | |
f47c96aa | 1050 | return val; |
4c124b4c | 1051 | } |
f47c96aa | 1052 | if (ptr->mayuses) |
4c124b4c | 1053 | { |
38635499 DN |
1054 | val = VDEF_OP (ptr->mayuses, ptr->mayuse_index); |
1055 | if (++(ptr->mayuse_index) >= VDEF_NUM (ptr->mayuses)) | |
1056 | { | |
1057 | ptr->mayuse_index = 0; | |
1058 | ptr->mayuses = ptr->mayuses->next; | |
1059 | } | |
f47c96aa | 1060 | return val; |
52328bf6 | 1061 | } |
f47c96aa | 1062 | if (ptr->defs) |
4c124b4c | 1063 | { |
f47c96aa AM |
1064 | val = DEF_OP (ptr->defs); |
1065 | ptr->defs = ptr->defs->next; | |
1066 | return val; | |
4c124b4c | 1067 | } |
38635499 | 1068 | if (ptr->vdefs) |
4c124b4c | 1069 | { |
38635499 DN |
1070 | val = VDEF_RESULT (ptr->vdefs); |
1071 | ptr->vdefs = ptr->vdefs->next; | |
f47c96aa | 1072 | return val; |
4c124b4c | 1073 | } |
f47c96aa AM |
1074 | |
1075 | ptr->done = true; | |
1076 | return NULL_TREE; | |
1077 | ||
1078 | } | |
1079 | ||
1080 | ||
395bda42 | 1081 | /* This functions clears the iterator PTR, and marks it done. This is normally |
c83eecad | 1082 | used to prevent warnings in the compile about might be uninitialized |
f47c96aa AM |
1083 | components. */ |
1084 | ||
1085 | static inline void | |
1086 | clear_and_done_ssa_iter (ssa_op_iter *ptr) | |
1087 | { | |
1088 | ptr->defs = NULL; | |
1089 | ptr->uses = NULL; | |
1090 | ptr->vuses = NULL; | |
38635499 | 1091 | ptr->vdefs = NULL; |
f47c96aa | 1092 | ptr->mayuses = NULL; |
f47c96aa AM |
1093 | ptr->iter_type = ssa_op_iter_none; |
1094 | ptr->phi_i = 0; | |
1095 | ptr->num_phi = 0; | |
1096 | ptr->phi_stmt = NULL_TREE; | |
4c124b4c | 1097 | ptr->done = true; |
38635499 DN |
1098 | ptr->vuse_index = 0; |
1099 | ptr->mayuse_index = 0; | |
4c124b4c AM |
1100 | } |
1101 | ||
1102 | /* Initialize the iterator PTR to the virtual defs in STMT. */ | |
1103 | static inline void | |
1104 | op_iter_init (ssa_op_iter *ptr, tree stmt, int flags) | |
1105 | { | |
f47c96aa AM |
1106 | #ifdef ENABLE_CHECKING |
1107 | gcc_assert (stmt_ann (stmt)); | |
1108 | #endif | |
4c124b4c | 1109 | |
f47c96aa AM |
1110 | ptr->defs = (flags & SSA_OP_DEF) ? DEF_OPS (stmt) : NULL; |
1111 | ptr->uses = (flags & SSA_OP_USE) ? USE_OPS (stmt) : NULL; | |
1112 | ptr->vuses = (flags & SSA_OP_VUSE) ? VUSE_OPS (stmt) : NULL; | |
38635499 DN |
1113 | ptr->vdefs = (flags & SSA_OP_VDEF) ? VDEF_OPS (stmt) : NULL; |
1114 | ptr->mayuses = (flags & SSA_OP_VMAYUSE) ? VDEF_OPS (stmt) : NULL; | |
4c124b4c | 1115 | ptr->done = false; |
f47c96aa AM |
1116 | |
1117 | ptr->phi_i = 0; | |
1118 | ptr->num_phi = 0; | |
1119 | ptr->phi_stmt = NULL_TREE; | |
38635499 DN |
1120 | ptr->vuse_index = 0; |
1121 | ptr->mayuse_index = 0; | |
4c124b4c AM |
1122 | } |
1123 | ||
1124 | /* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return | |
1125 | the first use. */ | |
1126 | static inline use_operand_p | |
1127 | op_iter_init_use (ssa_op_iter *ptr, tree stmt, int flags) | |
1128 | { | |
66d3fe47 | 1129 | gcc_assert ((flags & SSA_OP_ALL_DEFS) == 0); |
4c124b4c | 1130 | op_iter_init (ptr, stmt, flags); |
f47c96aa | 1131 | ptr->iter_type = ssa_op_iter_use; |
4c124b4c AM |
1132 | return op_iter_next_use (ptr); |
1133 | } | |
1134 | ||
1135 | /* Initialize iterator PTR to the def operands in STMT based on FLAGS. Return | |
1136 | the first def. */ | |
1137 | static inline def_operand_p | |
1138 | op_iter_init_def (ssa_op_iter *ptr, tree stmt, int flags) | |
1139 | { | |
38635499 | 1140 | gcc_assert ((flags & SSA_OP_ALL_USES) == 0); |
4c124b4c | 1141 | op_iter_init (ptr, stmt, flags); |
f47c96aa | 1142 | ptr->iter_type = ssa_op_iter_def; |
4c124b4c AM |
1143 | return op_iter_next_def (ptr); |
1144 | } | |
1145 | ||
1146 | /* Initialize iterator PTR to the operands in STMT based on FLAGS. Return | |
1147 | the first operand as a tree. */ | |
1148 | static inline tree | |
1149 | op_iter_init_tree (ssa_op_iter *ptr, tree stmt, int flags) | |
1150 | { | |
1151 | op_iter_init (ptr, stmt, flags); | |
f47c96aa | 1152 | ptr->iter_type = ssa_op_iter_tree; |
4c124b4c AM |
1153 | return op_iter_next_tree (ptr); |
1154 | } | |
1155 | ||
52328bf6 DB |
1156 | /* Get the next iterator mustdef value for PTR, returning the mustdef values in |
1157 | KILL and DEF. */ | |
1158 | static inline void | |
38635499 | 1159 | op_iter_next_vdef (vuse_vec_p *use, def_operand_p *def, |
f47c96aa | 1160 | ssa_op_iter *ptr) |
52328bf6 | 1161 | { |
f47c96aa | 1162 | #ifdef ENABLE_CHECKING |
38635499 | 1163 | gcc_assert (ptr->iter_type == ssa_op_iter_vdef); |
f47c96aa AM |
1164 | #endif |
1165 | if (ptr->mayuses) | |
52328bf6 | 1166 | { |
38635499 DN |
1167 | *def = VDEF_RESULT_PTR (ptr->mayuses); |
1168 | *use = VDEF_VECT (ptr->mayuses); | |
f47c96aa | 1169 | ptr->mayuses = ptr->mayuses->next; |
52328bf6 DB |
1170 | return; |
1171 | } | |
db30731a | 1172 | |
f47c96aa | 1173 | *def = NULL_DEF_OPERAND_P; |
38635499 | 1174 | *use = NULL; |
db30731a JL |
1175 | ptr->done = true; |
1176 | return; | |
1177 | } | |
1178 | ||
f47c96aa | 1179 | |
4c124b4c | 1180 | static inline void |
38635499 DN |
1181 | op_iter_next_mustdef (use_operand_p *use, def_operand_p *def, |
1182 | ssa_op_iter *ptr) | |
4c124b4c | 1183 | { |
38635499 DN |
1184 | vuse_vec_p vp; |
1185 | op_iter_next_vdef (&vp, def, ptr); | |
1186 | if (vp != NULL) | |
1187 | { | |
1188 | gcc_assert (VUSE_VECT_NUM_ELEM (*vp) == 1); | |
1189 | *use = VUSE_ELEMENT_PTR (*vp, 0); | |
1190 | } | |
1191 | else | |
1192 | *use = NULL_USE_OPERAND_P; | |
4c124b4c | 1193 | } |
52328bf6 DB |
1194 | |
1195 | /* Initialize iterator PTR to the operands in STMT. Return the first operands | |
38635499 | 1196 | in USE and DEF. */ |
52328bf6 | 1197 | static inline void |
38635499 | 1198 | op_iter_init_vdef (ssa_op_iter *ptr, tree stmt, vuse_vec_p *use, |
52328bf6 DB |
1199 | def_operand_p *def) |
1200 | { | |
f47c96aa AM |
1201 | gcc_assert (TREE_CODE (stmt) != PHI_NODE); |
1202 | ||
38635499 DN |
1203 | op_iter_init (ptr, stmt, SSA_OP_VMAYUSE); |
1204 | ptr->iter_type = ssa_op_iter_vdef; | |
1205 | op_iter_next_vdef (use, def, ptr); | |
f47c96aa AM |
1206 | } |
1207 | ||
1208 | ||
395bda42 | 1209 | /* If there is a single operand in STMT matching FLAGS, return it. Otherwise |
d7770457 | 1210 | return NULL. */ |
f47c96aa AM |
1211 | static inline tree |
1212 | single_ssa_tree_operand (tree stmt, int flags) | |
1213 | { | |
1214 | tree var; | |
1215 | ssa_op_iter iter; | |
1216 | ||
1217 | var = op_iter_init_tree (&iter, stmt, flags); | |
1218 | if (op_iter_done (&iter)) | |
1219 | return NULL_TREE; | |
1220 | op_iter_next_tree (&iter); | |
1221 | if (op_iter_done (&iter)) | |
1222 | return var; | |
1223 | return NULL_TREE; | |
1224 | } | |
1225 | ||
1226 | ||
395bda42 | 1227 | /* If there is a single operand in STMT matching FLAGS, return it. Otherwise |
d7770457 | 1228 | return NULL. */ |
f47c96aa AM |
1229 | static inline use_operand_p |
1230 | single_ssa_use_operand (tree stmt, int flags) | |
1231 | { | |
1232 | use_operand_p var; | |
1233 | ssa_op_iter iter; | |
1234 | ||
1235 | var = op_iter_init_use (&iter, stmt, flags); | |
1236 | if (op_iter_done (&iter)) | |
1237 | return NULL_USE_OPERAND_P; | |
1238 | op_iter_next_use (&iter); | |
1239 | if (op_iter_done (&iter)) | |
1240 | return var; | |
1241 | return NULL_USE_OPERAND_P; | |
1242 | } | |
1243 | ||
1244 | ||
1245 | ||
395bda42 | 1246 | /* If there is a single operand in STMT matching FLAGS, return it. Otherwise |
d7770457 | 1247 | return NULL. */ |
f47c96aa AM |
1248 | static inline def_operand_p |
1249 | single_ssa_def_operand (tree stmt, int flags) | |
1250 | { | |
1251 | def_operand_p var; | |
1252 | ssa_op_iter iter; | |
1253 | ||
1254 | var = op_iter_init_def (&iter, stmt, flags); | |
1255 | if (op_iter_done (&iter)) | |
1256 | return NULL_DEF_OPERAND_P; | |
1257 | op_iter_next_def (&iter); | |
1258 | if (op_iter_done (&iter)) | |
1259 | return var; | |
1260 | return NULL_DEF_OPERAND_P; | |
1261 | } | |
1262 | ||
1263 | ||
e1bb14ca DB |
1264 | /* Return true if there are zero operands in STMT matching the type |
1265 | given in FLAGS. */ | |
f47c96aa AM |
1266 | static inline bool |
1267 | zero_ssa_operands (tree stmt, int flags) | |
1268 | { | |
1269 | ssa_op_iter iter; | |
1270 | ||
1271 | op_iter_init_tree (&iter, stmt, flags); | |
1272 | return op_iter_done (&iter); | |
db30731a JL |
1273 | } |
1274 | ||
f47c96aa | 1275 | |
395bda42 | 1276 | /* Return the number of operands matching FLAGS in STMT. */ |
f47c96aa AM |
1277 | static inline int |
1278 | num_ssa_operands (tree stmt, int flags) | |
1279 | { | |
1280 | ssa_op_iter iter; | |
66d3fe47 | 1281 | tree t; |
f47c96aa AM |
1282 | int num = 0; |
1283 | ||
66d3fe47 | 1284 | FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, flags) |
f47c96aa | 1285 | num++; |
f47c96aa AM |
1286 | return num; |
1287 | } | |
1288 | ||
1289 | ||
1290 | /* Delink all immediate_use information for STMT. */ | |
1291 | static inline void | |
1292 | delink_stmt_imm_use (tree stmt) | |
1293 | { | |
1294 | ssa_op_iter iter; | |
1295 | use_operand_p use_p; | |
1296 | ||
1297 | if (ssa_operands_active ()) | |
38635499 | 1298 | FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES) |
f47c96aa AM |
1299 | delink_imm_use (use_p); |
1300 | } | |
1301 | ||
1302 | ||
1303 | /* This routine will compare all the operands matching FLAGS in STMT1 to those | |
1304 | in STMT2. TRUE is returned if they are the same. STMTs can be NULL. */ | |
1305 | static inline bool | |
1306 | compare_ssa_operands_equal (tree stmt1, tree stmt2, int flags) | |
1307 | { | |
1308 | ssa_op_iter iter1, iter2; | |
1309 | tree op1 = NULL_TREE; | |
1310 | tree op2 = NULL_TREE; | |
1311 | bool look1, look2; | |
1312 | ||
1313 | if (stmt1 == stmt2) | |
1314 | return true; | |
1315 | ||
1316 | look1 = stmt1 && stmt_ann (stmt1); | |
1317 | look2 = stmt2 && stmt_ann (stmt2); | |
1318 | ||
1319 | if (look1) | |
1320 | { | |
1321 | op1 = op_iter_init_tree (&iter1, stmt1, flags); | |
1322 | if (!look2) | |
1323 | return op_iter_done (&iter1); | |
1324 | } | |
1325 | else | |
1326 | clear_and_done_ssa_iter (&iter1); | |
1327 | ||
1328 | if (look2) | |
1329 | { | |
1330 | op2 = op_iter_init_tree (&iter2, stmt2, flags); | |
1331 | if (!look1) | |
1332 | return op_iter_done (&iter2); | |
1333 | } | |
1334 | else | |
1335 | clear_and_done_ssa_iter (&iter2); | |
1336 | ||
1337 | while (!op_iter_done (&iter1) && !op_iter_done (&iter2)) | |
1338 | { | |
1339 | if (op1 != op2) | |
1340 | return false; | |
1341 | op1 = op_iter_next_tree (&iter1); | |
1342 | op2 = op_iter_next_tree (&iter2); | |
1343 | } | |
1344 | ||
1345 | return (op_iter_done (&iter1) && op_iter_done (&iter2)); | |
1346 | } | |
1347 | ||
1348 | ||
1349 | /* If there is a single DEF in the PHI node which matches FLAG, return it. | |
1350 | Otherwise return NULL_DEF_OPERAND_P. */ | |
1351 | static inline tree | |
1352 | single_phi_def (tree stmt, int flags) | |
1353 | { | |
1354 | tree def = PHI_RESULT (stmt); | |
1355 | if ((flags & SSA_OP_DEF) && is_gimple_reg (def)) | |
1356 | return def; | |
1357 | if ((flags & SSA_OP_VIRTUAL_DEFS) && !is_gimple_reg (def)) | |
1358 | return def; | |
1359 | return NULL_TREE; | |
1360 | } | |
1361 | ||
1362 | /* Initialize the iterator PTR for uses matching FLAGS in PHI. FLAGS should | |
263bb8fb | 1363 | be either SSA_OP_USES or SSA_OP_VIRTUAL_USES. */ |
f47c96aa AM |
1364 | static inline use_operand_p |
1365 | op_iter_init_phiuse (ssa_op_iter *ptr, tree phi, int flags) | |
1366 | { | |
1367 | tree phi_def = PHI_RESULT (phi); | |
1368 | int comp; | |
1369 | ||
1370 | clear_and_done_ssa_iter (ptr); | |
1371 | ptr->done = false; | |
1372 | ||
1373 | gcc_assert ((flags & (SSA_OP_USE | SSA_OP_VIRTUAL_USES)) != 0); | |
1374 | ||
1375 | comp = (is_gimple_reg (phi_def) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES); | |
1376 | ||
395bda42 | 1377 | /* If the PHI node doesn't the operand type we care about, we're done. */ |
f47c96aa AM |
1378 | if ((flags & comp) == 0) |
1379 | { | |
1380 | ptr->done = true; | |
1381 | return NULL_USE_OPERAND_P; | |
1382 | } | |
1383 | ||
1384 | ptr->phi_stmt = phi; | |
1385 | ptr->num_phi = PHI_NUM_ARGS (phi); | |
1386 | ptr->iter_type = ssa_op_iter_use; | |
1387 | return op_iter_next_use (ptr); | |
1388 | } | |
1389 | ||
1390 | ||
395bda42 | 1391 | /* Start an iterator for a PHI definition. */ |
f47c96aa AM |
1392 | |
1393 | static inline def_operand_p | |
1394 | op_iter_init_phidef (ssa_op_iter *ptr, tree phi, int flags) | |
1395 | { | |
1396 | tree phi_def = PHI_RESULT (phi); | |
1397 | int comp; | |
1398 | ||
1399 | clear_and_done_ssa_iter (ptr); | |
1400 | ptr->done = false; | |
1401 | ||
1402 | gcc_assert ((flags & (SSA_OP_DEF | SSA_OP_VIRTUAL_DEFS)) != 0); | |
1403 | ||
1404 | comp = (is_gimple_reg (phi_def) ? SSA_OP_DEF : SSA_OP_VIRTUAL_DEFS); | |
1405 | ||
395bda42 | 1406 | /* If the PHI node doesn't the operand type we care about, we're done. */ |
f47c96aa AM |
1407 | if ((flags & comp) == 0) |
1408 | { | |
1409 | ptr->done = true; | |
1410 | return NULL_USE_OPERAND_P; | |
1411 | } | |
1412 | ||
1413 | ptr->iter_type = ssa_op_iter_def; | |
1414 | /* The first call to op_iter_next_def will terminate the iterator since | |
1415 | all the fields are NULL. Simply return the result here as the first and | |
1416 | therefore only result. */ | |
1417 | return PHI_RESULT_PTR (phi); | |
1418 | } | |
1419 | ||
6c00f606 AM |
1420 | /* Return true is IMM has reached the end of the immediate use stmt list. */ |
1421 | ||
1422 | static inline bool | |
1423 | end_imm_use_stmt_p (imm_use_iterator *imm) | |
1424 | { | |
1425 | return (imm->imm_use == imm->end_p); | |
1426 | } | |
1427 | ||
1428 | /* Finished the traverse of an immediate use stmt list IMM by removing the | |
1429 | placeholder node from the list. */ | |
1430 | ||
1431 | static inline void | |
1432 | end_imm_use_stmt_traverse (imm_use_iterator *imm) | |
1433 | { | |
1434 | delink_imm_use (&(imm->iter_node)); | |
1435 | } | |
1436 | ||
1437 | /* Immediate use traversal of uses within a stmt require that all the | |
1438 | uses on a stmt be sequentially listed. This routine is used to build up | |
1439 | this sequential list by adding USE_P to the end of the current list | |
1440 | currently delimited by HEAD and LAST_P. The new LAST_P value is | |
1441 | returned. */ | |
1442 | ||
1443 | static inline use_operand_p | |
1444 | move_use_after_head (use_operand_p use_p, use_operand_p head, | |
1445 | use_operand_p last_p) | |
1446 | { | |
1447 | gcc_assert (USE_FROM_PTR (use_p) == USE_FROM_PTR (head)); | |
1448 | /* Skip head when we find it. */ | |
1449 | if (use_p != head) | |
1450 | { | |
1451 | /* If use_p is already linked in after last_p, continue. */ | |
1452 | if (last_p->next == use_p) | |
1453 | last_p = use_p; | |
1454 | else | |
1455 | { | |
1456 | /* Delink from current location, and link in at last_p. */ | |
1457 | delink_imm_use (use_p); | |
1458 | link_imm_use_to_list (use_p, last_p); | |
1459 | last_p = use_p; | |
1460 | } | |
1461 | } | |
1462 | return last_p; | |
1463 | } | |
1464 | ||
1465 | ||
1466 | /* This routine will relink all uses with the same stmt as HEAD into the list | |
1467 | immediately following HEAD for iterator IMM. */ | |
1468 | ||
1469 | static inline void | |
1470 | link_use_stmts_after (use_operand_p head, imm_use_iterator *imm) | |
1471 | { | |
1472 | use_operand_p use_p; | |
1473 | use_operand_p last_p = head; | |
1474 | tree head_stmt = USE_STMT (head); | |
1475 | tree use = USE_FROM_PTR (head); | |
1476 | ssa_op_iter op_iter; | |
1477 | int flag; | |
1478 | ||
1479 | /* Only look at virtual or real uses, depending on the type of HEAD. */ | |
1480 | flag = (is_gimple_reg (use) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES); | |
1481 | ||
1482 | if (TREE_CODE (head_stmt) == PHI_NODE) | |
1483 | { | |
1484 | FOR_EACH_PHI_ARG (use_p, head_stmt, op_iter, flag) | |
1485 | if (USE_FROM_PTR (use_p) == use) | |
1486 | last_p = move_use_after_head (use_p, head, last_p); | |
1487 | } | |
1488 | else | |
1489 | { | |
1490 | FOR_EACH_SSA_USE_OPERAND (use_p, head_stmt, op_iter, flag) | |
1491 | if (USE_FROM_PTR (use_p) == use) | |
1492 | last_p = move_use_after_head (use_p, head, last_p); | |
1493 | } | |
1494 | /* LInk iter node in after last_p. */ | |
1495 | if (imm->iter_node.prev != NULL) | |
1496 | delink_imm_use (&imm->iter_node); | |
1497 | link_imm_use_to_list (&(imm->iter_node), last_p); | |
1498 | } | |
1499 | ||
1500 | /* Initialize IMM to traverse over uses of VAR. Return the first statement. */ | |
1501 | static inline tree | |
1502 | first_imm_use_stmt (imm_use_iterator *imm, tree var) | |
1503 | { | |
1504 | gcc_assert (TREE_CODE (var) == SSA_NAME); | |
1505 | ||
1506 | imm->end_p = &(SSA_NAME_IMM_USE_NODE (var)); | |
1507 | imm->imm_use = imm->end_p->next; | |
1508 | imm->next_imm_name = NULL_USE_OPERAND_P; | |
1509 | ||
1510 | /* iter_node is used as a marker within the immediate use list to indicate | |
bca50406 KH |
1511 | where the end of the current stmt's uses are. Initialize it to NULL |
1512 | stmt and use, which indicates a marker node. */ | |
6c00f606 AM |
1513 | imm->iter_node.prev = NULL_USE_OPERAND_P; |
1514 | imm->iter_node.next = NULL_USE_OPERAND_P; | |
1515 | imm->iter_node.stmt = NULL_TREE; | |
1516 | imm->iter_node.use = NULL_USE_OPERAND_P; | |
1517 | ||
1518 | if (end_imm_use_stmt_p (imm)) | |
1519 | return NULL_TREE; | |
1520 | ||
1521 | link_use_stmts_after (imm->imm_use, imm); | |
1522 | ||
1523 | return USE_STMT (imm->imm_use); | |
1524 | } | |
1525 | ||
1526 | /* Bump IMM to the next stmt which has a use of var. */ | |
1527 | ||
1528 | static inline tree | |
1529 | next_imm_use_stmt (imm_use_iterator *imm) | |
1530 | { | |
1531 | imm->imm_use = imm->iter_node.next; | |
1532 | if (end_imm_use_stmt_p (imm)) | |
1533 | { | |
1534 | if (imm->iter_node.prev != NULL) | |
1535 | delink_imm_use (&imm->iter_node); | |
1536 | return NULL_TREE; | |
1537 | } | |
1538 | ||
1539 | link_use_stmts_after (imm->imm_use, imm); | |
1540 | return USE_STMT (imm->imm_use); | |
f47c96aa | 1541 | |
6c00f606 AM |
1542 | } |
1543 | ||
1544 | /* This routine will return the first use on the stmt IMM currently refers | |
1545 | to. */ | |
1546 | ||
1547 | static inline use_operand_p | |
1548 | first_imm_use_on_stmt (imm_use_iterator *imm) | |
1549 | { | |
1550 | imm->next_imm_name = imm->imm_use->next; | |
1551 | return imm->imm_use; | |
1552 | } | |
1553 | ||
1554 | /* Return TRUE if the last use on the stmt IMM refers to has been visited. */ | |
1555 | ||
1556 | static inline bool | |
1557 | end_imm_use_on_stmt_p (imm_use_iterator *imm) | |
1558 | { | |
1559 | return (imm->imm_use == &(imm->iter_node)); | |
1560 | } | |
1561 | ||
1562 | /* Bump to the next use on the stmt IMM refers to, return NULL if done. */ | |
1563 | ||
1564 | static inline use_operand_p | |
1565 | next_imm_use_on_stmt (imm_use_iterator *imm) | |
1566 | { | |
1567 | imm->imm_use = imm->next_imm_name; | |
1568 | if (end_imm_use_on_stmt_p (imm)) | |
1569 | return NULL_USE_OPERAND_P; | |
1570 | else | |
1571 | { | |
1572 | imm->next_imm_name = imm->imm_use->next; | |
1573 | return imm->imm_use; | |
1574 | } | |
1575 | } | |
f47c96aa | 1576 | |
db30731a JL |
1577 | /* Return true if VAR cannot be modified by the program. */ |
1578 | ||
1579 | static inline bool | |
1580 | unmodifiable_var_p (tree var) | |
1581 | { | |
1582 | if (TREE_CODE (var) == SSA_NAME) | |
1583 | var = SSA_NAME_VAR (var); | |
326eda4b DB |
1584 | |
1585 | if (MTAG_P (var)) | |
1586 | return TREE_READONLY (var) && (TREE_STATIC (var) || MTAG_GLOBAL (var)); | |
1587 | ||
db30731a JL |
1588 | return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var)); |
1589 | } | |
1590 | ||
8d66aeca | 1591 | /* Return true if REF, an ARRAY_REF, has an INDIRECT_REF somewhere in it. */ |
b1347638 DB |
1592 | |
1593 | static inline bool | |
8d66aeca | 1594 | array_ref_contains_indirect_ref (tree ref) |
b1347638 | 1595 | { |
8d66aeca RG |
1596 | gcc_assert (TREE_CODE (ref) == ARRAY_REF); |
1597 | ||
1598 | do { | |
1599 | ref = TREE_OPERAND (ref, 0); | |
1600 | } while (handled_component_p (ref)); | |
1601 | ||
1602 | return TREE_CODE (ref) == INDIRECT_REF; | |
b1347638 DB |
1603 | } |
1604 | ||
8d66aeca RG |
1605 | /* Return true if REF, a handled component reference, has an ARRAY_REF |
1606 | somewhere in it. */ | |
c75ab022 DB |
1607 | |
1608 | static inline bool | |
1609 | ref_contains_array_ref (tree ref) | |
1610 | { | |
8d66aeca RG |
1611 | gcc_assert (handled_component_p (ref)); |
1612 | ||
1613 | do { | |
1614 | if (TREE_CODE (ref) == ARRAY_REF) | |
1615 | return true; | |
1616 | ref = TREE_OPERAND (ref, 0); | |
1617 | } while (handled_component_p (ref)); | |
1618 | ||
c75ab022 DB |
1619 | return false; |
1620 | } | |
1621 | ||
1622 | /* Given a variable VAR, lookup and return a pointer to the list of | |
1623 | subvariables for it. */ | |
1624 | ||
1625 | static inline subvar_t * | |
1626 | lookup_subvars_for_var (tree var) | |
1627 | { | |
1628 | var_ann_t ann = var_ann (var); | |
1629 | gcc_assert (ann); | |
1630 | return &ann->subvars; | |
1631 | } | |
1632 | ||
1633 | /* Given a variable VAR, return a linked list of subvariables for VAR, or | |
1634 | NULL, if there are no subvariables. */ | |
1635 | ||
1636 | static inline subvar_t | |
1637 | get_subvars_for_var (tree var) | |
1638 | { | |
1639 | subvar_t subvars; | |
1640 | ||
1641 | gcc_assert (SSA_VAR_P (var)); | |
1642 | ||
1643 | if (TREE_CODE (var) == SSA_NAME) | |
1644 | subvars = *(lookup_subvars_for_var (SSA_NAME_VAR (var))); | |
1645 | else | |
1646 | subvars = *(lookup_subvars_for_var (var)); | |
1647 | return subvars; | |
1648 | } | |
1649 | ||
e8ca4159 DN |
1650 | /* Return the subvariable of VAR at offset OFFSET. */ |
1651 | ||
1652 | static inline tree | |
1653 | get_subvar_at (tree var, unsigned HOST_WIDE_INT offset) | |
1654 | { | |
1655 | subvar_t sv; | |
1656 | ||
1657 | for (sv = get_subvars_for_var (var); sv; sv = sv->next) | |
3c0b6c43 | 1658 | if (SFT_OFFSET (sv->var) == offset) |
e8ca4159 DN |
1659 | return sv->var; |
1660 | ||
1661 | return NULL_TREE; | |
1662 | } | |
1663 | ||
c75ab022 | 1664 | /* Return true if V is a tree that we can have subvars for. |
a916f21d | 1665 | Normally, this is any aggregate type. Also complex |
8ae5e6f2 | 1666 | types which are not gimple registers can have subvars. */ |
c75ab022 DB |
1667 | |
1668 | static inline bool | |
1669 | var_can_have_subvars (tree v) | |
1670 | { | |
1651647c AP |
1671 | /* Volatile variables should never have subvars. */ |
1672 | if (TREE_THIS_VOLATILE (v)) | |
1673 | return false; | |
1674 | ||
8ae5e6f2 AP |
1675 | /* Non decls or memory tags can never have subvars. */ |
1676 | if (!DECL_P (v) || MTAG_P (v)) | |
1677 | return false; | |
1678 | ||
a916f21d RG |
1679 | /* Aggregates can have subvars. */ |
1680 | if (AGGREGATE_TYPE_P (TREE_TYPE (v))) | |
8ae5e6f2 AP |
1681 | return true; |
1682 | ||
1683 | /* Complex types variables which are not also a gimple register can | |
1684 | have subvars. */ | |
1685 | if (TREE_CODE (TREE_TYPE (v)) == COMPLEX_TYPE | |
0890b981 | 1686 | && !DECL_GIMPLE_REG_P (v)) |
8ae5e6f2 AP |
1687 | return true; |
1688 | ||
1689 | return false; | |
c75ab022 DB |
1690 | } |
1691 | ||
1692 | ||
013cc86f DB |
1693 | /* Return true if OFFSET and SIZE define a range that overlaps with some |
1694 | portion of the range of SV, a subvar. If there was an exact overlap, | |
1695 | *EXACT will be set to true upon return. */ | |
1696 | ||
1697 | static inline bool | |
e8ca4159 | 1698 | overlap_subvar (unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, |
3c0b6c43 | 1699 | tree sv, bool *exact) |
013cc86f DB |
1700 | { |
1701 | /* There are three possible cases of overlap. | |
1702 | 1. We can have an exact overlap, like so: | |
1703 | |offset, offset + size | | |
1704 | |sv->offset, sv->offset + sv->size | | |
1705 | ||
1706 | 2. We can have offset starting after sv->offset, like so: | |
1707 | ||
1708 | |offset, offset + size | | |
1709 | |sv->offset, sv->offset + sv->size | | |
1710 | ||
1711 | 3. We can have offset starting before sv->offset, like so: | |
1712 | ||
1713 | |offset, offset + size | | |
1714 | |sv->offset, sv->offset + sv->size| | |
1715 | */ | |
1716 | ||
1717 | if (exact) | |
1718 | *exact = false; | |
3c0b6c43 | 1719 | if (offset == SFT_OFFSET (sv) && size == SFT_SIZE (sv)) |
013cc86f DB |
1720 | { |
1721 | if (exact) | |
1722 | *exact = true; | |
1723 | return true; | |
1724 | } | |
3c0b6c43 DB |
1725 | else if (offset >= SFT_OFFSET (sv) |
1726 | && offset < (SFT_OFFSET (sv) + SFT_SIZE (sv))) | |
013cc86f DB |
1727 | { |
1728 | return true; | |
1729 | } | |
3c0b6c43 DB |
1730 | else if (offset < SFT_OFFSET (sv) |
1731 | && (size > SFT_OFFSET (sv) - offset)) | |
013cc86f DB |
1732 | { |
1733 | return true; | |
1734 | } | |
1735 | return false; | |
1736 | ||
1737 | } | |
c75ab022 | 1738 | |
cfaab3a9 DN |
1739 | /* Return the memory tag associated with symbol SYM. */ |
1740 | ||
1741 | static inline tree | |
1742 | symbol_mem_tag (tree sym) | |
1743 | { | |
1744 | tree tag = get_var_ann (sym)->symbol_mem_tag; | |
1745 | ||
1746 | #if defined ENABLE_CHECKING | |
1747 | if (tag) | |
1748 | gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG); | |
1749 | #endif | |
1750 | ||
1751 | return tag; | |
1752 | } | |
1753 | ||
1754 | ||
1755 | /* Set the memory tag associated with symbol SYM. */ | |
1756 | ||
1757 | static inline void | |
1758 | set_symbol_mem_tag (tree sym, tree tag) | |
1759 | { | |
1760 | #if defined ENABLE_CHECKING | |
1761 | if (tag) | |
1762 | gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG); | |
1763 | #endif | |
1764 | ||
1765 | get_var_ann (sym)->symbol_mem_tag = tag; | |
1766 | } | |
1767 | ||
83737db2 DB |
1768 | /* Get the value handle of EXPR. This is the only correct way to get |
1769 | the value handle for a "thing". If EXPR does not have a value | |
1770 | handle associated, it returns NULL_TREE. | |
1771 | NB: If EXPR is min_invariant, this function is *required* to return | |
1772 | EXPR. */ | |
1773 | ||
1774 | static inline tree | |
1775 | get_value_handle (tree expr) | |
1776 | { | |
1777 | if (TREE_CODE (expr) == SSA_NAME) | |
1778 | return SSA_NAME_VALUE (expr); | |
1779 | else if (DECL_P (expr) || TREE_CODE (expr) == TREE_LIST | |
1780 | || TREE_CODE (expr) == CONSTRUCTOR) | |
1781 | { | |
1782 | tree_ann_common_t ann = tree_common_ann (expr); | |
1783 | return ((ann) ? ann->value_handle : NULL_TREE); | |
1784 | } | |
1785 | else if (is_gimple_min_invariant (expr)) | |
1786 | return expr; | |
1787 | else if (EXPR_P (expr)) | |
1788 | { | |
1789 | tree_ann_common_t ann = tree_common_ann (expr); | |
1790 | return ((ann) ? ann->value_handle : NULL_TREE); | |
1791 | } | |
1792 | else | |
1793 | gcc_unreachable (); | |
1794 | } | |
1795 | ||
456cde30 JH |
1796 | /* Accessor to tree-ssa-operands.c caches. */ |
1797 | static inline struct ssa_operands * | |
1798 | gimple_ssa_operands (struct function *fun) | |
1799 | { | |
1800 | return &fun->gimple_df->ssa_operands; | |
1801 | } | |
6de9cd9a | 1802 | #endif /* _TREE_FLOW_INLINE_H */ |