PR middle-end/58094
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 Sep 2013 10:13:37 +0000 (10:13 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 Sep 2013 10:13:37 +0000 (10:13 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202316 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/cgraph.h
gcc/ipa-pure-const.c
gcc/ipa-utils.c
gcc/ipa-utils.h
gcc/symtab.c
gcc/tree-tailcall.c

index e5b74ed..a2a6822 100644 (file)
@@ -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
index 4fdf5cb..8430300 100644 (file)
@@ -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 \
index ea8a04d..5a7a949 100644 (file)
@@ -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 *);
index 7a29365..ed4deae 100644 (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)
index 0ea02ea..e2e1690 100644 (file)
@@ -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);
+}
index 5619b5d..d6f390d 100644 (file)
@@ -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);
index 253ba98..8dc61d0 100644 (file)
@@ -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"
index 9694046..289b75a 100644 (file)
@@ -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;