EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i,
{
tree var = referenced_var (i);
- DECL_NEEDS_TO_LIVE_IN_MEMORY_INTERNAL (var) = 0;
/* Variables that are intrinsically call-clobbered (globals,
local statics, etc) will not be marked by the aliasing
{
basic_block bb;
size_t i;
+ tree op;
+ ssa_op_iter iter;
timevar_push (TV_TREE_PTA);
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{
- use_optype uses;
- def_optype defs;
- v_may_def_optype v_may_defs;
- v_must_def_optype v_must_defs;
- stmt_ann_t ann;
bitmap addr_taken;
tree stmt = bsi_stmt (si);
bool stmt_escapes_p = is_escape_site (stmt, &ai->num_calls_found);
mark_call_clobbered (var);
});
- ann = stmt_ann (stmt);
- uses = USE_OPS (ann);
- for (i = 0; i < NUM_USES (uses); i++)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
{
- tree op = USE_OP (uses, i);
var_ann_t v_ann = var_ann (SSA_NAME_VAR (op));
struct ptr_info_def *pi;
bool is_store;
collect_points_to_info_for (ai, op);
- pi = SSA_NAME_PTR_INFO (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
- malloc, then mark it as being dereferenced. In a
- subsequent pass, dereferenced pointers that point
- to a set of variables will be assigned a name tag
- to alias all the variables OP points to. */
- if (pi->pt_malloc || pi->pt_vars)
- pi->is_dereferenced = 1;
+ /* Mark OP as dereferenced. In a subsequent pass,
+ dereferenced pointers that point to a set of
+ variables will be assigned a name tag to alias
+ all the variables OP points to. */
+ pi->is_dereferenced = 1;
/* Keep track of how many time we've dereferenced each
pointer. Again, we don't need to grow
that pointer OP will be dereferenced in a store
operation inside the called function. */
if (get_call_expr_in (stmt))
- bitmap_set_bit (ai->dereferenced_ptrs_store, v_ann->uid);
+ {
+ bitmap_set_bit (ai->dereferenced_ptrs_store, v_ann->uid);
+ pi->is_dereferenced = 1;
+ }
}
}
/* Update reference counter for definitions to any
potentially aliased variable. This is used in the alias
grouping heuristics. */
- defs = DEF_OPS (ann);
- for (i = 0; i < NUM_DEFS (defs); i++)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
{
- tree op = DEF_OP (defs, i);
tree var = SSA_NAME_VAR (op);
var_ann_t ann = var_ann (var);
bitmap_set_bit (ai->written_vars, ann->uid);
}
/* Mark variables in V_MAY_DEF operands as being written to. */
- v_may_defs = V_MAY_DEF_OPS (ann);
- for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_DEFS)
{
- tree op = V_MAY_DEF_OP (v_may_defs, i);
tree var = SSA_NAME_VAR (op);
var_ann_t ann = var_ann (var);
bitmap_set_bit (ai->written_vars, ann->uid);
}
- /* Mark variables in V_MUST_DEF operands as being written to. */
- v_must_defs = V_MUST_DEF_OPS (ann);
- for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
- {
- tree op = V_MUST_DEF_OP (v_must_defs, i);
- tree var = SSA_NAME_VAR (op);
- var_ann_t ann = var_ann (var);
- bitmap_set_bit (ai->written_vars, ann->uid);
- }
-
/* After promoting variables and computing aliasing we will
need to re-scan most statements. FIXME: Try to minimize the
number of statements re-scanned. It's not really necessary to
tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
- if (!pi->is_dereferenced)
+ if (pi->pt_anything || !pi->is_dereferenced)
{
/* No name tags for pointers that have not been
- dereferenced. */
+ dereferenced or point to an arbitrary location. */
pi->name_mem_tag = NULL_TREE;
continue;
}
- if (pi->pt_vars)
+ if (pi->pt_vars
+ && bitmap_first_set_bit (pi->pt_vars) >= 0)
{
size_t j;
tree old_name_tag = pi->name_mem_tag;
if (pi->value_escapes_p || pi->pt_anything)
{
/* If PTR escapes or may point to anything, then its associated
- memory tags are call-clobbered. */
+ memory tags and pointed-to variables are call-clobbered. */
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 (pi->pt_anything)
- {
- HOST_WIDE_INT ptr_set;
- ptr_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
- for (j = 0; j < ai->num_addressable_vars; j++)
- {
- struct alias_map_d *alias_map = ai->addressable_vars[j];
- if (alias_map->set == ptr_set)
- mark_call_clobbered (alias_map->var);
- }
- }
-
- /* If PTR's value may escape and PTR is never dereferenced, we
- need to mark all the variables PTR points-to as
- call-clobbered. Note that we only need do this it PTR is
- never dereferenced. If PTR is dereferenced, it will have a
- 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 (pi->value_escapes_p
- && pi->name_mem_tag == NULL_TREE
- && pi->pt_vars)
+ if (pi->pt_vars)
EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j,
mark_call_clobbered (referenced_var (j)));
}
{
if (!bitmap_bit_p (ai->addresses_needed, v_ann->uid)
&& v_ann->mem_tag_kind == NOT_A_TAG
- && !needs_to_live_in_memory (var))
+ && !is_global_var (var))
{
/* The address of VAR is not needed, remove the
addressable bit, so that it can be optimized as a
/* If pointer VAR is a global variable or a PARM_DECL,
then its memory tag should be considered a global
variable. */
- if (TREE_CODE (var) == PARM_DECL || needs_to_live_in_memory (var))
+ if (TREE_CODE (var) == PARM_DECL || is_global_var (var))
mark_call_clobbered (tag);
/* All the dereferences of pointer VAR count as
if (alias == VARRAY_TREE (v_ann->may_aliases, i))
return;
- /* If VAR is a call-clobbered variable, so is its new ALIAS. */
+ /* If VAR is a call-clobbered variable, so is its new ALIAS.
+ FIXME, call-clobbering should only depend on whether an address
+ escapes. It should be independent of aliasing. */
if (is_call_clobbered (var))
mark_call_clobbered (alias);
var_ann_t v_ann = var_ann (var);
VARRAY_TREE (v_ann->may_aliases, i) = new_alias;
- /* If VAR is a call-clobbered variable, so is NEW_ALIAS. */
+ /* If VAR is a call-clobbered variable, so is NEW_ALIAS.
+ FIXME, call-clobbering should only depend on whether an address
+ escapes. It should be independent of aliasing. */
if (is_call_clobbered (var))
mark_call_clobbered (new_alias);
pi->pt_anything = 1;
pi->pt_malloc = 0;
- pi->pt_vars = NULL;
- pi->is_dereferenced = 0;
/* The pointer used to have a name tag, but we now found it pointing
to an arbitrary location. The name tag needs to be renamed and
orig_pi->pt_vars);
}
}
+ else
+ set_pt_anything (dest);
}
add_pointed_to_var (struct alias_info *ai, tree ptr, tree value)
{
struct ptr_info_def *pi = get_ptr_info (ptr);
+ tree pt_var;
+ size_t uid;
- if (TREE_CODE (value) == ADDR_EXPR)
- {
- tree pt_var;
- size_t uid;
+#if defined ENABLE_CHECKING
+ if (TREE_CODE (value) != ADDR_EXPR)
+ abort ();
+#endif
- pt_var = TREE_OPERAND (value, 0);
- if (TREE_CODE_CLASS (TREE_CODE (pt_var)) == 'r')
- pt_var = get_base_address (pt_var);
+ pt_var = TREE_OPERAND (value, 0);
+ if (TREE_CODE_CLASS (TREE_CODE (pt_var)) == 'r')
+ pt_var = get_base_address (pt_var);
- if (pt_var && SSA_VAR_P (pt_var))
- {
- uid = var_ann (pt_var)->uid;
- bitmap_set_bit (ai->addresses_needed, uid);
+ if (pt_var && SSA_VAR_P (pt_var))
+ {
+ uid = var_ann (pt_var)->uid;
+ bitmap_set_bit (ai->addresses_needed, uid);
- /* If PTR has already been found to point anywhere, don't
- add the variable to PTR's points-to set. */
- if (!pi->pt_anything)
- {
- if (pi->pt_vars == NULL)
- pi->pt_vars = BITMAP_GGC_ALLOC ();
- bitmap_set_bit (pi->pt_vars, uid);
- }
- }
- else
- add_pointed_to_expr (ptr, value);
+ if (pi->pt_vars == NULL)
+ pi->pt_vars = BITMAP_GGC_ALLOC ();
+ bitmap_set_bit (pi->pt_vars, uid);
+
+ /* If the variable is a global, mark the pointer as pointing to
+ global memory (which will make its tag a global variable). */
+ if (is_global_var (pt_var))
+ pi->pt_global_mem = 1;
}
- else
- add_pointed_to_expr (ptr, value);
}
tree rhs = TREE_OPERAND (stmt, 1);
STRIP_NOPS (rhs);
- /* Found P_i = CONST. */
- if (is_gimple_min_invariant (rhs))
+ /* Found P_i = ADDR_EXPR */
+ if (TREE_CODE (rhs) == ADDR_EXPR)
add_pointed_to_var (ai, var, rhs);
/* Found P_i = Q_j. */
tree op0 = TREE_OPERAND (rhs, 0);
tree op1 = TREE_OPERAND (rhs, 1);
- if (TREE_CODE (op0) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (op0)))
- merge_pointed_to_info (ai, var, op0);
- else if (TREE_CODE (op1) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (op1)))
- merge_pointed_to_info (ai, var, op1);
- else if (is_gimple_min_invariant (op0))
- add_pointed_to_var (ai, var, op0);
- else if (is_gimple_min_invariant (op1))
- add_pointed_to_var (ai, var, op1);
- else
+ /* Both operands may be of pointer type. FIXME: Shouldn't
+ we just expect PTR + OFFSET always? */
+ if (POINTER_TYPE_P (TREE_TYPE (op0)))
+ {
+ if (TREE_CODE (op0) == SSA_NAME)
+ merge_pointed_to_info (ai, var, op0);
+ else if (TREE_CODE (op0) == ADDR_EXPR)
+ add_pointed_to_var (ai, var, op0);
+ else
+ add_pointed_to_expr (var, op0);
+ }
+
+ if (POINTER_TYPE_P (TREE_TYPE (op1)))
+ {
+ if (TREE_CODE (op1) == SSA_NAME)
+ merge_pointed_to_info (ai, var, op1);
+ else if (TREE_CODE (op1) == ADDR_EXPR)
+ add_pointed_to_var (ai, var, op1);
+ else
+ add_pointed_to_expr (var, op1);
+ }
+
+ /* Neither operand is a pointer? VAR can be pointing
+ anywhere. FIXME: Is this right? If we get here, we
+ found PTR = INT_CST + INT_CST. */
+ if (!POINTER_TYPE_P (TREE_TYPE (op0))
+ && !POINTER_TYPE_P (TREE_TYPE (op1)))
add_pointed_to_expr (var, rhs);
}
variable that we are analyzing is the LHS of the PHI node. */
tree lhs = PHI_RESULT (stmt);
- if (is_gimple_min_invariant (var))
+ if (TREE_CODE (var) == ADDR_EXPR)
add_pointed_to_var (ai, lhs, var);
else if (TREE_CODE (var) == SSA_NAME)
- {
- if (bitmap_bit_p (ai->ssa_names_visited, SSA_NAME_VERSION (var)))
- merge_pointed_to_info (ai, lhs, var);
- else
- set_pt_anything (lhs);
- }
+ merge_pointed_to_info (ai, lhs, var);
+ else if (is_gimple_min_invariant (var))
+ add_pointed_to_expr (lhs, var);
else
abort ();
}
tree tag = pi->name_mem_tag;
if (tag == NULL_TREE)
- {
- tag = create_memory_tag (TREE_TYPE (TREE_TYPE (ptr)), false);
+ tag = create_memory_tag (TREE_TYPE (TREE_TYPE (ptr)), false);
- /* If PTR is a PARM_DECL, its memory tag should be considered a
- global variable. */
- if (TREE_CODE (SSA_NAME_VAR (ptr)) == PARM_DECL)
- mark_call_clobbered (tag);
-
- /* Similarly, if PTR points to malloc, then TAG is a global. */
- if (pi->pt_malloc)
- mark_call_clobbered (tag);
- }
+ /* If PTR is a PARM_DECL, it points to a global variable or malloc,
+ then its name tag should be considered a global variable. */
+ if (TREE_CODE (SSA_NAME_VAR (ptr)) == PARM_DECL
+ || pi->pt_malloc
+ || pi->pt_global_mem)
+ mark_call_clobbered (tag);
return tag;
}
basic_block bb;
block_stmt_iterator si;
size_t i;
+ ssa_op_iter iter;
const char *fname =
lang_hooks.decl_printable_name (current_function_decl, 2);
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{
- stmt_ann_t ann = stmt_ann (bsi_stmt (si));
- def_optype defs = DEF_OPS (ann);
- if (defs)
- for (i = 0; i < NUM_DEFS (defs); i++)
- if (POINTER_TYPE_P (TREE_TYPE (DEF_OP (defs, i))))
- dump_points_to_info_for (file, DEF_OP (defs, i));
+ tree stmt = bsi_stmt (si);
+ tree def;
+ FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
+ if (POINTER_TYPE_P (TREE_TYPE (def)))
+ dump_points_to_info_for (file, def);
}
}
if (TREE_ADDRESSABLE (var))
return true;
- /* Automatic variables can't have their addresses escape any other way. */
- if (!TREE_STATIC (var))
- return false;
-
/* Globally visible variables can have their addresses taken by other
translation units. */
if (DECL_EXTERNAL (var) || TREE_PUBLIC (var))
return true;
+ /* Automatic variables can't have their addresses escape any other way.
+ This must be after the check for global variables, as extern declarations
+ do not have TREE_STATIC set. */
+ if (!TREE_STATIC (var))
+ return false;
+
/* If we're in unit-at-a-time mode, then we must have seen all occurrences
of address-of operators, and so we can trust TREE_ADDRESSABLE. Otherwise
we can only be sure the variable isn't addressable if it's local to the