public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Christophe LYON <christophe.lyon@foss.st.com>
To: <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH RFC] c++: implement C++17 hardware interference size
Date: Tue, 14 Sep 2021 09:56:01 +0200	[thread overview]
Message-ID: <511b262a-5187-108d-7047-16d2d87e5667@foss.st.com> (raw)
In-Reply-To: <20210910131625.159525-1-jason@redhat.com>


On 10/09/2021 15:16, Jason Merrill via Gcc-patches wrote:
> OK, time to finish this up.  The main change relative to the last patch I sent
> to the list is dropping the -finterference-tune flag and making that behavior
> the default.  Any more comments?
>
> ====
>
> The last missing piece of the C++17 standard library is the hardware
> intereference size constants.  Much of the delay in implementing these has
> been due to uncertainty about what the right values are, and even whether
> there is a single constant value that is suitable; the destructive
> interference size is intended to be used in structure layout, so program
> ABIs will depend on it.
>
> In principle, both of these values should be the same as the target's L1
> cache line size.  When compiling for a generic target that is intended to
> support a range of target CPUs with different cache line sizes, the
> constructive size should probably be the minimum size, and the destructive
> size the maximum, unless you are constrained by ABI compatibility with
> previous code.
>
>  From discussion on gcc-patches, I've come to the conclusion that the
> solution to the difficulty of choosing stable values is to give up on it,
> and instead encourage only uses where ABI stability is unimportant: in
> particular, uses where the ABI is shared at most between translation units
> built at the same time with the same flags.
>
> To that end, I've added a warning for any use of the constant value of
> std::hardware_destructive_interference_size in a header or module export.
> Appropriate uses within a project can disable the warning.
>
> A previous iteration of this patch included an -finterference-tune flag to
> make the value vary with -mtune; this iteration makes that the default
> behavior, which should be appropriate for all reasonable uses of the
> variable.  The previous default of "stable-ish" seems to me likely to have
> been more of an attractive nuisance; since we can't promise actual
> stability, we should instead make proper uses more convenient.
>
> JF Bastien's implementation proposal is summarized at
> https://github.com/itanium-cxx-abi/cxx-abi/issues/74
>
> I implement this by adding new --params for the two sizes.  Targets can
> override these values in targetm.target_option.override() to support a range
> of values for the generic target; otherwise, both will default to the L1
> cache line size.
>
> 64 bytes still seems correct for all x86.
>
> I'm not sure why he proposed 64/64 for generic 32-bit ARM, since the Cortex
> A9 has a 32-byte cache line, so I'd think 32/64 would make more sense.

While this works for an arm-linux-gnueabihf toolchain configured 
--with-mode=arm, it fails --with-mode=thumb (also using 
--with-cpu=cortex-a9):

<built-in>: error: '--param constructive-interference-size=64' is 
greater than '--param l1-cache-line-size=32' [-Werror=interference-size]
cc1plus: all warnings being treated as errors
make[4]: *** [Makefile:678: alloc_c.lo] Error 1



>
> He proposed 64/128 for generic AArch64, but since the A64FX now has a 256B
> cache line, I've changed that to 64/256.


Similarly, for aarch64 I'm seeing:

<built-in>: error: '--param constructive-interference-size=64' is 
greater than '--param l1-cache-line-size=32' [-Werror=interference-size]
cc1plus: all warnings being treated as errors
make[4]: *** [Makefile:678: alloc_c.lo] Error 1


So adjustment is needed for both arm and aarch64 targets


Christophe


>
> With the above choice to reject stability as a goal, getting these values
> "right" is now just a matter of what we want the default optimization to be,
> and we can feel free to adjust them as CPUs with different cache lines
> become more and less common.
>
> gcc/ChangeLog:
>
> 	* params.opt: Add destructive-interference-size and
> 	constructive-interference-size.
> 	* doc/invoke.texi: Document them.
> 	* config/aarch64/aarch64.c (aarch64_override_options_internal):
> 	Set them.
> 	* config/arm/arm.c (arm_option_override): Set them.
> 	* config/i386/i386-options.c (ix86_option_override_internal):
> 	Set them.
>
> gcc/c-family/ChangeLog:
>
> 	* c.opt: Add -Winterference-size.
> 	* c-cppbuiltin.c (cpp_atomic_builtins): Add __GCC_DESTRUCTIVE_SIZE
> 	and __GCC_CONSTRUCTIVE_SIZE.
>
> gcc/cp/ChangeLog:
>
> 	* constexpr.c (maybe_warn_about_constant_value):
> 	Complain about std::hardware_destructive_interference_size.
> 	(cxx_eval_constant_expression): Call it.
> 	* decl.c (cxx_init_decl_processing): Check
> 	--param *-interference-size values.
>
> libstdc++-v3/ChangeLog:
>
> 	* include/std/version: Define __cpp_lib_hardware_interference_size.
> 	* libsupc++/new: Define hardware interference size variables.
>
> gcc/testsuite/ChangeLog:
>
> 	* g++.dg/warn/Winterference.h: New file.
> 	* g++.dg/warn/Winterference.C: New test.
> 	* g++.target/aarch64/interference.C: New test.
> 	* g++.target/arm/interference.C: New test.
> 	* g++.target/i386/interference.C: New test.
> ---
>   gcc/doc/invoke.texi                           | 65 +++++++++++++++++++
>   gcc/c-family/c.opt                            |  5 ++
>   gcc/params.opt                                | 16 +++++
>   gcc/c-family/c-cppbuiltin.c                   | 12 ++++
>   gcc/config/aarch64/aarch64.c                  | 22 +++++++
>   gcc/config/arm/arm.c                          | 22 +++++++
>   gcc/config/i386/i386-options.c                |  6 ++
>   gcc/cp/constexpr.c                            | 33 ++++++++++
>   gcc/cp/decl.c                                 | 32 +++++++++
>   gcc/testsuite/g++.dg/warn/Winterference-2.C   | 14 ++++
>   gcc/testsuite/g++.dg/warn/Winterference.C     |  6 ++
>   .../g++.target/aarch64/interference.C         |  9 +++
>   gcc/testsuite/g++.target/arm/interference.C   |  9 +++
>   gcc/testsuite/g++.target/i386/interference.C  |  8 +++
>   gcc/testsuite/g++.dg/warn/Winterference.H     |  7 ++
>   libstdc++-v3/include/std/version              |  3 +
>   libstdc++-v3/libsupc++/new                    | 10 ++-
>   17 files changed, 277 insertions(+), 2 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/warn/Winterference-2.C
>   create mode 100644 gcc/testsuite/g++.dg/warn/Winterference.C
>   create mode 100644 gcc/testsuite/g++.target/aarch64/interference.C
>   create mode 100644 gcc/testsuite/g++.target/arm/interference.C
>   create mode 100644 gcc/testsuite/g++.target/i386/interference.C
>   create mode 100644 gcc/testsuite/g++.dg/warn/Winterference.H
>
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index d4b3a66ee4f..f49d82aa508 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -9017,6 +9017,43 @@ that has already been done in the current function.  Therefore,
>   seemingly insignificant changes in the source program can cause the
>   warnings produced by @option{-Winline} to appear or disappear.
>   
> +@item -Winterference-size
> +@opindex Winterference-size
> +Warn about use of C++17 @code{std::hardware_destructive_interference_size}
> +without specifying its value with @option{--param destructive-interference-size}.
> +Also warn about questionable values for that option.
> +
> +This variable is intended to be used for controlling class layout, to
> +avoid false sharing in concurrent code:
> +
> +@smallexample
> +struct independent_fields @{
> +  alignas(std::hardware_destructive_interference_size) std::atomic<int> one;
> +  alignas(std::hardware_destructive_interference_size) std::atomic<int> two;
> +@};
> +@end smallexample
> +
> +Here @samp{one} and @samp{two} are intended to be far enough apart
> +that stores to one won't require accesses to the other to reload the
> +cache line.
> +
> +By default, @option{--param destructive-interference-size} and
> +@option{--param constructive-interference-size} are set based on the
> +current @option{-mtune} option, typically to the L1 cache line size
> +for the particular target CPU, sometimes to a range if tuning for a
> +generic target.  So all translation units that depend on ABI
> +compatibility for the use of these variables must be compiled with
> +the same @option{-mtune} (or @option{-mcpu}).
> +
> +If ABI stability is important, such as if the use is in a header for a
> +library, you should probably not use the hardware interference size
> +variables at all.  Alternatively, you can force a particular value
> +with @option{--param}.
> +
> +If you are confident that your use of the variable does not affect ABI
> +outside a single build of your project, you can turn off the warning
> +with @option{-Wno-interference-size}.
> +
>   @item -Wint-in-bool-context
>   @opindex Wint-in-bool-context
>   @opindex Wno-int-in-bool-context
> @@ -13902,6 +13939,34 @@ prefetch hints can be issued for any constant stride.
>   
>   This setting is only useful for strides that are known and constant.
>   
> +@item destructive-interference-size
> +@item constructive-interference-size
> +The values for the C++17 variables
> +@code{std::hardware_destructive_interference_size} and
> +@code{std::hardware_constructive_interference_size}.  The destructive
> +interference size is the minimum recommended offset between two
> +independent concurrently-accessed objects; the constructive
> +interference size is the maximum recommended size of contiguous memory
> +accessed together.  Typically both will be the size of an L1 cache
> +line for the target, in bytes.  For a generic target covering a range of L1
> +cache line sizes, typically the constructive interference size will be
> +the small end of the range and the destructive size will be the large
> +end.
> +
> +The destructive interference size is intended to be used for layout,
> +and thus has ABI impact.  The default value is not expected to be
> +stable, and on some targets varies with @option{-mtune}, so use of
> +this variable in a context where ABI stability is important, such as
> +the public interface of a library, is strongly discouraged; if it is
> +used in that context, users can stabilize the value using this
> +option.
> +
> +The constructive interference size is less sensitive, as it is
> +typically only used in a @samp{static_assert} to make sure that a type
> +fits within a cache line.
> +
> +See also @option{-Winterference-size}.
> +
>   @item loop-interchange-max-num-stmts
>   The maximum number of stmts in a loop to be interchanged.
>   
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index c5fe90003f2..9c151d19870 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -722,6 +722,11 @@ Winit-list-lifetime
>   C++ ObjC++ Var(warn_init_list) Warning Init(1)
>   Warn about uses of std::initializer_list that can result in dangling pointers.
>   
> +Winterference-size
> +C++ ObjC++ Var(warn_interference_size) Warning Init(1)
> +Warn about nonsensical values of --param destructive-interference-size or
> +constructive-interference-size.
> +
>   Wimplicit
>   C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall)
>   Warn about implicit declarations.
> diff --git a/gcc/params.opt b/gcc/params.opt
> index 3a701e22c46..658ca028851 100644
> --- a/gcc/params.opt
> +++ b/gcc/params.opt
> @@ -361,6 +361,22 @@ The maximum code size growth ratio when expanding into a jump table (in percent)
>   Common Joined UInteger Var(param_l1_cache_line_size) Init(32) Param Optimization
>   The size of L1 cache line.
>   
> +-param=destructive-interference-size=
> +Common Joined UInteger Var(param_destruct_interfere_size) Init(0) Param Optimization
> +The minimum recommended offset between two concurrently-accessed objects to
> +avoid additional performance degradation due to contention introduced by the
> +implementation.  Typically the L1 cache line size, but can be larger to
> +accommodate a variety of target processors with different cache line sizes.
> +C++17 code might use this value in structure layout, but is strongly
> +discouraged from doing so in public ABIs.
> +
> +-param=constructive-interference-size=
> +Common Joined UInteger Var(param_construct_interfere_size) Init(0) Param Optimization
> +The maximum recommended size of contiguous memory occupied by two objects
> +accessed with temporal locality by concurrent threads.  Typically the L1 cache
> +line size, but can be smaller to accommodate a variety of target processors with
> +different cache line sizes.
> +
>   -param=l1-cache-size=
>   Common Joined UInteger Var(param_l1_cache_size) Init(64) Param Optimization
>   The size of L1 cache.
> diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
> index 48cbefd8bf8..020e2ea4f25 100644
> --- a/gcc/c-family/c-cppbuiltin.c
> +++ b/gcc/c-family/c-cppbuiltin.c
> @@ -741,6 +741,18 @@ cpp_atomic_builtins (cpp_reader *pfile)
>     builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
>   				 targetm.atomic_test_and_set_trueval);
>   
> +  /* Macros for C++17 hardware interference size constants.  Either both or
> +     neither should be set.  */
> +  gcc_assert (!param_destruct_interfere_size
> +	      == !param_construct_interfere_size);
> +  if (param_destruct_interfere_size)
> +    {
> +      builtin_define_with_int_value ("__GCC_DESTRUCTIVE_SIZE",
> +				     param_destruct_interfere_size);
> +      builtin_define_with_int_value ("__GCC_CONSTRUCTIVE_SIZE",
> +				     param_construct_interfere_size);
> +    }
> +
>     /* ptr_type_node can't be used here since ptr_mode is only set when
>        toplev calls backend_init which is not done with -E  or pch.  */
>     psize = POINTER_SIZE_UNITS;
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 1fbe9e0daa0..05d42a66c7e 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -16539,6 +16539,28 @@ aarch64_override_options_internal (struct gcc_options *opts)
>       SET_OPTION_IF_UNSET (opts, &global_options_set,
>   			 param_l1_cache_line_size,
>   			 aarch64_tune_params.prefetch->l1_cache_line_size);
> +
> +  if (aarch64_tune_params.prefetch->l1_cache_line_size >= 0)
> +    {
> +      SET_OPTION_IF_UNSET (opts, &global_options_set,
> +			   param_destruct_interfere_size,
> +			   aarch64_tune_params.prefetch->l1_cache_line_size);
> +      SET_OPTION_IF_UNSET (opts, &global_options_set,
> +			   param_construct_interfere_size,
> +			   aarch64_tune_params.prefetch->l1_cache_line_size);
> +    }
> +  else
> +    {
> +      /* For a generic AArch64 target, cover the current range of cache line
> +	 sizes.  */
> +      SET_OPTION_IF_UNSET (opts, &global_options_set,
> +			   param_destruct_interfere_size,
> +			   256);
> +      SET_OPTION_IF_UNSET (opts, &global_options_set,
> +			   param_construct_interfere_size,
> +			   64);
> +    }
> +
>     if (aarch64_tune_params.prefetch->l2_cache_size >= 0)
>       SET_OPTION_IF_UNSET (opts, &global_options_set,
>   			 param_l2_cache_size,
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index f1e628253d0..6c6e77fab66 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -3669,6 +3669,28 @@ arm_option_override (void)
>       SET_OPTION_IF_UNSET (&global_options, &global_options_set,
>   			 param_l1_cache_line_size,
>   			 current_tune->prefetch.l1_cache_line_size);
> +  if (current_tune->prefetch.l1_cache_line_size >= 0)
> +    {
> +      SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> +			   param_destruct_interfere_size,
> +			   current_tune->prefetch.l1_cache_line_size);
> +      SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> +			   param_construct_interfere_size,
> +			   current_tune->prefetch.l1_cache_line_size);
> +    }
> +  else
> +    {
> +      /* For a generic ARM target, JF Bastien proposed using 64 for both.  */
> +      /* ??? Cortex A9 has a 32-byte cache line, so why not 32 for
> +	 constructive?  */
> +      /* More recent Cortex chips have a 64-byte cache line, but are marked
> +	 ARM_PREFETCH_NOT_BENEFICIAL, so they get these defaults.  */
> +      SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> +			   param_destruct_interfere_size, 64);
> +      SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> +			   param_construct_interfere_size, 64);
> +    }
> +
>     if (current_tune->prefetch.l1_cache_size >= 0)
>       SET_OPTION_IF_UNSET (&global_options, &global_options_set,
>   			 param_l1_cache_size,
> diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
> index 2cb87cedec0..c0006b3674b 100644
> --- a/gcc/config/i386/i386-options.c
> +++ b/gcc/config/i386/i386-options.c
> @@ -2579,6 +2579,12 @@ ix86_option_override_internal (bool main_args_p,
>     SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size,
>   		       ix86_tune_cost->l2_cache_size);
>   
> +  /* 64B is the accepted value for these for all x86.  */
> +  SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> +		       param_destruct_interfere_size, 64);
> +  SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> +		       param_construct_interfere_size, 64);
> +
>     /* Enable sw prefetching at -O3 for CPUS that prefetching is helpful.  */
>     if (opts->x_flag_prefetch_loop_arrays < 0
>         && HAVE_prefetch
> diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> index 7772fe62d95..0c2498aee22 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -6075,6 +6075,37 @@ inline_asm_in_constexpr_error (location_t loc)
>   	  "%<constexpr%> function in C++20");
>   }
>   
> +/* We're getting the constant value of DECL in a manifestly constant-evaluated
> +   context; maybe complain about that.  */
> +
> +static void
> +maybe_warn_about_constant_value (location_t loc, tree decl)
> +{
> +  static bool explained = false;
> +  if (cxx_dialect >= cxx17
> +      && warn_interference_size
> +      && !global_options_set.x_param_destruct_interfere_size
> +      && DECL_CONTEXT (decl) == std_node
> +      && id_equal (DECL_NAME (decl), "hardware_destructive_interference_size")
> +      && (LOCATION_FILE (input_location) != main_input_filename
> +	  || module_exporting_p ())
> +      && warning_at (loc, OPT_Winterference_size, "use of %qD", decl)
> +      && !explained)
> +    {
> +      explained = true;
> +      inform (loc, "its value can vary between compiler versions or "
> +	      "with different %<-mtune%> or %<-mcpu%> flags");
> +      inform (loc, "if this use is part of a public ABI, change it to "
> +	      "instead use a constant variable you define");
> +      inform (loc, "the default value for the current CPU tuning "
> +	      "is %d bytes", param_destruct_interfere_size);
> +      inform (loc, "you can stabilize this value with %<--param "
> +	      "hardware_destructive_interference_size=%d%>, or disable "
> +	      "this warning with %<-Wno-interference-size%>",
> +	      param_destruct_interfere_size);
> +    }
> +}
> +
>   /* Attempt to reduce the expression T to a constant value.
>      On failure, issue diagnostic and return error_mark_node.  */
>   /* FIXME unify with c_fully_fold */
> @@ -6219,6 +6250,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
>   	      r = *p;
>   	      break;
>   	    }
> +      if (ctx->manifestly_const_eval)
> +	maybe_warn_about_constant_value (loc, t);
>         if (COMPLETE_TYPE_P (TREE_TYPE (t))
>   	  && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
>   	{
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index bce62ad202a..c2065027369 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -4752,6 +4752,38 @@ cxx_init_decl_processing (void)
>     /* Show we use EH for cleanups.  */
>     if (flag_exceptions)
>       using_eh_for_cleanups ();
> +
> +  /* Check that the hardware interference sizes are at least
> +     alignof(max_align_t), as required by the standard.  */
> +  const int max_align = max_align_t_align () / BITS_PER_UNIT;
> +  if (param_destruct_interfere_size)
> +    {
> +      if (param_destruct_interfere_size < max_align)
> +	error ("%<--param destructive-interference-size=%d%> is less than "
> +	       "%d", param_destruct_interfere_size, max_align);
> +      else if (param_destruct_interfere_size < param_l1_cache_line_size)
> +	warning (OPT_Winterference_size,
> +		 "%<--param destructive-interference-size=%d%> "
> +		 "is less than %<--param l1-cache-line-size=%d%>",
> +		 param_destruct_interfere_size, param_l1_cache_line_size);
> +    }
> +  else if (param_l1_cache_line_size >= max_align)
> +    param_destruct_interfere_size = param_l1_cache_line_size;
> +  /* else leave it unset.  */
> +
> +  if (param_construct_interfere_size)
> +    {
> +      if (param_construct_interfere_size < max_align)
> +	error ("%<--param constructive-interference-size=%d%> is less than "
> +	       "%d", param_construct_interfere_size, max_align);
> +      else if (param_construct_interfere_size > param_l1_cache_line_size)
> +	warning (OPT_Winterference_size,
> +		 "%<--param constructive-interference-size=%d%> "
> +		 "is greater than %<--param l1-cache-line-size=%d%>",
> +		 param_construct_interfere_size, param_l1_cache_line_size);
> +    }
> +  else if (param_l1_cache_line_size >= max_align)
> +    param_construct_interfere_size = param_l1_cache_line_size;
>   }
>   
>   /* Enter an abi node in global-module context.  returns a cookie to
> diff --git a/gcc/testsuite/g++.dg/warn/Winterference-2.C b/gcc/testsuite/g++.dg/warn/Winterference-2.C
> new file mode 100644
> index 00000000000..2af75c63f83
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Winterference-2.C
> @@ -0,0 +1,14 @@
> +// { dg-do compile { target c++20 } }
> +// { dg-additional-options -fmodules-ts }
> +
> +module ;
> +
> +#include <new>
> +
> +export module foo;
> +
> +export {
> +  struct A {
> +    alignas(std::hardware_destructive_interference_size) int x; // { dg-warning Winterference-size }
> +  };
> +}
> diff --git a/gcc/testsuite/g++.dg/warn/Winterference.C b/gcc/testsuite/g++.dg/warn/Winterference.C
> new file mode 100644
> index 00000000000..57c001bc032
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Winterference.C
> @@ -0,0 +1,6 @@
> +// Test that we warn about use of std::hardware_destructive_interference_size
> +// in a header.
> +// { dg-do compile { target c++17 } }
> +
> +// { dg-warning Winterference-size "" { target *-*-* } 0 }
> +#include "Winterference.H"
> diff --git a/gcc/testsuite/g++.target/aarch64/interference.C b/gcc/testsuite/g++.target/aarch64/interference.C
> new file mode 100644
> index 00000000000..0fc01655223
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/interference.C
> @@ -0,0 +1,9 @@
> +// Test C++17 hardware interference size constants
> +// { dg-do compile { target c++17 } }
> +
> +#include <new>
> +
> +// Most AArch64 CPUs have an L1 cache line size of 64, but some recent ones use
> +// 128 or even 256.
> +static_assert(std::hardware_destructive_interference_size == 256);
> +static_assert(std::hardware_constructive_interference_size == 64);
> diff --git a/gcc/testsuite/g++.target/arm/interference.C b/gcc/testsuite/g++.target/arm/interference.C
> new file mode 100644
> index 00000000000..34fe8a52bff
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/arm/interference.C
> @@ -0,0 +1,9 @@
> +// Test C++17 hardware interference size constants
> +// { dg-do compile { target c++17 } }
> +
> +#include <new>
> +
> +// Recent ARM CPUs have a cache line size of 64.  Older ones have
> +// a size of 32, but I guess they're old enough that we don't care?
> +static_assert(std::hardware_destructive_interference_size == 64);
> +static_assert(std::hardware_constructive_interference_size == 64);
> diff --git a/gcc/testsuite/g++.target/i386/interference.C b/gcc/testsuite/g++.target/i386/interference.C
> new file mode 100644
> index 00000000000..c7b910e3ada
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/i386/interference.C
> @@ -0,0 +1,8 @@
> +// Test C++17 hardware interference size constants
> +// { dg-do compile { target c++17 } }
> +
> +#include <new>
> +
> +// It is generally agreed that these are the right values for all x86.
> +static_assert(std::hardware_destructive_interference_size == 64);
> +static_assert(std::hardware_constructive_interference_size == 64);
> diff --git a/gcc/testsuite/g++.dg/warn/Winterference.H b/gcc/testsuite/g++.dg/warn/Winterference.H
> new file mode 100644
> index 00000000000..36f0ad5f6d1
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Winterference.H
> @@ -0,0 +1,7 @@
> +#include <new>
> +
> +struct A
> +{
> +  alignas(std::hardware_destructive_interference_size) int i;
> +  alignas(std::hardware_destructive_interference_size) int j;
> +};
> diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
> index f950bf0f0db..f41004b5911 100644
> --- a/libstdc++-v3/include/std/version
> +++ b/libstdc++-v3/include/std/version
> @@ -140,6 +140,9 @@
>   #define __cpp_lib_filesystem 201703
>   #define __cpp_lib_gcd 201606
>   #define __cpp_lib_gcd_lcm 201606
> +#ifdef __GCC_DESTRUCTIVE_SIZE
> +# define __cpp_lib_hardware_interference_size 201703L
> +#endif
>   #define __cpp_lib_hypot 201603
>   #define __cpp_lib_invoke 201411L
>   #define __cpp_lib_lcm 201606
> diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
> index 3349b13fd1b..7bc67a6cb02 100644
> --- a/libstdc++-v3/libsupc++/new
> +++ b/libstdc++-v3/libsupc++/new
> @@ -183,9 +183,9 @@ inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
>   } // extern "C++"
>   
>   #if __cplusplus >= 201703L
> -#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
>   namespace std
>   {
> +#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
>   #define __cpp_lib_launder 201606
>     /// Pointer optimization barrier [ptr.launder]
>     template<typename _Tp>
> @@ -205,8 +205,14 @@ namespace std
>     void launder(const void*) = delete;
>     void launder(volatile void*) = delete;
>     void launder(const volatile void*) = delete;
> -}
>   #endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER
> +
> +#ifdef __GCC_DESTRUCTIVE_SIZE
> +# define __cpp_lib_hardware_interference_size 201703L
> +  inline constexpr size_t hardware_destructive_interference_size = __GCC_DESTRUCTIVE_SIZE;
> +  inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUCTIVE_SIZE;
> +#endif // __GCC_DESTRUCTIVE_SIZE
> +}
>   #endif // C++17
>   
>   #if __cplusplus > 201703L
>
> base-commit: de515ce0b209cc7e5a780d9846e5154d380a763e

  reply	other threads:[~2021-09-14  7:56 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-16  2:36 [PATCH] " Jason Merrill
2021-07-16  2:41 ` Jason Merrill
2021-07-16  2:48   ` Noah Goldstein
2021-07-16 11:17     ` Jonathan Wakely
2021-07-16 13:27       ` Richard Earnshaw
2021-07-16 13:26   ` Jonathan Wakely
2021-07-16 15:12   ` Matthias Kretz
2021-07-16 15:30     ` Jason Merrill
2021-07-16 16:54       ` Jonathan Wakely
2021-07-16 18:43         ` Jason Merrill
2021-07-16 19:26         ` Matthias Kretz
2021-07-16 19:58           ` Jonathan Wakely
2021-07-17  8:14             ` Matthias Kretz
2021-07-17 13:32               ` Jonathan Wakely
2021-07-17 13:54                 ` Matthias Kretz
2021-07-17 21:37                   ` Jason Merrill
2021-07-19  9:41                     ` Richard Earnshaw
2021-07-20 16:43                       ` Jason Merrill
2021-09-10 13:16                         ` [PATCH RFC] " Jason Merrill
2021-09-14  7:56                           ` Christophe LYON [this message]
2021-09-15 10:25                             ` Richard Earnshaw
2021-09-15 11:30                               ` Christophe Lyon
2021-09-15 12:31                             ` Martin Liška
2021-09-15 15:31                               ` [pushed] c++: don't warn about internal interference sizes Jason Merrill
2021-09-15 15:36                                 ` Jeff Law
2021-09-15 15:38                                   ` Jason Merrill
2021-09-15 16:15                                     ` Christophe Lyon
2021-09-15 15:35                               ` [PATCH RFC] c++: implement C++17 hardware interference size Jason Merrill
2021-07-20 18:05                 ` [PATCH] " Thomas Rodgers
2021-07-16 17:20     ` Noah Goldstein
2021-07-16 19:37       ` Matthias Kretz
2021-07-16 21:23         ` Noah Goldstein

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=511b262a-5187-108d-7047-16d2d87e5667@foss.st.com \
    --to=christophe.lyon@foss.st.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).