Commit fc11f321 by Jan Hubicka Committed by Jan Hubicka

re PR middle-end/58094 (IPA devirt testsuite errors)

	PR middle-end/58094
	* cgraph.h (symtab_semantically_equivalent_p): Declare.
	* tree-tailcall.c: Include ipa-utils.h.
	(find_tail_calls): Use it.
	* ipa-pure-const.c (check_call): Likewise.
	* ipa-utils.c (recursive_call_p): New function.
	* ipa-utils.h (recursive_call_p): Dclare.
	* symtab.c (symtab_nonoverwritable_alias): Fix formatting.
	(symtab_semantically_equivalent_p): New function.
	* Makefile.in (tree-tailcall.o): Update dependencies.

From-SVN: r202316
parent 9a6af450
2013-09-06 Jan Hubicka <jh@suse.cz>
PR middle-end/58094
* cgraph.h (symtab_semantically_equivalent_p): Declare.
* tree-tailcall.c: Include ipa-utils.h.
(find_tail_calls): Use it.
* ipa-pure-const.c (check_call): Likewise.
* ipa-utils.c (recursive_call_p): New function.
* ipa-utils.h (recursive_call_p): Dclare.
* symtab.c (symtab_nonoverwritable_alias): Fix formatting.
(symtab_semantically_equivalent_p): New function.
* Makefile.in (tree-tailcall.o): Update dependencies.
2013-09-06 Eric Botcazou <ebotcazou@adacore.com> 2013-09-06 Eric Botcazou <ebotcazou@adacore.com>
* ipa-split.c (split_function): Set DECL_NO_INLINE_WARNING_P on the * ipa-split.c (split_function): Set DECL_NO_INLINE_WARNING_P on the
......
...@@ -2432,7 +2432,7 @@ tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ ...@@ -2432,7 +2432,7 @@ tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(TM_P_H) $(FUNCTION_H) $(TM_H) coretypes.h \ $(TREE_H) $(TM_P_H) $(FUNCTION_H) $(TM_H) coretypes.h \
$(EXCEPT_H) $(TREE_PASS_H) $(FLAGS_H) langhooks.h \ $(EXCEPT_H) $(TREE_PASS_H) $(FLAGS_H) langhooks.h \
$(BASIC_BLOCK_H) $(DBGCNT_H) $(GIMPLE_PRETTY_PRINT_H) $(TARGET_H) \ $(BASIC_BLOCK_H) $(DBGCNT_H) $(GIMPLE_PRETTY_PRINT_H) $(TARGET_H) \
$(COMMON_TARGET_H) $(CFGLOOP_H) $(COMMON_TARGET_H) $(CFGLOOP_H) ipa-utils.h
tree-ssa-sink.o : tree-ssa-sink.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-sink.o : tree-ssa-sink.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \ $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
$(TM_H) coretypes.h $(TREE_PASS_H) $(FLAGS_H) alloc-pool.h \ $(TM_H) coretypes.h $(TREE_PASS_H) $(FLAGS_H) alloc-pool.h \
......
...@@ -627,6 +627,7 @@ bool symtab_for_node_and_aliases (symtab_node, ...@@ -627,6 +627,7 @@ bool symtab_for_node_and_aliases (symtab_node,
bool); bool);
symtab_node symtab_nonoverwritable_alias (symtab_node); symtab_node symtab_nonoverwritable_alias (symtab_node);
enum availability symtab_node_availability (symtab_node); enum availability symtab_node_availability (symtab_node);
bool symtab_semantically_equivalent_p (symtab_node, symtab_node);
/* In cgraph.c */ /* In cgraph.c */
void dump_cgraph (FILE *); void dump_cgraph (FILE *);
......
...@@ -541,7 +541,8 @@ check_call (funct_state local, gimple call, bool ipa) ...@@ -541,7 +541,8 @@ check_call (funct_state local, gimple call, bool ipa)
} }
/* When not in IPA mode, we can still handle self recursion. */ /* When not in IPA mode, we can still handle self recursion. */
if (!ipa && callee_t == current_function_decl) if (!ipa && callee_t
&& recursive_call_p (current_function_decl, callee_t))
{ {
if (dump_file) if (dump_file)
fprintf (dump_file, " Recursive call can loop.\n"); fprintf (dump_file, " Recursive call can loop.\n");
...@@ -1079,8 +1080,9 @@ ignore_edge (struct cgraph_edge *e) ...@@ -1079,8 +1080,9 @@ ignore_edge (struct cgraph_edge *e)
} }
/* Return true if NODE is self recursive function. /* Return true if NODE is self recursive function.
??? self recursive and indirectly recursive funcions should Indirectly recursive functions appears as non-trivial strongly
be the same, so this function seems unnecessary. */ connected components, so we need to care about self recursion
only. */
static bool static bool
self_recursive_p (struct cgraph_node *node) self_recursive_p (struct cgraph_node *node)
......
...@@ -791,3 +791,14 @@ ipa_merge_profiles (struct cgraph_node *dst, ...@@ -791,3 +791,14 @@ ipa_merge_profiles (struct cgraph_node *dst,
src->symbol.decl = oldsrcdecl; src->symbol.decl = oldsrcdecl;
} }
/* Return true if call to DEST is known to be self-recusive call withing FUNC. */
bool
recursive_call_p (tree func, tree dest)
{
struct cgraph_node *dest_node = cgraph_get_create_node (dest);
struct cgraph_node *cnode = cgraph_get_create_node (func);
return symtab_semantically_equivalent_p ((symtab_node)dest_node,
(symtab_node)cnode);
}
...@@ -46,6 +46,7 @@ int ipa_reverse_postorder (struct cgraph_node **); ...@@ -46,6 +46,7 @@ int ipa_reverse_postorder (struct cgraph_node **);
tree get_base_var (tree); tree get_base_var (tree);
void ipa_merge_profiles (struct cgraph_node *dst, void ipa_merge_profiles (struct cgraph_node *dst,
struct cgraph_node *src); struct cgraph_node *src);
bool recursive_call_p (tree, tree);
/* In ipa-profile.c */ /* In ipa-profile.c */
bool ipa_propagate_frequency (struct cgraph_node *node); bool ipa_propagate_frequency (struct cgraph_node *node);
......
...@@ -1106,11 +1106,48 @@ symtab_nonoverwritable_alias (symtab_node node) ...@@ -1106,11 +1106,48 @@ symtab_nonoverwritable_alias (symtab_node node)
{ {
DECL_STATIC_CONSTRUCTOR (new_decl) = 0; DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
DECL_STATIC_DESTRUCTOR (new_decl) = 0; DECL_STATIC_DESTRUCTOR (new_decl) = 0;
new_node = (symtab_node) cgraph_create_function_alias (new_decl, node->symbol.decl); new_node = (symtab_node) cgraph_create_function_alias
(new_decl, node->symbol.decl);
} }
else else
new_node = (symtab_node) varpool_create_variable_alias (new_decl, node->symbol.decl); new_node = (symtab_node) varpool_create_variable_alias (new_decl,
node->symbol.decl);
symtab_resolve_alias (new_node, node); symtab_resolve_alias (new_node, node);
gcc_assert (decl_binds_to_current_def_p (new_decl));
return new_node; return new_node;
} }
/* Return true if A and B represents semantically equivalent symbols. */
bool
symtab_semantically_equivalent_p (symtab_node a,
symtab_node b)
{
enum availability avail;
symtab_node ba, bb;
/* Equivalent functions are equivalent. */
if (a->symbol.decl == b->symbol.decl)
return true;
/* If symbol is not overwritable by different implementation,
walk to the base object it defines. */
ba = symtab_alias_ultimate_target (a, &avail);
if (avail >= AVAIL_AVAILABLE)
{
if (ba == b)
return true;
}
else
ba = a;
bb = symtab_alias_ultimate_target (b, &avail);
if (avail >= AVAIL_AVAILABLE)
{
if (a == bb)
return true;
}
else
bb = b;
return bb == ba;
}
#include "gt-symtab.h" #include "gt-symtab.h"
...@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h" #include "target.h"
#include "cfgloop.h" #include "cfgloop.h"
#include "common/common-target.h" #include "common/common-target.h"
#include "ipa-utils.h"
/* The file implements the tail recursion elimination. It is also used to /* The file implements the tail recursion elimination. It is also used to
analyze the tail calls in general, passing the results to the rtl level analyze the tail calls in general, passing the results to the rtl level
...@@ -445,7 +446,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret) ...@@ -445,7 +446,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
/* We found the call, check whether it is suitable. */ /* We found the call, check whether it is suitable. */
tail_recursion = false; tail_recursion = false;
func = gimple_call_fndecl (call); func = gimple_call_fndecl (call);
if (func == current_function_decl) if (func && recursive_call_p (current_function_decl, func))
{ {
tree arg; tree arg;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment