This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: RFA: Allow __sync_synchronize to use an external function
- From: "Richard Guenther" <richard dot guenther at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org, rdsandiford at googlemail dot com
- Date: Thu, 26 Jun 2008 22:57:51 +0200
- Subject: Re: RFA: Allow __sync_synchronize to use an external function
- References: <87d4m3q5yx.fsf@firetop.home>
On Thu, Jun 26, 2008 at 10:47 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> Most of the __sync_* builtins fall back to external routines if
> the target has no native support for them. The exception is
> __sync_synchronize, which simply becomes an empty volatile asm
> with a memory clobber attached. This default implementation
> is (in general) ineffective for SMP.
>
> The default implementation of __sync_lock_release is a call to
> __sync_synchronize followed by a store of zero. Thus the fallback
> definition of __sync_lock_release is an empty volatile asm followed
> by a store of zero.
>
> This is usually not a problem, as most targets either have
> native synchronisation instructions or don't support SMP at all.
> Unfortunately, MIPS16 is one exception to this. The MIPS16 ISA
> doesn't have a synchronisation instruction itself, but the full
> non-MIPS16 ISA does. The MIPS16 implementation of __sync_synchronize
> must therefore call an external non-MIPS16 routine.
>
> I could handle this as a special case in the MIPS backend, but I can
> imagine that other ports might eventually need an external call too.
> I'd therefore like to add a new global libfunc that can be filled in
> by targetm.init_libfuncs.
>
> Tested on mipsisa64-elfoabi and x86_64-linux-gnu. OK to install?
Reasonable. This is ok.
Thanks,
Richard.
> Richard
>
>
> gcc/
> * libfuncs.h (LTI_synchronize): New libfunc_index.
> (synchronize_libfunc): Declare.
> * builtins.c (expand_builtin_synchronize): Consider using
> synchronize_libfunc before falling back on an asm blockage.
> * config/mips/mips.c: Include libfuncs.h
> (mips_init_libfuncs): Initialize synchronize_libfunc for TARGET_MIPS16.
>
> Index: gcc/libfuncs.h
> ===================================================================
> --- gcc/libfuncs.h 2008-06-25 05:13:52.000000000 +0100
> +++ gcc/libfuncs.h 2008-06-25 05:16:08.000000000 +0100
> @@ -40,6 +40,8 @@ enum libfunc_index
> LTI_profile_function_entry,
> LTI_profile_function_exit,
>
> + LTI_synchronize,
> +
> LTI_gcov_flush,
>
> LTI_MAX
> @@ -69,6 +71,8 @@ #define unwind_sjlj_unregister_libfunc \
> #define profile_function_entry_libfunc (libfunc_table[LTI_profile_function_entry])
> #define profile_function_exit_libfunc (libfunc_table[LTI_profile_function_exit])
>
> +#define synchronize_libfunc (libfunc_table[LTI_synchronize])
> +
> #define gcov_flush_libfunc (libfunc_table[LTI_gcov_flush])
>
> #endif /* GCC_LIBFUNCS_H */
> Index: gcc/builtins.c
> ===================================================================
> --- gcc/builtins.c 2008-06-25 05:13:52.000000000 +0100
> +++ gcc/builtins.c 2008-06-25 05:16:08.000000000 +0100
> @@ -5993,6 +5993,12 @@ expand_builtin_synchronize (void)
> }
> #endif
>
> + if (synchronize_libfunc != NULL_RTX)
> + {
> + emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
> + return;
> + }
> +
> /* If no explicit memory barrier instruction is available, create an
> empty asm stmt with a memory clobber. */
> x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
> Index: gcc/config/mips/mips.c
> ===================================================================
> --- gcc/config/mips/mips.c 2008-06-25 05:15:49.000000000 +0100
> +++ gcc/config/mips/mips.c 2008-06-25 05:18:04.000000000 +0100
> @@ -42,6 +42,7 @@ the Free Software Foundation; either ver
> #include "function.h"
> #include "expr.h"
> #include "optabs.h"
> +#include "libfuncs.h"
> #include "flags.h"
> #include "reload.h"
> #include "tm_p.h"
> @@ -9402,6 +9403,11 @@ mips_init_libfuncs (void)
> else
> /* Register the gofast functions if selected using --enable-gofast. */
> gofast_maybe_init_libfuncs ();
> +
> + /* The MIPS16 ISA does not have an encoding for "sync", so we rely
> + on an external non-MIPS16 routine to implement __sync_synchronize. */
> + if (TARGET_MIPS16)
> + synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
> }
>
> /* Return the length of INSN. LENGTH is the initial length computed by
>