/*---------------------------------------------------------------------------
Tree annotations stored in tree_common.ann
---------------------------------------------------------------------------*/
-enum tree_ann_type { TREE_ANN_COMMON, VAR_ANN, STMT_ANN, SSA_NAME_ANN };
+enum tree_ann_type { TREE_ANN_COMMON, VAR_ANN, STMT_ANN };
struct tree_ann_common_d GTY(())
{
};
-struct ssa_name_ann_d GTY(())
-{
- struct tree_ann_common_d common;
-
- /* Nonzero if points-to analysis couldn't determine where this pointer
- is pointing to. */
- unsigned int pt_anything : 1;
-
- /* Nonzero if this pointer is the result of a call to malloc. */
- unsigned int pt_malloc : 1;
-
- /* Nonzero if the value of this pointer escapes the current function. */
- unsigned int value_escapes_p : 1;
-
- /* Set of variables that this pointer may point to. */
- bitmap pt_vars;
-
- /* If this pointer has been dereferenced, and points-to information is
- more precise than type-based aliasing, indirect references to this
- pointer will be represented by this memory tag, instead of the type
- tag computed by TBAA. */
- tree name_mem_tag;
-};
-
-
union tree_ann_d GTY((desc ("ann_type ((tree_ann)&%h)")))
{
struct tree_ann_common_d GTY((tag ("TREE_ANN_COMMON"))) common;
struct var_ann_d GTY((tag ("VAR_ANN"))) decl;
struct stmt_ann_d GTY((tag ("STMT_ANN"))) stmt;
- struct ssa_name_ann_d GTY((tag ("SSA_NAME_ANN"))) ssa_name;
};
typedef union tree_ann_d *tree_ann;
typedef struct var_ann_d *var_ann_t;
typedef struct stmt_ann_d *stmt_ann_t;
-typedef struct ssa_name_ann_d *ssa_name_ann_t;
static inline var_ann_t var_ann (tree);
static inline var_ann_t get_var_ann (tree);
static inline stmt_ann_t stmt_ann (tree);
static inline stmt_ann_t get_stmt_ann (tree);
-static inline ssa_name_ann_t ssa_name_ann (tree);
-static inline ssa_name_ann_t get_ssa_name_ann (tree);
static inline enum tree_ann_type ann_type (tree_ann);
static inline basic_block bb_for_stmt (tree);
extern void set_bb_for_stmt (tree, basic_block);
/* In tree-dfa.c */
extern var_ann_t create_var_ann (tree);
extern stmt_ann_t create_stmt_ann (tree);
-extern ssa_name_ann_t create_ssa_name_ann (tree);
extern tree create_phi_node (tree, basic_block);
extern void add_phi_arg (tree *, tree, edge);
extern void remove_phi_arg (tree, basic_block);
static bool ptr_is_dereferenced_by (tree, tree, bool *);
static void maybe_create_global_var (struct alias_info *ai);
static void group_aliases (struct alias_info *);
+static struct ptr_info_def *get_ptr_info (tree t);
/* Global declarations. */
if (!bitmap_bit_p (ai->ssa_names_visited, SSA_NAME_VERSION (ptr)))
{
- ssa_name_ann_t ann;
+ struct ptr_info_def *pi;
bitmap_set_bit (ai->ssa_names_visited, SSA_NAME_VERSION (ptr));
walk_use_def_chains (ptr, collect_points_to_info_r, ai);
/* If we could not determine where PTR was pointing to, clear all the
other points-to information. */
- ann = ssa_name_ann (ptr);
- if (ann->pt_anything)
+ pi = SSA_NAME_PTR_INFO (ptr);
+ if (pi->pt_anything)
{
- ann->pt_malloc = 0;
- ann->pt_vars = NULL;
+ pi->pt_malloc = 0;
+ pi->pt_vars = NULL;
}
}
}
if (stmt_escapes_p)
block_ann->has_escape_site = 1;
- /* Special case for silly ADDR_EXPR tricks. If this
- statement is an assignment to a non-pointer variable and
- the RHS takes the address of a variable, assume that the
- variable on the RHS is call-clobbered. We could add the
- LHS to the list of "pointers" and follow it to see if it
- really escapes, but it's not worth the pain. */
+ /* Special case for silly ADDR_EXPR tricks
+ (gcc.c-torture/unsorted/pass.c). If this statement is an
+ assignment to a non-pointer variable and the RHS takes the
+ address of a variable, assume that the variable on the RHS is
+ call-clobbered. We could add the LHS to the list of
+ "pointers" and follow it to see if it really escapes, but it's
+ not worth the pain. */
if (addr_taken
&& TREE_CODE (stmt) == MODIFY_EXPR
&& !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 0))))
{
tree op = USE_OP (uses, i);
var_ann_t v_ann = var_ann (SSA_NAME_VAR (op));
- ssa_name_ann_t ptr_ann;
+ struct ptr_info_def *pi;
bool is_store;
/* If the operand's variable may be aliased, keep track
collect_points_to_info_for (ai, op);
- ptr_ann = ssa_name_ann (op);
+ pi = SSA_NAME_PTR_INFO (op);
if (ptr_is_dereferenced_by (op, stmt, &is_store))
{
/* If we found OP to point to a set of variables or
FIXME: Cycles in the SSA web and the lack of SSA
information for structures will prevent the creation
of name tags. Find ways around this limitation. */
- if (ptr_ann->pt_malloc || ptr_ann->pt_vars)
- ptr_ann->name_mem_tag = get_nmt_for (op);
+ if (pi->pt_malloc || pi->pt_vars)
+ pi->name_mem_tag = get_nmt_for (op);
/* Keep track of how many time we've dereferenced each
pointer. Again, we don't need to grow
will not escape if it is being dereferenced. That's
why we only check for escape points if OP is not
dereferenced by STMT. */
- ptr_ann->value_escapes_p = 1;
+ pi->value_escapes_p = 1;
/* If the statement makes a function call, assume
that pointer OP will be dereferenced in a store
{
size_t j;
tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
- ssa_name_ann_t ann = ssa_name_ann (ptr);
+ struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
- if (ann->value_escapes_p || ann->pt_anything)
+ if (pi->value_escapes_p || pi->pt_anything)
{
/* If PTR escapes or may point to anything, then its associated
memory tags are call-clobbered. */
- if (ann->name_mem_tag)
- mark_call_clobbered (ann->name_mem_tag);
+ if (pi->name_mem_tag)
+ mark_call_clobbered (pi->name_mem_tag);
if (v_ann->type_mem_tag)
mark_call_clobbered (v_ann->type_mem_tag);
/* If PTR may point to anything, mark call-clobbered all the
addressables with the same alias set as the type pointed-to by
PTR. */
- if (ann->pt_anything)
+ if (pi->pt_anything)
{
HOST_WIDE_INT ptr_set;
ptr_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
name memory tag, which will have been marked call-clobbered.
This will in turn mark the pointed-to variables as
call-clobbered when we call add_may_alias below. */
- if (ann->value_escapes_p && !ann->name_mem_tag && ann->pt_vars)
- EXECUTE_IF_SET_IN_BITMAP (ann->pt_vars, 0, j,
+ if (pi->value_escapes_p
+ && pi->name_mem_tag == NULL_TREE
+ && pi->pt_vars)
+ EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j,
mark_call_clobbered (referenced_var (j)));
}
/* Set up aliasing information for PTR's name memory tag (if it has
one). Note that only pointers that have been dereferenced will
have a name memory tag. */
- if (ann->name_mem_tag && ann->pt_vars)
- EXECUTE_IF_SET_IN_BITMAP (ann->pt_vars, 0, j,
- add_may_alias (ann->name_mem_tag, referenced_var (j)));
+ if (pi->name_mem_tag && pi->pt_vars)
+ EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j,
+ add_may_alias (pi->name_mem_tag, referenced_var (j)));
/* If the name tag is call clobbered, so is the type tag
associated with the base VAR_DECL. */
- if (ann->name_mem_tag
+ if (pi->name_mem_tag
&& v_ann->type_mem_tag
- && is_call_clobbered (ann->name_mem_tag))
+ && is_call_clobbered (pi->name_mem_tag))
mark_call_clobbered (v_ann->type_mem_tag);
}
}
{
size_t j;
tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
- tree name_tag = ssa_name_ann (ptr)->name_mem_tag;
+ tree name_tag = SSA_NAME_PTR_INFO (ptr)->name_mem_tag;
varray_type aliases;
if (name_tag == NULL_TREE)
static void
merge_pointed_to_info (struct alias_info *ai, tree dest, tree orig)
{
- ssa_name_ann_t dest_ann, orig_ann;
+ struct ptr_info_def *dest_pi, *orig_pi;
/* Make sure we have points-to information for ORIG. */
collect_points_to_info_for (ai, orig);
- dest_ann = get_ssa_name_ann (dest);
- orig_ann = ssa_name_ann (orig);
+ dest_pi = get_ptr_info (dest);
+ orig_pi = SSA_NAME_PTR_INFO (orig);
- if (orig_ann)
+ if (orig_pi)
{
- dest_ann->pt_anything |= orig_ann->pt_anything;
- dest_ann->pt_malloc |= orig_ann->pt_malloc;
+ dest_pi->pt_anything |= orig_pi->pt_anything;
+ dest_pi->pt_malloc |= orig_pi->pt_malloc;
- if (orig_ann->pt_vars)
+ if (orig_pi->pt_vars)
{
- if (dest_ann->pt_vars == NULL)
+ if (dest_pi->pt_vars == NULL)
{
- dest_ann->pt_vars = BITMAP_GGC_ALLOC ();
- bitmap_copy (dest_ann->pt_vars, orig_ann->pt_vars);
+ dest_pi->pt_vars = BITMAP_GGC_ALLOC ();
+ bitmap_copy (dest_pi->pt_vars, orig_pi->pt_vars);
}
else
- bitmap_a_or_b (dest_ann->pt_vars,
- dest_ann->pt_vars,
- orig_ann->pt_vars);
- }
+ bitmap_a_or_b (dest_pi->pt_vars,
+ dest_pi->pt_vars,
+ orig_pi->pt_vars);
+ }
}
}
static void
add_pointed_to_expr (tree ptr, tree value)
{
- ssa_name_ann_t ann;
+ struct ptr_info_def *pi;
#if defined ENABLE_CHECKING
/* Pointer variables should have been handled by merge_pointed_to_info. */
abort ();
#endif
- ann = get_ssa_name_ann (ptr);
+ pi = get_ptr_info (ptr);
/* If VALUE is the result of a malloc-like call, then the area pointed to
PTR is guaranteed to not alias with anything else. */
if (TREE_CODE (value) == CALL_EXPR
&& (call_expr_flags (value) & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
- ann->pt_malloc = 1;
+ pi->pt_malloc = 1;
else
- ann->pt_anything = 1;
+ pi->pt_anything = 1;
if (dump_file)
{
fprintf (dump_file, "Pointer ");
print_generic_expr (dump_file, ptr, dump_flags);
fprintf (dump_file, " points to ");
- if (ann->pt_malloc)
+ if (pi->pt_malloc)
fprintf (dump_file, "malloc space: ");
else
fprintf (dump_file, "an arbitrary address: ");
if (TREE_CODE (value) == ADDR_EXPR)
{
tree pt_var;
- ssa_name_ann_t ann;
+ struct ptr_info_def *pi;
size_t uid;
pt_var = TREE_OPERAND (value, 0);
if (pt_var && SSA_VAR_P (pt_var))
{
- ann = get_ssa_name_ann (ptr);
+ pi = get_ptr_info (ptr);
uid = var_ann (pt_var)->uid;
- if (ann->pt_vars == NULL)
- ann->pt_vars = BITMAP_GGC_ALLOC ();
- bitmap_set_bit (ann->pt_vars, uid);
+ if (pi->pt_vars == NULL)
+ pi->pt_vars = BITMAP_GGC_ALLOC ();
+ bitmap_set_bit (pi->pt_vars, uid);
bitmap_set_bit (ai->addresses_needed, uid);
}
else
else if (TREE_CODE (stmt) == ASM_EXPR)
{
/* Pointers defined by __asm__ statements can point anywhere. */
- ssa_name_ann_t ann = get_ssa_name_ann (var);
- ann->pt_anything = 1;
+ get_ptr_info (var)->pt_anything = 1;
}
else if (IS_EMPTY_STMT (stmt))
{
static tree
get_nmt_for (tree ptr)
{
- ssa_name_ann_t ptr_ann = ssa_name_ann (ptr);
- tree tag = ptr_ann->name_mem_tag;
+ struct ptr_info_def *pi = get_ptr_info (ptr);
+ tree tag = pi->name_mem_tag;
if (tag == NULL_TREE)
{
mark_call_clobbered (tag);
/* Similarly, if PTR points to malloc, then TAG is a global. */
- if (ptr_ann->pt_malloc)
+ if (pi->pt_malloc)
mark_call_clobbered (tag);
}
}
+/* Return the alias information associated with pointer T. It creates a
+ new instance if none existed. */
+
+static struct ptr_info_def *
+get_ptr_info (tree t)
+{
+ struct ptr_info_def *pi;
+
+#if defined ENABLE_CHECKING
+ if (!POINTER_TYPE_P (TREE_TYPE (t)))
+ abort ();
+#endif
+
+ pi = SSA_NAME_PTR_INFO (t);
+ if (pi == NULL)
+ {
+ pi = ggc_alloc (sizeof (*pi));
+ memset ((void *)pi, 0, sizeof (*pi));
+ SSA_NAME_PTR_INFO (t) = pi;
+ }
+
+ return pi;
+}
+
+
/* Dump points-to information for SSA_NAME PTR into FILE. */
static void
dump_points_to_info_for (FILE *file, tree ptr)
{
- ssa_name_ann_t ann = ssa_name_ann (ptr);
+ struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
fprintf (file, "Pointer ");
print_generic_expr (file, ptr, dump_flags);
- if (ann == NULL)
+ if (pi == NULL)
return;
- if (ann->name_mem_tag)
+ if (pi->name_mem_tag)
{
fprintf (file, ", name memory tag: ");
- print_generic_expr (file, ann->name_mem_tag, dump_flags);
+ print_generic_expr (file, pi->name_mem_tag, dump_flags);
}
- if (ann->value_escapes_p)
+ if (pi->value_escapes_p)
fprintf (file, ", its value escapes");
- if (ann->pt_anything)
+ if (pi->pt_anything)
fprintf (file, ", points-to anything");
- if (ann->pt_malloc)
+ if (pi->pt_malloc)
fprintf (file, ", points-to malloc");
- if (ann->pt_vars)
+ if (pi->pt_vars)
{
unsigned ix;
fprintf (file, ", points-to vars: { ");
- EXECUTE_IF_SET_IN_BITMAP (ann->pt_vars, 0, ix,
+ EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix,
{
print_generic_expr (file, referenced_var (ix), dump_flags);
fprintf (file, " ");