Currently, both IRA and LRA spill all pseudo regs that are live across a
setjmp call.  If the target has a sane setjmp, then the compiler should not
have to treat the setjmp call any differently than is does any other normal
function call.  Namely, just mark all pseudos that are live across the setjmp
as conflicting with the volatile registers.

This issue was discussed in the following gcc mailing list thread:

  https://gcc.gnu.org/ml/gcc/2018-03/msg00014.html

...and some people mentioned that some systems do not have sane setjmp
implementations and therefore need the spill all pseudos live across setjmps
to get correct functionality.  It was decided in the thread above that we
should create a target hook that can allow targets to tell IRA and LRA
whether or not they have a sane setjmp implementation.  The following patch
implements that idea along with converting the rs6000 port to use the hook.

This patch passed bootstrap and regtesting on powerpc64le-linux with
no regressions.  Ok for trunk?

Peter


gcc/
        PR rtl-optimization/87466
        * target.def (is_reg_clobbering_setjmp_p): New target hook.
        * doc/tm.texi.in (TARGET_IS_REG_CLOBBERING_SETJMP_P): New hook.
        * doc/tm.texi: Regenerate.
        * targhooks.c (default_is_reg_clobbering_setjmp_p): Declare.
        * targhooks.h (default_is_reg_clobbering_setjmp_p): New function.
        * ira-lives.c (process_bb_node_lives): Use the new target hook.
        * lra-lives.c (process_bb_lives): Likewise.
        * config/rs6000/rs6000.c (TARGET_IS_REG_CLOBBERING_SETJMP_P): Define.
        (rs6000_is_reg_clobbering_setjmp_p): New function.

gcc/testsuite/
        PR rtl-optimization/87466
        * gcc.target/powerpc/pr87466.c: New test.

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} } } */

Reply via email to