diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e1822130709511f521efa926287dd0cc09df29c0..0dc55b7a366b640da42558b862b0bf1837550b52 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -25,6 +25,9 @@
 	(TARGET_SWITCHES): Add -mleaf-id-shared-library and -msep-data.
 	* doc/invoke.texi (Blackfin Options): Document new switches.
 
+	* config/bfin/bfin.c (bfin_function_ok_for_sibcall): Handle some
+	edge cases with local functions and TARGET_ID_SHARED_LIBRARY.
+
 2006-11-19  Andrew Pinski  <pinskia@gmail.com>
 
 	PR rtl-opt/29879
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 6238690d9c2b34f58aea5fed467fa9f4c7b4ae16..b71b12374a16d3bed0fb1999320721a094efd5d6 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -1596,7 +1596,28 @@ bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
 			      tree exp ATTRIBUTE_UNUSED)
 {
   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
-  return fkind == SUBROUTINE;
+  if (fkind != SUBROUTINE)
+    return false;
+  if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
+    return true;
+
+  /* When compiling for ID shared libraries, can't sibcall a local function
+     from a non-local function, because the local function thinks it does
+     not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
+     sibcall epilogue, and we end up with the wrong value in P5.  */
+
+  if (!flag_unit_at_a_time || decl == NULL)
+    /* Not enough information.  */
+    return false;
+
+  {
+    struct cgraph_local_info *this_func, *called_func;
+    rtx addr, insn;
+ 
+    this_func = cgraph_local_info (current_function_decl);
+    called_func = cgraph_local_info (decl);
+    return !called_func->local || this_func->local;
+  }
 }
 
 /* Emit RTL insns to initialize the variable parts of a trampoline at