]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-flow-inline.h
Merge tree-ssa-20020619-branch into mainline.
[thirdparty/gcc.git] / gcc / tree-flow-inline.h
1 /* Inline functions for tree-flow.h
2 Copyright (C) 2001, 2003 Free Software Foundation, Inc.
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
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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
28 static inline var_ann_t
29 var_ann (tree t)
30 {
31 #if defined ENABLE_CHECKING
32 if (t == NULL_TREE
33 || !DECL_P (t)
34 || (t->common.ann
35 && t->common.ann->common.type != VAR_ANN))
36 abort ();
37 #endif
38
39 return (var_ann_t) t->common.ann;
40 }
41
42 static inline var_ann_t
43 get_var_ann (tree var)
44 {
45 var_ann_t ann = var_ann (var);
46 return (ann) ? ann : create_var_ann (var);
47 }
48
49 static inline stmt_ann_t
50 stmt_ann (tree t)
51 {
52 #if defined ENABLE_CHECKING
53 if (!is_gimple_stmt (t) && !is_essa_node (t))
54 abort ();
55 #endif
56
57 return (stmt_ann_t) t->common.ann;
58 }
59
60 static inline stmt_ann_t
61 get_stmt_ann (tree stmt)
62 {
63 stmt_ann_t ann = stmt_ann (stmt);
64 return (ann) ? ann : create_stmt_ann (stmt);
65 }
66
67 static inline ssa_name_ann_t
68 ssa_name_ann (tree t)
69 {
70 #if defined ENABLE_CHECKING
71 if (t == NULL_TREE
72 || TREE_CODE (t) != SSA_NAME
73 || (t->common.ann
74 && t->common.ann->common.type != SSA_NAME_ANN))
75 abort ();
76 #endif
77
78 return (ssa_name_ann_t) t->common.ann;
79 }
80
81 static inline ssa_name_ann_t
82 get_ssa_name_ann (tree var)
83 {
84 ssa_name_ann_t ann = ssa_name_ann (var);
85 return (ann) ? ann : create_ssa_name_ann (var);
86 }
87
88
89 static inline enum tree_ann_type
90 ann_type (tree_ann ann)
91 {
92 return ann->common.type;
93 }
94
95 static inline basic_block
96 bb_for_stmt (tree t)
97 {
98 stmt_ann_t ann = stmt_ann (t);
99 return ann ? ann->bb : NULL;
100 }
101
102 static inline varray_type
103 may_aliases (tree var)
104 {
105 var_ann_t ann = var_ann (var);
106 return ann ? ann->may_aliases : NULL;
107 }
108
109 static inline bool
110 has_hidden_use (tree var)
111 {
112 var_ann_t ann = var_ann (var);
113 return ann ? ann->has_hidden_use : false;
114 }
115
116 static inline void
117 set_has_hidden_use (tree var)
118 {
119 var_ann_t ann = var_ann (var);
120 if (ann == NULL)
121 ann = create_var_ann (var);
122 ann->has_hidden_use = 1;
123 }
124
125 static inline int
126 get_lineno (tree expr)
127 {
128 if (expr == NULL_TREE)
129 return -1;
130
131 if (TREE_CODE (expr) == COMPOUND_EXPR)
132 expr = TREE_OPERAND (expr, 0);
133
134 if (! EXPR_LOCUS (expr))
135 return -1;
136
137 return EXPR_LINENO (expr);
138 }
139
140 static inline const char *
141 get_filename (tree expr)
142 {
143 if (expr == NULL_TREE)
144 return "???";
145
146 if (TREE_CODE (expr) == COMPOUND_EXPR)
147 expr = TREE_OPERAND (expr, 0);
148
149 if (EXPR_LOCUS (expr) && EXPR_FILENAME (expr))
150 return EXPR_FILENAME (expr);
151 else
152 return "???";
153 }
154
155 static inline void
156 modify_stmt (tree t)
157 {
158 stmt_ann_t ann = stmt_ann (t);
159 if (ann == NULL)
160 ann = create_stmt_ann (t);
161 ann->modified = 1;
162 }
163
164 static inline void
165 unmodify_stmt (tree t)
166 {
167 stmt_ann_t ann = stmt_ann (t);
168 if (ann == NULL)
169 ann = create_stmt_ann (t);
170 ann->modified = 0;
171 }
172
173 static inline bool
174 stmt_modified_p (tree t)
175 {
176 stmt_ann_t ann = stmt_ann (t);
177
178 /* Note that if the statement doesn't yet have an annotation, we consider it
179 modified. This will force the next call to get_stmt_operands to scan the
180 statement. */
181 return ann ? ann->modified : true;
182 }
183
184 static inline def_optype
185 get_def_ops (stmt_ann_t ann)
186 {
187 return ann ? ann->def_ops : NULL;
188 }
189
190 static inline use_optype
191 get_use_ops (stmt_ann_t ann)
192 {
193 return ann ? ann->use_ops : NULL;
194 }
195
196 static inline vdef_optype
197 get_vdef_ops (stmt_ann_t ann)
198 {
199 return ann ? ann->vdef_ops : NULL;
200 }
201
202 static inline vuse_optype
203 get_vuse_ops (stmt_ann_t ann)
204 {
205 return ann ? ann->vuse_ops : NULL;
206 }
207
208 static inline tree *
209 get_use_op_ptr (use_optype uses, unsigned int index)
210 {
211 #ifdef ENABLE_CHECKING
212 if (index >= uses->num_uses)
213 abort();
214 #endif
215 return uses->uses[index];
216 }
217
218 static inline tree *
219 get_def_op_ptr (def_optype defs, unsigned int index)
220 {
221 #ifdef ENABLE_CHECKING
222 if (index >= defs->num_defs)
223 abort();
224 #endif
225 return defs->defs[index];
226 }
227
228 static inline tree *
229 get_vdef_result_ptr(vdef_optype vdefs, unsigned int index)
230 {
231 #ifdef ENABLE_CHECKING
232 if (index >= vdefs->num_vdefs)
233 abort();
234 #endif
235 return &(vdefs->vdefs[index * 2]);
236 }
237
238 static inline tree *
239 get_vdef_op_ptr(vdef_optype vdefs, unsigned int index)
240 {
241 #ifdef ENABLE_CHECKING
242 if (index >= vdefs->num_vdefs)
243 abort();
244 #endif
245 return &(vdefs->vdefs[index * 2 + 1]);
246 }
247
248 static inline tree *
249 get_vuse_op_ptr(vuse_optype vuses, unsigned int index)
250 {
251 #ifdef ENABLE_CHECKING
252 if (index >= vuses->num_vuses)
253 abort();
254 #endif
255 return &(vuses->vuses[index]);
256 }
257
258 static inline void
259 start_ssa_stmt_operands (tree stmt ATTRIBUTE_UNUSED)
260 {
261 #ifdef ENABLE_CHECKING
262 verify_start_operands (stmt);
263 #endif
264 }
265
266 static inline bitmap
267 addresses_taken (tree stmt)
268 {
269 stmt_ann_t ann = stmt_ann (stmt);
270 return ann ? ann->addresses_taken : NULL;
271 }
272
273 static dataflow_t
274 get_immediate_uses (tree stmt)
275 {
276 stmt_ann_t ann = stmt_ann (stmt);
277 return ann ? ann->df : NULL;
278 }
279
280 static inline int
281 num_immediate_uses (dataflow_t df)
282 {
283 varray_type imm;
284
285 if (!df)
286 return 0;
287
288 imm = df->immediate_uses;
289 if (!imm)
290 return df->uses[1] ? 2 : 1;
291
292 return VARRAY_ACTIVE_SIZE (imm) + 2;
293 }
294
295 static inline tree
296 immediate_use (dataflow_t df, int num)
297 {
298 #ifdef ENABLE_CHECKING
299 if (num >= num_immediate_uses (df))
300 abort ();
301 #endif
302 if (num < 2)
303 return df->uses[num];
304 return VARRAY_TREE (df->immediate_uses, num - 2);
305 }
306
307 static inline bb_ann_t
308 bb_ann (basic_block bb)
309 {
310 return (bb_ann_t)bb->tree_annotations;
311 }
312
313 static inline tree
314 phi_nodes (basic_block bb)
315 {
316 if (bb->index < 0)
317 return NULL;
318 return bb_ann (bb)->phi_nodes;
319 }
320
321 /* Set list of phi nodes of a basic block BB to L. */
322
323 static inline void
324 set_phi_nodes (basic_block bb, tree l)
325 {
326 tree phi;
327
328 bb_ann (bb)->phi_nodes = l;
329 for (phi = l; phi; phi = TREE_CHAIN (phi))
330 set_bb_for_stmt (phi, bb);
331 }
332
333 /* Return the phi index number for an edge. */
334 static inline int
335 phi_arg_from_edge (tree phi, edge e)
336 {
337 int i;
338 #if defined ENABLE_CHECKING
339 if (!phi || TREE_CODE (phi) != PHI_NODE)
340 abort();
341 #endif
342
343 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
344 if (PHI_ARG_EDGE (phi, i) == e)
345 return i;
346
347 return -1;
348 }
349
350
351 /* Return the phi argument number for an edge. */
352 static inline struct phi_arg_d *
353 phi_element_for_edge (tree phi, edge e)
354 {
355 int i;
356
357 i = phi_arg_from_edge (phi, e);
358 if (i != -1)
359 return &(PHI_ARG_ELT (phi, i));
360 else
361 return (struct phi_arg_d *)NULL;
362 }
363
364 /* ----------------------------------------------------------------------- */
365
366 static inline bool
367 is_exec_stmt (tree t)
368 {
369 return (t && !IS_EMPTY_STMT (t) && t != error_mark_node);
370 }
371
372
373 /* Return true if this stmt can be the target of a control transfer stmt such
374 as a goto. */
375 static inline bool
376 is_label_stmt (tree t)
377 {
378 if (t)
379 switch (TREE_CODE (t))
380 {
381 case LABEL_DECL:
382 case LABEL_EXPR:
383 case CASE_LABEL_EXPR:
384 return true;
385 default:
386 return false;
387 }
388 return false;
389 }
390
391 static inline bool
392 may_propagate_copy (tree dest, tree orig)
393 {
394 /* FIXME. GIMPLE is allowing pointer assignments and comparisons of
395 pointers that have different alias sets. This means that these
396 pointers will have different memory tags associated to them.
397
398 If we allow copy propagation in these cases, statements de-referencing
399 the new pointer will now have a reference to a different memory tag
400 with potentially incorrect SSA information.
401
402 This was showing up in libjava/java/util/zip/ZipFile.java with code
403 like:
404
405 struct java.io.BufferedInputStream *T.660;
406 struct java.io.BufferedInputStream *T.647;
407 struct java.io.InputStream *is;
408 struct java.io.InputStream *is.662;
409 [ ... ]
410 T.660 = T.647;
411 is = T.660; <-- This ought to be type-casted
412 is.662 = is;
413
414 Also, f/name.c exposed a similar problem with a COND_EXPR predicate
415 that was causing DOM to generate and equivalence with two pointers of
416 alias-incompatible types:
417
418 struct _ffename_space *n;
419 struct _ffename *ns;
420 [ ... ]
421 if (n == ns)
422 goto lab;
423 ...
424 lab:
425 return n;
426
427 I think that GIMPLE should emit the appropriate type-casts. For the
428 time being, blocking copy-propagation in these cases is the safe thing
429 to do. */
430 if (TREE_CODE (dest) == SSA_NAME
431 && TREE_CODE (orig) == SSA_NAME
432 && POINTER_TYPE_P (TREE_TYPE (dest))
433 && POINTER_TYPE_P (TREE_TYPE (orig)))
434 {
435 tree mt_dest = var_ann (SSA_NAME_VAR (dest))->type_mem_tag;
436 tree mt_orig = var_ann (SSA_NAME_VAR (orig))->type_mem_tag;
437 if (mt_dest && mt_orig && mt_dest != mt_orig)
438 return false;
439 }
440
441 /* If the destination is a SSA_NAME for a virtual operand, then we have
442 some special cases to handle. */
443 if (TREE_CODE (dest) == SSA_NAME && !is_gimple_reg (dest))
444 {
445 /* If both operands are SSA_NAMEs referring to virtual operands, then
446 we can always propagate. */
447 if (TREE_CODE (orig) == SSA_NAME)
448 {
449 if (!is_gimple_reg (orig))
450 return true;
451
452 #ifdef ENABLE_CHECKING
453 /* If we have one real and one virtual operand, then something has
454 gone terribly wrong. */
455 if (is_gimple_reg (orig))
456 abort ();
457 #endif
458 }
459
460 /* We have a "copy" from something like a constant into a virtual
461 operand. Reject these. */
462 return false;
463 }
464
465 return (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest)
466 && (TREE_CODE (orig) != SSA_NAME
467 || !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
468 && !DECL_HARD_REGISTER (SSA_NAME_VAR (dest)));
469 }
470
471 static inline void
472 set_default_def (tree var, tree def)
473 {
474 var_ann_t ann = var_ann (var);
475 if (ann == NULL)
476 ann = create_var_ann (var);
477 ann->default_def = def;
478 }
479
480 static inline tree
481 default_def (tree var)
482 {
483 var_ann_t ann = var_ann (var);
484 return ann ? ann->default_def : NULL_TREE;
485 }
486
487 /* PHI nodes should contain only ssa_names and invariants. A test
488 for ssa_name is definitely simpler; don't let invalid contents
489 slip in in the meantime. */
490
491 static inline bool
492 phi_ssa_name_p (tree t)
493 {
494 if (TREE_CODE (t) == SSA_NAME)
495 return true;
496 #ifdef ENABLE_CHECKING
497 if (!is_gimple_min_invariant (t))
498 abort ();
499 #endif
500 return false;
501 }
502
503 /* ----------------------------------------------------------------------- */
504
505 static inline block_stmt_iterator
506 bsi_start (basic_block bb)
507 {
508 block_stmt_iterator bsi;
509 if (bb->stmt_list)
510 bsi.tsi = tsi_start (bb->stmt_list);
511 else
512 {
513 #ifdef ENABLE_CHECKING
514 if (bb->index >= 0)
515 abort ();
516 #endif
517 bsi.tsi.ptr = NULL;
518 bsi.tsi.container = NULL;
519 }
520 bsi.bb = bb;
521 return bsi;
522 }
523
524 static inline block_stmt_iterator
525 bsi_last (basic_block bb)
526 {
527 block_stmt_iterator bsi;
528 if (bb->stmt_list)
529 bsi.tsi = tsi_last (bb->stmt_list);
530 else
531 {
532 #ifdef ENABLE_CHECKING
533 if (bb->index >= 0)
534 abort ();
535 #endif
536 bsi.tsi.ptr = NULL;
537 bsi.tsi.container = NULL;
538 }
539 bsi.bb = bb;
540 return bsi;
541 }
542
543 static inline bool
544 bsi_end_p (block_stmt_iterator i)
545 {
546 return tsi_end_p (i.tsi);
547 }
548
549 static inline void
550 bsi_next (block_stmt_iterator *i)
551 {
552 tsi_next (&i->tsi);
553 }
554
555 static inline void
556 bsi_prev (block_stmt_iterator *i)
557 {
558 tsi_prev (&i->tsi);
559 }
560
561 static inline tree
562 bsi_stmt (block_stmt_iterator i)
563 {
564 return tsi_stmt (i.tsi);
565 }
566
567 static inline tree *
568 bsi_stmt_ptr (block_stmt_iterator i)
569 {
570 return tsi_stmt_ptr (i.tsi);
571 }
572
573 static inline bool
574 may_be_aliased (tree var)
575 {
576 return (TREE_ADDRESSABLE (var)
577 || decl_function_context (var) != current_function_decl);
578 }
579
580 static inline bool
581 is_call_clobbered (tree var)
582 {
583 return needs_to_live_in_memory (var)
584 || bitmap_bit_p (call_clobbered_vars, var_ann (var)->uid);
585 }
586
587 static inline void
588 mark_call_clobbered (tree var)
589 {
590 var_ann_t ann = var_ann (var);
591 /* Call-clobbered variables need to live in memory. */
592 DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (var) = 1;
593 bitmap_set_bit (call_clobbered_vars, ann->uid);
594 }
595
596 static inline void
597 mark_non_addressable (tree var)
598 {
599 bitmap_clear_bit (call_clobbered_vars, var_ann (var)->uid);
600 DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (var) = 0;
601 TREE_ADDRESSABLE (var) = 0;
602 }
603
604 #endif /* _TREE_FLOW_INLINE_H */