On Sat, Sep 29, 2018 at 5:12 AM Peter Bergner <berg...@linux.ibm.com> wrote:
>
> 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?

LGTM.  Please leave others the opportunity to comment.

Thanks,
Richard.

> 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