/* Alias analysis for trees.
- Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
This file is part of GCC.
struct alias_map_d **pointers;
size_t num_pointers;
- /* Variables that have been written to directly (i.e., not through a
- pointer dereference). */
- struct pointer_set_t *written_vars;
-
- /* Pointers that have been used in an indirect store operation. */
- struct pointer_set_t *dereferenced_ptrs_store;
-
- /* Pointers that have been used in an indirect load operation. */
- struct pointer_set_t *dereferenced_ptrs_load;
+ /* Pointers that have been used in an indirect load/store operation. */
+ struct pointer_set_t *dereferenced_ptrs;
};
dump_referenced_vars (dump_file);
}
- /* Report strict aliasing violations. */
- strict_aliasing_warning_backend ();
-
/* Deallocate memory used by aliasing data structures. */
delete_alias_info (ai);
struct alias_info *ai;
referenced_var_iterator rvi;
tree var;
+ static bool alias_bitmap_obstack_initialized;
ai = XCNEW (struct alias_info);
ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
sbitmap_zero (ai->ssa_names_visited);
ai->processed_ptrs = VEC_alloc (tree, heap, 50);
- ai->written_vars = pointer_set_create ();
- ai->dereferenced_ptrs_store = pointer_set_create ();
- ai->dereferenced_ptrs_load = pointer_set_create ();
+ ai->dereferenced_ptrs = pointer_set_create ();
/* Clear out all memory reference stats. */
init_mem_ref_stats ();
/* Next time, we will need to reset alias information. */
cfun->gimple_df->aliases_computed_p = true;
- if (alias_bitmap_obstack.elements != NULL)
+ if (alias_bitmap_obstack_initialized)
bitmap_obstack_release (&alias_bitmap_obstack);
bitmap_obstack_initialize (&alias_bitmap_obstack);
+ alias_bitmap_obstack_initialized = true;
return ai;
}
free (ai->pointers[i]);
free (ai->pointers);
- pointer_set_destroy (ai->written_vars);
- pointer_set_destroy (ai->dereferenced_ptrs_store);
- pointer_set_destroy (ai->dereferenced_ptrs_load);
+ pointer_set_destroy (ai->dereferenced_ptrs);
free (ai);
delete_mem_ref_stats (cfun);
{
struct alias_map_d *v_map;
var_ann_t v_ann;
- bool tag_stored_p, var_stored_p;
v_map = ai->addressable_vars[j];
var = v_map->var;
v_ann = var_ann (var);
- /* Skip memory tags and variables that have never been
- written to. We also need to check if the variables are
- call-clobbered because they may be overwritten by
- function calls. */
- tag_stored_p = pointer_set_contains (ai->written_vars, tag)
- || is_call_clobbered (tag);
- var_stored_p = pointer_set_contains (ai->written_vars, var)
- || is_call_clobbered (var);
- if (!tag_stored_p && !var_stored_p)
- continue;
-
+ /* We used to skip variables that have never been written to
+ if the memory tag has been never written to directly (or
+ either of them were call clobbered). This is not enough
+ though, as this misses writes through the tags aliases.
+ So, for correctness we need to include any aliased
+ variable here. */
+
if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
{
/* Add VAR to TAG's may-aliases set. */
if (addr_taken)
bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
+ /* If we have a call or an assignment, see if the lhs contains
+ a local decl that requires not to be a gimple register. */
+ if (gimple_code (stmt) == GIMPLE_ASSIGN
+ || gimple_code (stmt) == GIMPLE_CALL)
+ {
+ tree lhs = gimple_get_lhs (stmt);
+ /* A plain decl does not need it set. */
+ if (lhs && handled_component_p (lhs))
+ {
+ tree var = get_base_address (lhs);
+ if (DECL_P (var)
+ /* We are not going to mess with RESULT_DECL anyway. */
+ && TREE_CODE (var) != RESULT_DECL
+ && is_gimple_reg_type (TREE_TYPE (var)))
+ bitmap_set_bit (gimple_addressable_vars (cfun), DECL_UID (var));
+ }
+ }
+
/* Process each operand use. For pointers, determine whether they
are dereferenced by the statement, or whether their value
escapes, etc. */
/* ??? For always executed direct dereferences we can
apply TBAA-pruning to their escape set. */
- /* If this is a store operation, mark OP as being
- dereferenced to store, otherwise mark it as being
- dereferenced to load. */
- if (num_stores > 0)
- pointer_set_insert (ai->dereferenced_ptrs_store, var);
- else
- pointer_set_insert (ai->dereferenced_ptrs_load, var);
+ /* Mark OP as being dereferenced. */
+ pointer_set_insert (ai->dereferenced_ptrs, var);
/* Update the frequency estimate for all the dereferences of
pointer OP. */
if (is_gimple_call (stmt)
|| stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
{
- pointer_set_insert (ai->dereferenced_ptrs_store, var);
+ pointer_set_insert (ai->dereferenced_ptrs, var);
pi->memory_tag_needed = 1;
}
}
dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
memory symbols in its argument list, but these cases do not
occur so frequently as to constitute a serious problem. */
- if (gimple_stored_syms (stmt))
- EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
- {
- tree sym = referenced_var (i);
- pointer_set_insert (ai->written_vars, sym);
- if (!stmt_dereferences_ptr_p
- && stmt_escape_type != ESCAPE_TO_CALL
- && stmt_escape_type != ESCAPE_TO_PURE_CONST
- && stmt_escape_type != ESCAPE_TO_ASM)
- update_mem_sym_stats_from_stmt (sym, stmt, 0, 1);
- }
-
if (!stmt_dereferences_ptr_p
- && gimple_loaded_syms (stmt)
&& stmt_escape_type != ESCAPE_TO_CALL
&& stmt_escape_type != ESCAPE_TO_PURE_CONST
&& stmt_escape_type != ESCAPE_TO_ASM)
- EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
- update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
+ {
+ if (gimple_stored_syms (stmt))
+ EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
+ update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 0, 1);
+
+ if (gimple_loaded_syms (stmt))
+ EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
+ update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
+ }
}
}
/* Since we don't keep track of volatile variables, assume that
these pointers are used in indirect store operations. */
if (TREE_THIS_VOLATILE (var))
- pointer_set_insert (ai->dereferenced_ptrs_store, var);
+ pointer_set_insert (ai->dereferenced_ptrs, var);
num_pointers++;
}
array and create a symbol memory tag for them. */
if (POINTER_TYPE_P (TREE_TYPE (var)))
{
- if ((pointer_set_contains (ai->dereferenced_ptrs_store, var)
- || pointer_set_contains (ai->dereferenced_ptrs_load, var)))
+ if (pointer_set_contains (ai->dereferenced_ptrs, var))
{
tree tag, old_tag;
var_ann_t t_ann;
/* Associate the tag with pointer VAR. */
set_symbol_mem_tag (var, tag);
-
- /* If pointer VAR has been used in a store operation,
- then its memory tag must be marked as written-to. */
- if (pointer_set_contains (ai->dereferenced_ptrs_store, var))
- pointer_set_insert (ai->written_vars, tag);
}
else
{
return false;
}
- /* If either MEM or VAR is a read-only global and the other one
- isn't, then PTR cannot point to VAR. */
- if ((unmodifiable_var_p (mem) && !unmodifiable_var_p (var))
- || (unmodifiable_var_p (var) && !unmodifiable_var_p (mem)))
- {
- alias_stats.alias_noalias++;
- alias_stats.simple_resolved++;
- return false;
- }
-
/* If the pointed to memory has alias set zero, or the pointer
is ref-all, or the pointer decl is marked that no TBAA is to
be applied, the MEM can alias VAR. */
Applications (OOPSLA), pp. 1-19, 1999. */
return ESCAPE_STORED_IN_GLOBAL;
}
- else if (gimple_code (stmt) == RETURN_EXPR)
+ else if (gimple_code (stmt) == GIMPLE_RETURN)
return ESCAPE_TO_RETURN;
return NO_ESCAPE;
size_t i;
tree tag;
tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
- alias_set_type tag_set = get_alias_set (tag_type);
+ alias_set_type tag_set;
+
+ /* Get the alias set to be used for the pointed-to memory. If that
+ differs from what we would get from looking at the type adjust
+ the tag_type to void to make sure we get a proper alias set from
+ just looking at the SMT we create. */
+ tag_set = get_alias_set (tag_type);
+ if (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr))
+ /* This is overly conservative but we do not want to assign
+ restrict alias sets here (which if they are not assigned
+ are -2 but still "known"). */
+ || DECL_POINTER_ALIAS_SET_KNOWN_P (ptr))
+ {
+ tag_set = 0;
+ tag_type = void_type_node;
+ }
/* To avoid creating unnecessary memory tags, only create one memory tag
per alias set class. Note that it may be tempting to group
artificial variable representing the memory location
pointed-to by PTR. */
tag = symbol_mem_tag (ptr);
- if (tag == NULL_TREE)
+ if (tag == NULL_TREE
+ || tag_set != get_alias_set (tag))
tag = create_memory_tag (tag_type, true);
/* Add PTR to the POINTERS array. Note that we are not interested in