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
This commit is contained in:
parent
9a6af4504b
commit
fc11f321bb
@ -1,3 +1,16 @@
|
||||
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>
|
||||
|
||||
* 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) \
|
||||
$(TREE_H) $(TM_P_H) $(FUNCTION_H) $(TM_H) coretypes.h \
|
||||
$(EXCEPT_H) $(TREE_PASS_H) $(FLAGS_H) langhooks.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) \
|
||||
$(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_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,
|
||||
bool);
|
||||
symtab_node symtab_nonoverwritable_alias (symtab_node);
|
||||
enum availability symtab_node_availability (symtab_node);
|
||||
bool symtab_semantically_equivalent_p (symtab_node, symtab_node);
|
||||
|
||||
/* In cgraph.c */
|
||||
void dump_cgraph (FILE *);
|
||||
|
@ -541,7 +541,8 @@ check_call (funct_state local, gimple call, bool ipa)
|
||||
}
|
||||
|
||||
/* 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)
|
||||
fprintf (dump_file, " Recursive call can loop.\n");
|
||||
@ -1079,8 +1080,9 @@ ignore_edge (struct cgraph_edge *e)
|
||||
}
|
||||
|
||||
/* Return true if NODE is self recursive function.
|
||||
??? self recursive and indirectly recursive funcions should
|
||||
be the same, so this function seems unnecessary. */
|
||||
Indirectly recursive functions appears as non-trivial strongly
|
||||
connected components, so we need to care about self recursion
|
||||
only. */
|
||||
|
||||
static bool
|
||||
self_recursive_p (struct cgraph_node *node)
|
||||
|
@ -791,3 +791,14 @@ ipa_merge_profiles (struct cgraph_node *dst,
|
||||
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 **);
|
||||
tree get_base_var (tree);
|
||||
void ipa_merge_profiles (struct cgraph_node *dst,
|
||||
struct cgraph_node *src);
|
||||
bool recursive_call_p (tree, tree);
|
||||
|
||||
/* In ipa-profile.c */
|
||||
bool ipa_propagate_frequency (struct cgraph_node *node);
|
||||
|
41
gcc/symtab.c
41
gcc/symtab.c
@ -1106,11 +1106,48 @@ symtab_nonoverwritable_alias (symtab_node node)
|
||||
{
|
||||
DECL_STATIC_CONSTRUCTOR (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
|
||||
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);
|
||||
gcc_assert (decl_binds_to_current_def_p (new_decl));
|
||||
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"
|
||||
|
@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "target.h"
|
||||
#include "cfgloop.h"
|
||||
#include "common/common-target.h"
|
||||
#include "ipa-utils.h"
|
||||
|
||||
/* 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
|
||||
@ -445,7 +446,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
|
||||
/* We found the call, check whether it is suitable. */
|
||||
tail_recursion = false;
|
||||
func = gimple_call_fndecl (call);
|
||||
if (func == current_function_decl)
|
||||
if (func && recursive_call_p (current_function_decl, func))
|
||||
{
|
||||
tree arg;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user