re PR tree-optimization/43572 (FAIL: gfortran.dg/PR19872.f execution test; formatted read - wrong numbers)

2010-04-16  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/43572
	* tree-ssa-alias.h (call_may_clobber_ref_p): Declare.
	* tree-ssa-alias.c (call_may_clobber_ref_p): Export.
	* tree-flow.h (is_call_clobbered): Remove.
	* tree-flow-inline.h (is_call_clobbered): Likewise.
	* tree-dfa.c (dump_variable): Do not dump call clobber state.
	* tree-nrv.c (dest_safe_for_nrv_p): Use the alias oracle.
	(execute_return_slot_opt): Adjust.
	* tree-tailcall.c (suitable_for_tail_opt_p): Remove
	check for call clobbered vars here.
	(find_tail_calls): Move tailcall verification to the
	proper place.

	* gcc.dg/tree-ssa/tailcall-5.c: New testcase.

From-SVN: r158418
This commit is contained in:
Richard Guenther 2010-04-16 13:21:38 +00:00 committed by Richard Biener
parent 6ab643b5a4
commit 12de635528
10 changed files with 57 additions and 58 deletions

View File

@ -1,3 +1,18 @@
2010-04-16 Richard Guenther <rguenther@suse.de>
PR tree-optimization/43572
* tree-ssa-alias.h (call_may_clobber_ref_p): Declare.
* tree-ssa-alias.c (call_may_clobber_ref_p): Export.
* tree-flow.h (is_call_clobbered): Remove.
* tree-flow-inline.h (is_call_clobbered): Likewise.
* tree-dfa.c (dump_variable): Do not dump call clobber state.
* tree-nrv.c (dest_safe_for_nrv_p): Use the alias oracle.
(execute_return_slot_opt): Adjust.
* tree-tailcall.c (suitable_for_tail_opt_p): Remove
check for call clobbered vars here.
(find_tail_calls): Move tailcall verification to the
proper place.
2010-04-16 Diego Novillo <dnovillo@google.com> 2010-04-16 Diego Novillo <dnovillo@google.com>
* doc/invoke.texi: Explain how are unrecognized -Wno- warnings * doc/invoke.texi: Explain how are unrecognized -Wno- warnings

View File

@ -1,3 +1,8 @@
2010-04-16 Richard Guenther <rguenther@suse.de>
PR tree-optimization/43572
* gcc.dg/tree-ssa/tailcall-5.c: New testcase.
2010-04-16 Olivier Hainque <hainque@adacore.com> 2010-04-16 Olivier Hainque <hainque@adacore.com>
* gnat.dg/specs/discr_private.ads: New test. * gnat.dg/specs/discr_private.ads: New test.

View File

@ -0,0 +1,12 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-tailc" } */
void
set_integer (void *dest, int value, int length)
{
int tmp = value;
__builtin_memcpy (dest, (void *) &tmp, length);
}
/* { dg-final { scan-tree-dump-not "tail call" "tailc" } } */
/* { dg-final { cleanup-tree-dump "tailc" } } */

View File

@ -284,9 +284,6 @@ dump_variable (FILE *file, tree var)
if (TREE_THIS_VOLATILE (var)) if (TREE_THIS_VOLATILE (var))
fprintf (file, ", is volatile"); fprintf (file, ", is volatile");
if (is_call_clobbered (var))
fprintf (file, ", call clobbered");
if (ann && ann->noalias_state == NO_ALIAS) if (ann && ann->noalias_state == NO_ALIAS)
fprintf (file, ", NO_ALIAS (does not alias other NO_ALIAS symbols)"); fprintf (file, ", NO_ALIAS (does not alias other NO_ALIAS symbols)");
else if (ann && ann->noalias_state == NO_ALIAS_GLOBAL) else if (ann && ann->noalias_state == NO_ALIAS_GLOBAL)

View File

