mirror of git://gcc.gnu.org/git/gcc.git
tree-ssa-structalias.c (callused_id, [...]): Add.
2008-06-28 Richard Guenther <rguenther@suse.de> * tree-ssa-structalias.c (callused_id, var_callused, callused_tree): Add. (handle_pure_call): New function. (find_func_aliases): Call it. (find_what_p_points_to): Handle the call-used set. (clobber_what_escaped): Likewise. (compute_call_used_vars): New function. (init_base_vars): Init the call-used variable. (do_sd_constraint): Do not propagate the solution from CALLUSED but use CALLUSED as a placeholder. (solve_graph): Likewise. * tree-flow-inline.h (gimple_call_used_vars): New function. * tree-flow.h (struct gimple_df): Add call_used_vars bitmap. (compute_call_used_vars): Declare. * tree-ssa-alias.c (set_initial_properties): Call compute_call_used_vars. (reset_alias_info): Clear call-used variables. (add_call_clobber_ops): Assert we are not called for const/pure functions. Remove handling of them. (add_call_read_ops): Handle pure functions by adding the call-used set of variables as VUSEs. * tree-ssa.c (init_tree_ssa): Allocate call-used bitmap. (delete_tree_ssa): Free it. * tree-dfa.c (remove_referenced_var): Clear the var from the call-used bitmap. * gcc.dg/tree-ssa/pr24287.c: Remove XFAIL. From-SVN: r137222
This commit is contained in:
parent
ff1c393bd3
commit
15c151967d
|
|
@ -1,3 +1,31 @@
|
||||||
|
2008-06-28 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
* tree-ssa-structalias.c (callused_id, var_callused,
|
||||||
|
callused_tree): Add.
|
||||||
|
(handle_pure_call): New function.
|
||||||
|
(find_func_aliases): Call it.
|
||||||
|
(find_what_p_points_to): Handle the call-used set.
|
||||||
|
(clobber_what_escaped): Likewise.
|
||||||
|
(compute_call_used_vars): New function.
|
||||||
|
(init_base_vars): Init the call-used variable.
|
||||||
|
(do_sd_constraint): Do not propagate the solution from CALLUSED
|
||||||
|
but use CALLUSED as a placeholder.
|
||||||
|
(solve_graph): Likewise.
|
||||||
|
* tree-flow-inline.h (gimple_call_used_vars): New function.
|
||||||
|
* tree-flow.h (struct gimple_df): Add call_used_vars bitmap.
|
||||||
|
(compute_call_used_vars): Declare.
|
||||||
|
* tree-ssa-alias.c (set_initial_properties): Call
|
||||||
|
compute_call_used_vars.
|
||||||
|
(reset_alias_info): Clear call-used variables.
|
||||||
|
(add_call_clobber_ops): Assert we are not called for const/pure
|
||||||
|
functions. Remove handling of them.
|
||||||
|
(add_call_read_ops): Handle pure functions by adding the
|
||||||
|
call-used set of variables as VUSEs.
|
||||||
|
* tree-ssa.c (init_tree_ssa): Allocate call-used bitmap.
|
||||||
|
(delete_tree_ssa): Free it.
|
||||||
|
* tree-dfa.c (remove_referenced_var): Clear the var from the
|
||||||
|
call-used bitmap.
|
||||||
|
|
||||||
2008-06-28 Kai Tietz <kai.tietz@onevision.com>
|
2008-06-28 Kai Tietz <kai.tietz@onevision.com>
|
||||||
|
|
||||||
* tree.c (build_varargs_function_type_list): New.
|
* tree.c (build_varargs_function_type_list): New.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
2008-06-28 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
* gcc.dg/tree-ssa/pr24287.c: Remove XFAIL.
|
||||||
|
|
||||||
2008-06-27 Mark Mitchell <mark@codesourcery.com>
|
2008-06-27 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
* g++.dg/abi/arm_cxa_vec2.C: New test.
|
* g++.dg/abi/arm_cxa_vec2.C: New test.
|
||||||
|
|
|
||||||
|
|
@ -21,5 +21,5 @@ int g(void)
|
||||||
link_error ();
|
link_error ();
|
||||||
return t2 == 2;
|
return t2 == 2;
|
||||||
}
|
}
|
||||||
/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail *-*-* } } } */
|
/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */
|
||||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
||||||
|
|
|
||||||
|
|
@ -746,6 +746,7 @@ remove_referenced_var (tree var)
|
||||||
unsigned int uid = DECL_UID (var);
|
unsigned int uid = DECL_UID (var);
|
||||||
|
|
||||||
clear_call_clobbered (var);
|
clear_call_clobbered (var);
|
||||||
|
bitmap_clear_bit (gimple_call_used_vars (cfun), uid);
|
||||||
if ((v_ann = var_ann (var)))
|
if ((v_ann = var_ann (var)))
|
||||||
{
|
{
|
||||||
/* Preserve var_anns of globals, but clear their alias info. */
|
/* Preserve var_anns of globals, but clear their alias info. */
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,15 @@ gimple_call_clobbered_vars (const struct function *fun)
|
||||||
return fun->gimple_df->call_clobbered_vars;
|
return fun->gimple_df->call_clobbered_vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Call-used variables in the function. If bit I is set, then
|
||||||
|
REFERENCED_VARS (I) is call-used at pure function call-sites. */
|
||||||
|
static inline bitmap
|
||||||
|
gimple_call_used_vars (const struct function *fun)
|
||||||
|
{
|
||||||
|
gcc_assert (fun && fun->gimple_df);
|
||||||
|
return fun->gimple_df->call_used_vars;
|
||||||
|
}
|
||||||
|
|
||||||
/* Array of all variables referenced in the function. */
|
/* Array of all variables referenced in the function. */
|
||||||
static inline htab_t
|
static inline htab_t
|
||||||
gimple_referenced_vars (const struct function *fun)
|
gimple_referenced_vars (const struct function *fun)
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,10 @@ struct gimple_df GTY(())
|
||||||
REFERENCED_VARS (I) is call-clobbered. */
|
REFERENCED_VARS (I) is call-clobbered. */
|
||||||
bitmap call_clobbered_vars;
|
bitmap call_clobbered_vars;
|
||||||
|
|
||||||
|
/* Call-used variables in the function. If bit I is set, then
|
||||||
|
REFERENCED_VARS (I) is call-used at pure function call-sites. */
|
||||||
|
bitmap call_used_vars;
|
||||||
|
|
||||||
/* Addressable variables in the function. If bit I is set, then
|
/* Addressable variables in the function. If bit I is set, then
|
||||||
REFERENCED_VARS (I) has had its address taken. Note that
|
REFERENCED_VARS (I) has had its address taken. Note that
|
||||||
CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related. An
|
CALL_CLOBBERED_VARS and ADDRESSABLE_VARS are not related. An
|
||||||
|
|
@ -1174,6 +1178,7 @@ tree gimple_fold_indirect_ref (tree);
|
||||||
/* In tree-ssa-structalias.c */
|
/* In tree-ssa-structalias.c */
|
||||||
bool find_what_p_points_to (tree);
|
bool find_what_p_points_to (tree);
|
||||||
bool clobber_what_escaped (void);
|
bool clobber_what_escaped (void);
|
||||||
|
void compute_call_used_vars (void);
|
||||||
|
|
||||||
/* In tree-ssa-live.c */
|
/* In tree-ssa-live.c */
|
||||||
extern void remove_unused_locals (void);
|
extern void remove_unused_locals (void);
|
||||||
|
|
|
||||||
|
|
@ -505,7 +505,7 @@ compute_tag_properties (void)
|
||||||
VEC_free (tree, heap, taglist);
|
VEC_free (tree, heap, taglist);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the initial variable clobbers and globalness.
|
/* Set up the initial variable clobbers, call-uses and globalness.
|
||||||
When this function completes, only tags whose aliases need to be
|
When this function completes, only tags whose aliases need to be
|
||||||
clobbered will be set clobbered. Tags clobbered because they
|
clobbered will be set clobbered. Tags clobbered because they
|
||||||
contain call clobbered vars are handled in compute_tag_properties. */
|
contain call clobbered vars are handled in compute_tag_properties. */
|
||||||
|
|
@ -543,6 +543,8 @@ set_initial_properties (struct alias_info *ai)
|
||||||
pt_anything_mask |= ESCAPE_TO_CALL;
|
pt_anything_mask |= ESCAPE_TO_CALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compute_call_used_vars ();
|
||||||
|
|
||||||
for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
|
for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
|
||||||
{
|
{
|
||||||
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
|
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
|
||||||
|
|
@ -2000,6 +2002,9 @@ reset_alias_info (void)
|
||||||
/* There should be no call-clobbered variable left. */
|
/* There should be no call-clobbered variable left. */
|
||||||
gcc_assert (bitmap_empty_p (gimple_call_clobbered_vars (cfun)));
|
gcc_assert (bitmap_empty_p (gimple_call_clobbered_vars (cfun)));
|
||||||
|
|
||||||
|
/* Clear the call-used variables. */
|
||||||
|
bitmap_clear (gimple_call_used_vars (cfun));
|
||||||
|
|
||||||
/* Clear flow-sensitive points-to information from each SSA name. */
|
/* Clear flow-sensitive points-to information from each SSA name. */
|
||||||
for (i = 1; i < num_ssa_names; i++)
|
for (i = 1; i < num_ssa_names; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1660,7 +1660,10 @@ add_call_clobber_ops (tree stmt, tree callee)
|
||||||
bitmap_iterator bi;
|
bitmap_iterator bi;
|
||||||
stmt_ann_t s_ann = stmt_ann (stmt);
|
stmt_ann_t s_ann = stmt_ann (stmt);
|
||||||
bitmap not_read_b, not_written_b;
|
bitmap not_read_b, not_written_b;
|
||||||
|
tree call = get_call_expr_in (stmt);
|
||||||
|
|
||||||
|
gcc_assert (!(call_expr_flags (call) & (ECF_PURE | ECF_CONST)));
|
||||||
|
|
||||||
/* If we created .GLOBAL_VAR earlier, just use it. */
|
/* If we created .GLOBAL_VAR earlier, just use it. */
|
||||||
if (gimple_global_var (cfun))
|
if (gimple_global_var (cfun))
|
||||||
{
|
{
|
||||||
|
|
@ -1674,12 +1677,10 @@ add_call_clobber_ops (tree stmt, tree callee)
|
||||||
or write that variable. */
|
or write that variable. */
|
||||||
not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
|
not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
|
||||||
not_written_b = callee ? ipa_reference_get_not_written_global (callee) : NULL;
|
not_written_b = callee ? ipa_reference_get_not_written_global (callee) : NULL;
|
||||||
|
|
||||||
/* Add a VDEF operand for every call clobbered variable. */
|
/* Add a VDEF operand for every call clobbered variable. */
|
||||||
EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
|
EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
|
||||||
{
|
{
|
||||||
tree var = referenced_var_lookup (u);
|
tree var = referenced_var_lookup (u);
|
||||||
unsigned int escape_mask = var_ann (var)->escape_mask;
|
|
||||||
tree real_var = var;
|
tree real_var = var;
|
||||||
bool not_read;
|
bool not_read;
|
||||||
bool not_written;
|
bool not_written;
|
||||||
|
|
@ -1697,24 +1698,6 @@ add_call_clobber_ops (tree stmt, tree callee)
|
||||||
|
|
||||||
/* See if this variable is really clobbered by this function. */
|
/* See if this variable is really clobbered by this function. */
|
||||||
|
|
||||||
/* Trivial case: Things escaping only to pure/const are not
|
|
||||||
clobbered by non-pure-const, and only read by pure/const. */
|
|
||||||
if ((escape_mask & ~(ESCAPE_TO_PURE_CONST)) == 0)
|
|
||||||
{
|
|
||||||
tree call = get_call_expr_in (stmt);
|
|
||||||
if (call_expr_flags (call) & (ECF_CONST | ECF_PURE))
|
|
||||||
{
|
|
||||||
add_virtual_operand (var, s_ann, opf_use, NULL, 0, -1, true);
|
|
||||||
clobber_stats.unescapable_clobbers_avoided++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clobber_stats.unescapable_clobbers_avoided++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not_written)
|
if (not_written)
|
||||||
{
|
{
|
||||||
clobber_stats.static_write_clobbers_avoided++;
|
clobber_stats.static_write_clobbers_avoided++;
|
||||||
|
|
@ -1739,18 +1722,47 @@ add_call_read_ops (tree stmt, tree callee)
|
||||||
bitmap_iterator bi;
|
bitmap_iterator bi;
|
||||||
stmt_ann_t s_ann = stmt_ann (stmt);
|
stmt_ann_t s_ann = stmt_ann (stmt);
|
||||||
bitmap not_read_b;
|
bitmap not_read_b;
|
||||||
|
tree call = get_call_expr_in (stmt);
|
||||||
|
|
||||||
/* if the function is not pure, it may reference memory. Add
|
/* Const functions do not reference memory. */
|
||||||
a VUSE for .GLOBAL_VAR if it has been created. See add_referenced_var
|
if (call_expr_flags (call) & ECF_CONST)
|
||||||
for the heuristic used to decide whether to create .GLOBAL_VAR. */
|
return;
|
||||||
|
|
||||||
|
not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
|
||||||
|
|
||||||
|
/* For pure functions we compute non-escaped uses separately. */
|
||||||
|
if (call_expr_flags (call) & ECF_PURE)
|
||||||
|
EXECUTE_IF_SET_IN_BITMAP (gimple_call_used_vars (cfun), 0, u, bi)
|
||||||
|
{
|
||||||
|
tree var = referenced_var_lookup (u);
|
||||||
|
tree real_var = var;
|
||||||
|
bool not_read;
|
||||||
|
|
||||||
|
if (unmodifiable_var_p (var))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
not_read = not_read_b
|
||||||
|
? bitmap_bit_p (not_read_b, DECL_UID (real_var))
|
||||||
|
: false;
|
||||||
|
|
||||||
|
clobber_stats.readonly_clobbers++;
|
||||||
|
|
||||||
|
/* See if this variable is really used by this function. */
|
||||||
|
if (!not_read)
|
||||||
|
add_virtual_operand (var, s_ann, opf_use, NULL, 0, -1, true);
|
||||||
|
else
|
||||||
|
clobber_stats.static_readonly_clobbers_avoided++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a VUSE for .GLOBAL_VAR if it has been created. See
|
||||||
|
add_referenced_var for the heuristic used to decide whether to
|
||||||
|
create .GLOBAL_VAR. */
|
||||||
if (gimple_global_var (cfun))
|
if (gimple_global_var (cfun))
|
||||||
{
|
{
|
||||||
tree var = gimple_global_var (cfun);
|
tree var = gimple_global_var (cfun);
|
||||||
add_virtual_operand (var, s_ann, opf_use, NULL, 0, -1, true);
|
add_virtual_operand (var, s_ann, opf_use, NULL, 0, -1, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
|
|
||||||
|
|
||||||
/* Add a VUSE for each call-clobbered variable. */
|
/* Add a VUSE for each call-clobbered variable. */
|
||||||
EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
|
EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
|
||||||
|
|
|
||||||
|
|
@ -296,7 +296,7 @@ get_varinfo_fc (unsigned int n)
|
||||||
|
|
||||||
/* Static IDs for the special variables. */
|
/* Static IDs for the special variables. */
|
||||||
enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
|
enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
|
||||||
escaped_id = 3, nonlocal_id = 4, integer_id = 5 };
|
escaped_id = 3, nonlocal_id = 4, callused_id = 5, integer_id = 6 };
|
||||||
|
|
||||||
/* Variable that represents the unknown pointer. */
|
/* Variable that represents the unknown pointer. */
|
||||||
static varinfo_t var_anything;
|
static varinfo_t var_anything;
|
||||||
|
|
@ -318,6 +318,10 @@ static tree escaped_tree;
|
||||||
static varinfo_t var_nonlocal;
|
static varinfo_t var_nonlocal;
|
||||||
static tree nonlocal_tree;
|
static tree nonlocal_tree;
|
||||||
|
|
||||||
|
/* Variable that represents call-used memory. */
|
||||||
|
static varinfo_t var_callused;
|
||||||
|
static tree callused_tree;
|
||||||
|
|
||||||
/* Variable that represents integers. This is used for when people do things
|
/* Variable that represents integers. This is used for when people do things
|
||||||
like &0->a.b. */
|
like &0->a.b. */
|
||||||
static varinfo_t var_integer;
|
static varinfo_t var_integer;
|
||||||
|
|
@ -1429,11 +1433,13 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
|
||||||
if (get_varinfo (t)->is_special_var)
|
if (get_varinfo (t)->is_special_var)
|
||||||
flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
|
flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
|
||||||
/* Merging the solution from ESCAPED needlessly increases
|
/* Merging the solution from ESCAPED needlessly increases
|
||||||
the set. Use ESCAPED as representative instead. */
|
the set. Use ESCAPED as representative instead.
|
||||||
else if (get_varinfo (t)->id == escaped_id
|
Same for CALLUSED. */
|
||||||
|
else if ((get_varinfo (t)->id == escaped_id
|
||||||
|
|| get_varinfo (t)->id == callused_id)
|
||||||
&& !bitmap_bit_p (sol, get_varinfo (t)->id))
|
&& !bitmap_bit_p (sol, get_varinfo (t)->id))
|
||||||
{
|
{
|
||||||
bitmap_set_bit (sol, escaped_id);
|
bitmap_set_bit (sol, get_varinfo (t)->id);
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
else if (add_graph_edge (graph, lhs, t))
|
else if (add_graph_edge (graph, lhs, t))
|
||||||
|
|
@ -2369,8 +2375,9 @@ solve_graph (constraint_graph_t graph)
|
||||||
solution_empty = bitmap_empty_p (solution);
|
solution_empty = bitmap_empty_p (solution);
|
||||||
|
|
||||||
if (!solution_empty
|
if (!solution_empty
|
||||||
/* Do not propagate the ESCAPED solution. */
|
/* Do not propagate the ESCAPED/CALLUSED solutions. */
|
||||||
&& i != escaped_id)
|
&& i != escaped_id
|
||||||
|
&& i != callused_id)
|
||||||
{
|
{
|
||||||
bitmap_iterator bi;
|
bitmap_iterator bi;
|
||||||
|
|
||||||
|
|
@ -3702,6 +3709,61 @@ handle_const_call (tree stmt)
|
||||||
VEC_free (ce_s, heap, lhsc);
|
VEC_free (ce_s, heap, lhsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For non-IPA mode, generate constraints necessary for a call to a
|
||||||
|
pure function in statement STMT. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_pure_call (tree stmt)
|
||||||
|
{
|
||||||
|
tree call = get_call_expr_in (stmt);
|
||||||
|
tree arg;
|
||||||
|
call_expr_arg_iterator iter;
|
||||||
|
|
||||||
|
/* Memory reached from pointer arguments is call-used. */
|
||||||
|
FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
|
||||||
|
if (could_have_pointers (arg))
|
||||||
|
make_constraint_to (callused_id, arg);
|
||||||
|
|
||||||
|
/* The static chain is used as well. */
|
||||||
|
if (CALL_EXPR_STATIC_CHAIN (call))
|
||||||
|
make_constraint_to (callused_id, CALL_EXPR_STATIC_CHAIN (call));
|
||||||
|
|
||||||
|
/* If the call returns a pointer it may point to reachable memory
|
||||||
|
from the arguments. */
|
||||||
|
if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
|
||||||
|
&& could_have_pointers (GIMPLE_STMT_OPERAND (stmt, 0)))
|
||||||
|
{
|
||||||
|
tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
|
||||||
|
VEC(ce_s, heap) *lhsc = NULL;
|
||||||
|
struct constraint_expr rhsc;
|
||||||
|
struct constraint_expr *lhsp;
|
||||||
|
unsigned j;
|
||||||
|
|
||||||
|
get_constraint_for (lhs, &lhsc);
|
||||||
|
|
||||||
|
/* If this is a nested function then it can return anything. */
|
||||||
|
if (CALL_EXPR_STATIC_CHAIN (call))
|
||||||
|
{
|
||||||
|
rhsc.var = anything_id;
|
||||||
|
rhsc.offset = 0;
|
||||||
|
rhsc.type = ADDRESSOF;
|
||||||
|
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
|
||||||
|
process_constraint_1 (new_constraint (*lhsp, rhsc), true);
|
||||||
|
VEC_free (ce_s, heap, lhsc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Else just add the call-used memory here. Escaped variables
|
||||||
|
and globals will be dealt with in handle_lhs_call. */
|
||||||
|
rhsc.var = callused_id;
|
||||||
|
rhsc.offset = 0;
|
||||||
|
rhsc.type = ADDRESSOF;
|
||||||
|
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
|
||||||
|
process_constraint_1 (new_constraint (*lhsp, rhsc), true);
|
||||||
|
VEC_free (ce_s, heap, lhsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Walk statement T setting up aliasing constraints according to the
|
/* Walk statement T setting up aliasing constraints according to the
|
||||||
references found in T. This function is the main part of the
|
references found in T. This function is the main part of the
|
||||||
constraint builder. AI points to auxiliary alias information used
|
constraint builder. AI points to auxiliary alias information used
|
||||||
|
|
@ -3778,6 +3840,13 @@ find_func_aliases (tree origt)
|
||||||
&& could_have_pointers (GIMPLE_STMT_OPERAND (t, 1)))
|
&& could_have_pointers (GIMPLE_STMT_OPERAND (t, 1)))
|
||||||
handle_const_call (t);
|
handle_const_call (t);
|
||||||
}
|
}
|
||||||
|
else if (flags & ECF_PURE)
|
||||||
|
{
|
||||||
|
handle_pure_call (t);
|
||||||
|
if (TREE_CODE (t) == GIMPLE_MODIFY_STMT
|
||||||
|
&& could_have_pointers (GIMPLE_STMT_OPERAND (t, 1)))
|
||||||
|
handle_lhs_call (GIMPLE_STMT_OPERAND (t, 0));
|
||||||
|
}
|
||||||
/* Pure functions can return addresses in and of memory
|
/* Pure functions can return addresses in and of memory
|
||||||
reachable from their arguments, but they are not an escape
|
reachable from their arguments, but they are not an escape
|
||||||
point for reachable memory of their arguments. But as we
|
point for reachable memory of their arguments. But as we
|
||||||
|
|
@ -4940,7 +5009,8 @@ find_what_p_points_to (tree p)
|
||||||
pi->pt_null = 1;
|
pi->pt_null = 1;
|
||||||
else if (vi->id == anything_id
|
else if (vi->id == anything_id
|
||||||
|| vi->id == nonlocal_id
|
|| vi->id == nonlocal_id
|
||||||
|| vi->id == escaped_id)
|
|| vi->id == escaped_id
|
||||||
|
|| vi->id == callused_id)
|
||||||
was_pt_anything = 1;
|
was_pt_anything = 1;
|
||||||
else if (vi->id == readonly_id)
|
else if (vi->id == readonly_id)
|
||||||
was_pt_anything = 1;
|
was_pt_anything = 1;
|
||||||
|
|
@ -5007,6 +5077,15 @@ clobber_what_escaped (void)
|
||||||
variable for escaped_id. */
|
variable for escaped_id. */
|
||||||
vi = get_varinfo (find (escaped_id));
|
vi = get_varinfo (find (escaped_id));
|
||||||
|
|
||||||
|
/* If call-used memory escapes we need to include it in the
|
||||||
|
set of escaped variables. This can happen if a pure
|
||||||
|
function returns a pointer and this pointer escapes. */
|
||||||
|
if (bitmap_bit_p (vi->solution, callused_id))
|
||||||
|
{
|
||||||
|
varinfo_t cu_vi = get_varinfo (find (callused_id));
|
||||||
|
bitmap_ior_into (vi->solution, cu_vi->solution);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark variables in the solution call-clobbered. */
|
/* Mark variables in the solution call-clobbered. */
|
||||||
EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
|
EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
|
||||||
{
|
{
|
||||||
|
|
@ -5036,6 +5115,54 @@ clobber_what_escaped (void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute the call-used variables. */
|
||||||
|
|
||||||
|
void
|
||||||
|
compute_call_used_vars (void)
|
||||||
|
{
|
||||||
|
varinfo_t vi;
|
||||||
|
unsigned int i;
|
||||||
|
bitmap_iterator bi;
|
||||||
|
bool has_anything_id = false;
|
||||||
|
|
||||||
|
if (!have_alias_info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* This variable may have been collapsed, let's get the real
|
||||||
|
variable for escaped_id. */
|
||||||
|
vi = get_varinfo (find (callused_id));
|
||||||
|
|
||||||
|
/* Mark variables in the solution call-clobbered. */
|
||||||
|
EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
|
||||||
|
{
|
||||||
|
varinfo_t vi = get_varinfo (i);
|
||||||
|
|
||||||
|
if (vi->is_artificial_var)
|
||||||
|
{
|
||||||
|
/* For anything_id and integer_id we need to make
|
||||||
|
all local addressable vars call-used. */
|
||||||
|
if (vi->id == anything_id
|
||||||
|
|| vi->id == integer_id)
|
||||||
|
has_anything_id = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only artificial heap-vars are further interesting. */
|
||||||
|
if (vi->is_artificial_var && !vi->is_heap_var)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((TREE_CODE (vi->decl) == VAR_DECL
|
||||||
|
|| TREE_CODE (vi->decl) == PARM_DECL
|
||||||
|
|| TREE_CODE (vi->decl) == RESULT_DECL)
|
||||||
|
&& !unmodifiable_var_p (vi->decl))
|
||||||
|
bitmap_set_bit (gimple_call_used_vars (cfun), DECL_UID (vi->decl));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If anything is call-used, add all addressable locals to the set. */
|
||||||
|
if (has_anything_id)
|
||||||
|
bitmap_ior_into (gimple_call_used_vars (cfun),
|
||||||
|
gimple_addressable_vars (cfun));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Dump points-to information to OUTFILE. */
|
/* Dump points-to information to OUTFILE. */
|
||||||
|
|
||||||
|
|
@ -5193,6 +5320,27 @@ init_base_vars (void)
|
||||||
rhs.offset = 0;
|
rhs.offset = 0;
|
||||||
process_constraint (new_constraint (lhs, rhs));
|
process_constraint (new_constraint (lhs, rhs));
|
||||||
|
|
||||||
|
/* Create the CALLUSED variable, used to represent the set of call-used
|
||||||
|
memory. */
|
||||||
|
callused_tree = create_tmp_var_raw (void_type_node, "CALLUSED");
|
||||||
|
var_callused = new_var_info (callused_tree, callused_id, "CALLUSED");
|
||||||
|
insert_vi_for_tree (callused_tree, var_callused);
|
||||||
|
var_callused->is_artificial_var = 1;
|
||||||
|
var_callused->offset = 0;
|
||||||
|
var_callused->size = ~0;
|
||||||
|
var_callused->fullsize = ~0;
|
||||||
|
var_callused->is_special_var = 0;
|
||||||
|
VEC_safe_push (varinfo_t, heap, varmap, var_callused);
|
||||||
|
|
||||||
|
/* CALLUSED = *CALLUSED, because call-used is may-deref'd at calls, etc. */
|
||||||
|
lhs.type = SCALAR;
|
||||||
|
lhs.var = callused_id;
|
||||||
|
lhs.offset = 0;
|
||||||
|
rhs.type = DEREF;
|
||||||
|
rhs.var = callused_id;
|
||||||
|
rhs.offset = 0;
|
||||||
|
process_constraint_1 (new_constraint (lhs, rhs), true);
|
||||||
|
|
||||||
/* Create the INTEGER variable, used to represent that a variable points
|
/* Create the INTEGER variable, used to represent that a variable points
|
||||||
to an INTEGER. */
|
to an INTEGER. */
|
||||||
integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
|
integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
|
||||||
|
|
|
||||||
|
|
@ -937,6 +937,7 @@ init_tree_ssa (struct function *fn)
|
||||||
fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
|
fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
|
||||||
uid_ssaname_map_eq, NULL);
|
uid_ssaname_map_eq, NULL);
|
||||||
fn->gimple_df->call_clobbered_vars = BITMAP_GGC_ALLOC ();
|
fn->gimple_df->call_clobbered_vars = BITMAP_GGC_ALLOC ();
|
||||||
|
fn->gimple_df->call_used_vars = BITMAP_GGC_ALLOC ();
|
||||||
fn->gimple_df->addressable_vars = BITMAP_GGC_ALLOC ();
|
fn->gimple_df->addressable_vars = BITMAP_GGC_ALLOC ();
|
||||||
init_ssanames (fn, 0);
|
init_ssanames (fn, 0);
|
||||||
init_phinodes ();
|
init_phinodes ();
|
||||||
|
|
@ -1009,6 +1010,7 @@ delete_tree_ssa (void)
|
||||||
htab_delete (cfun->gimple_df->default_defs);
|
htab_delete (cfun->gimple_df->default_defs);
|
||||||
cfun->gimple_df->default_defs = NULL;
|
cfun->gimple_df->default_defs = NULL;
|
||||||
cfun->gimple_df->call_clobbered_vars = NULL;
|
cfun->gimple_df->call_clobbered_vars = NULL;
|
||||||
|
cfun->gimple_df->call_used_vars = NULL;
|
||||||
cfun->gimple_df->addressable_vars = NULL;
|
cfun->gimple_df->addressable_vars = NULL;
|
||||||
cfun->gimple_df->modified_noreturn_calls = NULL;
|
cfun->gimple_df->modified_noreturn_calls = NULL;
|
||||||
if (gimple_aliases_computed_p (cfun))
|
if (gimple_aliases_computed_p (cfun))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue