On Sat, Sep 29, 2018 at 5:12 AM Peter Bergner <[email protected]> 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} } } */
>