@ -624,15 +624,6 @@ loop_containing_stmt (gimple stmt)
} }
/* Return true if VAR is clobbered by function calls. */
static inline bool
is_call_clobbered (const_tree var)
{
return (is_global_var (var)
|| (may_be_aliased (var)
&& pt_solution_includes (&cfun->gimple_df->escaped, var)));
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* The following set of routines are used to iterator over various type of /* The following set of routines are used to iterator over various type of

View File

@ -774,7 +774,6 @@ extern enum move_pos movement_possibility (gimple);
char *get_lsm_tmp_name (tree, unsigned); char *get_lsm_tmp_name (tree, unsigned);
/* In tree-flow-inline.h */ /* In tree-flow-inline.h */
static inline bool is_call_clobbered (const_tree);
static inline void set_is_used (tree); static inline void set_is_used (tree);
static inline bool unmodifiable_var_p (const_tree); static inline bool unmodifiable_var_p (const_tree);
static inline bool ref_contains_array_ref (const_tree); static inline bool ref_contains_array_ref (const_tree);

View File

@ -291,23 +291,21 @@ struct gimple_opt_pass pass_nrv =
optimization, where DEST is expected to be the LHS of a modify optimization, where DEST is expected to be the LHS of a modify
expression where the RHS is a function returning an aggregate. expression where the RHS is a function returning an aggregate.
We search for a base VAR_DECL and look to see if it is call clobbered. DEST is available if it is not clobbered by the call. */
Note that we could do better, for example, by
attempting to doing points-to analysis on INDIRECT_REFs. */
static bool static bool
dest_safe_for_nrv_p (tree dest) dest_safe_for_nrv_p (gimple call)
{ {
while (handled_component_p (dest)) tree dest = gimple_call_lhs (call);
dest = TREE_OPERAND (dest, 0);
if (! SSA_VAR_P (dest)) dest = get_base_address (dest);
if (! dest)
return false; return false;
if (TREE_CODE (dest) == SSA_NAME) if (TREE_CODE (dest) == SSA_NAME)
dest = SSA_NAME_VAR (dest); return true;
if (is_call_clobbered (dest)) if (call_may_clobber_ref_p (call, dest))
return false; return false;
return true; return true;
@ -346,8 +344,8 @@ execute_return_slot_opt (void)
) )
{ {
/* Check if the location being assigned to is /* Check if the location being assigned to is
call-clobbered. */ clobbered by the call. */
slot_opt_p = dest_safe_for_nrv_p (gimple_call_lhs (stmt)); slot_opt_p = dest_safe_for_nrv_p (stmt);
gimple_call_set_return_slot_opt (stmt, slot_opt_p); gimple_call_set_return_slot_opt (stmt, slot_opt_p);
} }
} }

View File

@ -1339,7 +1339,10 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
return true; return true;
} }
static bool ATTRIBUTE_UNUSED /* If the call in statement CALL may clobber the memory reference REF
return true, otherwise return false. */
bool
call_may_clobber_ref_p (gimple call, tree ref) call_may_clobber_ref_p (gimple call, tree ref)
{ {
bool res; bool res;

View File

@ -104,6 +104,7 @@ extern bool refs_output_dependent_p (tree, tree);
extern bool ref_maybe_used_by_stmt_p (gimple, tree); extern bool ref_maybe_used_by_stmt_p (gimple, tree);
extern bool stmt_may_clobber_ref_p (gimple, tree); extern bool stmt_may_clobber_ref_p (gimple, tree);
extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *); extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
extern bool call_may_clobber_ref_p (gimple, tree);
extern tree get_continuation_for_phi (gimple, ao_ref *, bitmap *); extern tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
extern void *walk_non_aliased_vuses (ao_ref *, tree, extern void *walk_non_aliased_vuses (ao_ref *, tree,
void *(*)(ao_ref *, tree, void *), void *(*)(ao_ref *, tree, void *),

View File

@ -130,32 +130,9 @@ static void find_tail_calls (basic_block, struct tailcall **);
static bool static bool
suitable_for_tail_opt_p (void) suitable_for_tail_opt_p (void)
{ {
referenced_var_iterator rvi;
tree var;
if (cfun->stdarg) if (cfun->stdarg)
return false; return false;
/* No local variable nor structure field should escape to callees. */
FOR_EACH_REFERENCED_VAR (var, rvi)
{
if (!is_global_var (var)
/* ??? We do not have a suitable predicate for escaping to
callees. With IPA-PTA the following might be incorrect.
We want to catch
foo {
int i;
bar (&i);
foo ();
}
where bar might store &i somewhere and in the next
recursion should not be able to tell if it got the
same (with tail-recursion applied) or a different
address. */
&& is_call_clobbered (var))
return false;
}
return true; return true;
} }
/* Returns false when the function is not suitable for tail call optimization /* Returns false when the function is not suitable for tail call optimization
@ -387,6 +364,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
tree m, a; tree m, a;
basic_block abb; basic_block abb;
size_t idx; size_t idx;
tree var;
referenced_var_iterator rvi;
if (!single_succ_p (bb)) if (!single_succ_p (bb))
return; return;
@ -442,8 +421,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
func = gimple_call_fndecl (call); func = gimple_call_fndecl (call);
if (func == current_function_decl) if (func == current_function_decl)
{ {
tree arg, var; tree arg;
referenced_var_iterator rvi;
for (param = DECL_ARGUMENTS (func), idx = 0; for (param = DECL_ARGUMENTS (func), idx = 0;
param && idx < gimple_call_num_args (call); param && idx < gimple_call_num_args (call);
@ -474,15 +452,15 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
} }
if (idx == gimple_call_num_args (call) && !param) if (idx == gimple_call_num_args (call) && !param)
tail_recursion = true; tail_recursion = true;
}
/* Make sure the tail invocation of this function does not refer /* Make sure the tail invocation of this function does not refer
to local variables. */ to local variables. */
FOR_EACH_REFERENCED_VAR (var, rvi) FOR_EACH_REFERENCED_VAR (var, rvi)
{ {
if (!is_global_var (var) if (!is_global_var (var)
&& ref_maybe_used_by_stmt_p (call, var)) && ref_maybe_used_by_stmt_p (call, var))
return; return;
}
} }
/* Now check the statements after the call. None of them has virtual /* Now check the statements after the call. None of them has virtual