Index: cgraph.h
===================================================================
--- cgraph.h	(revision 202315)
+++ cgraph.h	(working copy)
@@ -627,6 +627,7 @@ bool symtab_for_node_and_aliases (symtab
 				  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: tree-tailcall.c
===================================================================
--- tree-tailcall.c	(revision 202315)
+++ tree-tailcall.c	(working copy)
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.
 #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
   /* 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;
 
Index: ipa-pure-const.c
===================================================================
--- ipa-pure-const.c	(revision 202315)
+++ ipa-pure-const.c	(working copy)
@@ -541,7 +541,8 @@ check_call (funct_state local, gimple ca
     }
 
   /* 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: ipa-utils.c
===================================================================
--- ipa-utils.c	(revision 202315)
+++ ipa-utils.c	(working copy)
@@ -791,3 +791,14 @@ ipa_merge_profiles (struct cgraph_node *
   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: ipa-utils.h
===================================================================
--- ipa-utils.h	(revision 202315)
+++ ipa-utils.h	(working copy)
@@ -46,6 +46,7 @@ int ipa_reverse_postorder (struct cgraph
 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: symtab.c
===================================================================
--- symtab.c	(revision 202315)
+++ symtab.c	(working copy)
@@ -1106,11 +1106,48 @@ symtab_nonoverwritable_alias (symtab_nod
     {
       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: Makefile.in
===================================================================
--- Makefile.in	(revision 202315)
+++ Makefile.in	(working copy)
@@ -2432,7 +2432,7 @@ tree-tailcall.o : tree-tailcall.c $(TREE
    $(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 \
