Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 264698)
+++ gcc/target.def	(working copy)
@@ -3123,6 +3123,20 @@ In order to enforce the representation o
  int, (scalar_int_mode mode, scalar_int_mode rep_mode),
  default_mode_rep_extended)
 
+ DEFHOOK
+(is_reg_clobbering_setjmp_p,
+ "On some targets, it is assumed that the compiler will spill all registers\n\
+  that are live across a call to @code{setjmp}, while other targets treat\n\
+  @code{setjmp} calls as normal function calls.\n\
+  \n\
+  This hook returns true if @var{insn} is a @code{setjmp} call that must\n\
+  have all registers that are live across it spilled.  Define this to return\n\
+  false if the target does not need to spill all registers across calls to\n\
+  @code{setjmp} calls.  The default implementation conservatively assumes all\n\
+  registers must be spilled across @code{setjmp} calls.",
+bool, (const rtx_insn *insn),
+default_is_reg_clobbering_setjmp_p)
+
 /* True if MODE is valid for a pointer in __attribute__((mode("MODE"))).  */
 DEFHOOK
 (valid_pointer_mode,
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 264698)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -7507,6 +7507,8 @@ You need not define this macro if it wou
 
 @hook TARGET_MODE_REP_EXTENDED
 
+@hook TARGET_IS_REG_CLOBBERING_SETJMP_P
+
 @defmac STORE_FLAG_VALUE
 A C expression describing the value returned by a comparison operator
 with an integral mode and stored by a store-flag instruction
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 264698)
+++ gcc/doc/tm.texi	(working copy)
@@ -11000,6 +11000,18 @@ In order to enforce the representation o
 @code{mode}.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_IS_REG_CLOBBERING_SETJMP_P (const rtx_insn *@var{insn})
+On some targets, it is assumed that the compiler will spill all registers
+  that are live across a call to @code{setjmp}, while other targets treat
+  @code{setjmp} calls as normal function calls.
+  
+  This hook returns true if @var{insn} is a @code{setjmp} call that must
+  have all registers that are live across it spilled.  Define this to return
+  false if the target does not need to spill all registers across calls to
+  @code{setjmp} calls.  The default implementation conservatively assumes all
+  registers must be spilled across @code{setjmp} calls.
+@end deftypefn
+
 @defmac STORE_FLAG_VALUE
 A C expression describing the value returned by a comparison operator
 with an integral mode and stored by a store-flag instruction
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(revision 264698)
+++ gcc/targhooks.c	(working copy)
@@ -209,6 +209,15 @@ default_builtin_setjmp_frame_value (void
   return virtual_stack_vars_rtx;
 }
 
+/* The default implementation of TARGET_IS_REG_CLOBBERING_SETJMP_P.  */
+
+bool
+default_is_reg_clobbering_setjmp_p (const rtx_insn *insn)
+{
+  return CALL_P (insn)
+	 && find_reg_note (insn, REG_SETJMP, NULL_RTX) != NULL_RTX;
+}
+
 /* Generic hook that takes a CUMULATIVE_ARGS pointer and returns false.  */
 
 bool
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	(revision 264698)
+++ gcc/targhooks.h	(working copy)
@@ -42,6 +42,7 @@ extern bool default_return_in_memory (co
 extern rtx default_expand_builtin_saveregs (void);
 extern void default_setup_incoming_varargs (cumulative_args_t, machine_mode, tree, int *, int);
 extern rtx default_builtin_setjmp_frame_value (void);
+extern bool default_is_reg_clobbering_setjmp_p (const rtx_insn *);
 extern bool default_pretend_outgoing_varargs_named (cumulative_args_t);
 
 extern scalar_int_mode default_eh_return_filter_mode (void);
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c	(revision 264698)
+++ gcc/ira-lives.c	(working copy)
@@ -1209,8 +1209,7 @@ process_bb_node_lives (ira_loop_tree_nod
 		     call, if this function receives a nonlocal
 		     goto.  */
 		  if (cfun->has_nonlocal_label
-		      || find_reg_note (insn, REG_SETJMP,
-					NULL_RTX) != NULL_RTX)
+		      || targetm.is_reg_clobbering_setjmp_p (insn))
 		    {
 		      SET_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj));
 		      SET_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
Index: gcc/lra-lives.c
===================================================================
--- gcc/lra-lives.c	(revision 264698)
+++ gcc/lra-lives.c	(working copy)
@@ -893,8 +893,7 @@ process_bb_lives (basic_block bb, int &c
 	  sparseset_ior (pseudos_live_through_calls,
 			 pseudos_live_through_calls, pseudos_live);
 	  if (cfun->has_nonlocal_label
-	      || find_reg_note (curr_insn, REG_SETJMP,
-				NULL_RTX) != NULL_RTX)
+	      || targetm.is_reg_clobbering_setjmp_p (curr_insn))
 	    sparseset_ior (pseudos_live_through_setjumps,
 			   pseudos_live_through_setjumps, pseudos_live);
 	}
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 264698)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1978,6 +1978,9 @@ static const struct attribute_spec rs600
 #undef TARGET_ASM_GLOBALIZE_DECL_NAME
 #define TARGET_ASM_GLOBALIZE_DECL_NAME rs6000_globalize_decl_name
 #endif
+
+#undef TARGET_IS_REG_CLOBBERING_SETJMP_P
+#define TARGET_IS_REG_CLOBBERING_SETJMP_P rs6000_is_reg_clobbering_setjmp_p
 
 
 /* Processor table.  */
@@ -38696,6 +38699,14 @@ rs6000_starting_frame_offset (void)
     return 0;
   return RS6000_STARTING_FRAME_OFFSET;
 }
+
+/* Implement TARGET_IS_REG_CLOBBERING_SETJMP_P.  */
+
+static bool
+rs6000_is_reg_clobbering_setjmp_p (const rtx_insn *insn ATTRIBUTE_UNUSED)
+{
+  return false;
+}
 
 
 /* Create an alias for a mangled name where we have changed the mangling (in
Index: gcc/testsuite/gcc.target/powerpc/pr87466.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr87466.c	(nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr87466.c	(working copy)
@@ -0,0 +1,19 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-options "-O2" } */
+
+#include <stdlib.h>
+#include <setjmp.h>
+
+extern void foo (jmp_buf);
+
+long
+c (long var)
+{
+  jmp_buf env;
+  if (setjmp(env) != 0)
+    abort();
+  foo (env);
+  return var;
+}
+
+/* { dg-final { scan-assembler {\mmr\M} } } */
