On Tue, Jan 6, 2026 at 11:22 AM Wilco Dijkstra <[email protected]> wrote:
>
>
> The -fmerge-constants option controls whether constants are emitted into
> mergeable sections - however this applies to all constants, including
> strings. On targets that support anchors it may be better to use anchors
> for FP constants (eg. PR121240). Add new params string-merging-threshold
> and constant-merging-threshold to allow finer grained control. The default
> is zero and generated code is unchanged.
>
> OK for commit?
>
> gcc:
> * params.opt (constant-merging-threshold): Add new param.
> (string-merging-threshold): Add new param.
> * varasm.cc (mergeable_string_section): Compare string size with
> param_string_merging_threshold before merging.
> (mergeable_constant_section): Compare constant size with
> param_constant_merging_threshold before merging.
> * doc/invoke.texi (string-merging-threshold): Document new param.
> (constant-merging-threshold): Likewise.
Does it make sense rather to do the non-merge based on the mode in the
case of floating point with maybe a target hook that
mergeable_constant_section calls?
I don't think a param is a good approach here rather than something
finer control.
For an example an constant array of 4 char would still be size of 4
but do you still want to merge those constants or use anchors in that
case? Or is it just floating point values where it might improve
things?
Note I am trying to convince myself which way is better because right
now it is not obvious from this patch if something finer tuned is
needed or doing it by size is always a good idea.
Maybe there are not many non-floating point constants that go into the
mergeable section so the size check won't make a huge difference in
the end; I know that the constant switch load table is now a mergeable
decl. But maybe that does not show up enough to make a difference
here. Likewise of the backing constant of a std::initializer_list.
I would rather be forward looking on this and add the hook now rather
than later on when there are much more mergeable constants which we
want to still merge.
Thanks,
Andrew
>
> ---
>
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index
> bae66ba6c45f9f23f3c97cc55eb292474db502db..8a6c8473d90f2a4798c71c8aeba77a166ccebdae
> 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -18066,6 +18066,14 @@ bubbles. This is the current default. Zero means
> the scheduling description
> might not be available/accurate or perhaps not applicable at all, such as for
> modern out-of-order processors.
>
> +@item string-merging-threshold
> +Specifies the minimum size in bytes before string constants are considered
> for
> +merging across compilation units.
> +
> +@item constant-merging-threshold
> +Specifies the minimum size in bytes before integer/floating-point constants
> +are considered for merging across compilation units.
> +
> @end table
>
> The following choices of @var{name} are available on AArch64 targets:
> diff --git a/gcc/params.opt b/gcc/params.opt
> index
> e2b3930d5a768cb4bcd8815e2d0887190f89596e..947497fa3ac0057c9a3eed86e9db260a1b8894e1
> 100644
> --- a/gcc/params.opt
> +++ b/gcc/params.opt
> @@ -130,6 +130,10 @@ The smallest number of different values for which it is
> best to use a jump-table
> Common Joined UInteger Var(param_comdat_sharing_probability) Init(20) Param
> Optimization
> Probability that COMDAT function will be shared with different compilation
> unit.
>
> +-param=constant-merging-threshold=
> +Common Joined UInteger Var(param_constant_merging_threshold) Init(0) Param
> Optimization
> +Minimum constant size before it is considered for merging across compilation
> units.
> +
> -param=cxx-max-namespaces-for-diagnostic-help=
> Common Joined UInteger Var(param_cxx_max_namespaces_for_diagnostic_help)
> Init(1000) Param
> Maximum number of namespaces to search for alternatives when name lookup
> fails.
> @@ -1107,6 +1111,10 @@ Maximum size of a single store merging region in bytes.
> Common Joined UInteger Var(param_store_forwarding_max_distance) Init(10)
> IntegerRange(0, 1000) Param Optimization
> Maximum number of instruction distance that a small store forwarded to a
> larger load may stall. Value '0' disables the cost checks for the
> avoid-store-forwarding pass.
>
> +-param=string-merging-threshold=
> +Common Joined UInteger Var(param_string_merging_threshold) Init(0) Param
> Optimization
> +Minimum string size before it is considered for merging across compilation
> units.
> +
> -param=switch-conversion-max-branch-ratio=
> Common Joined UInteger Var(param_switch_conversion_branch_ratio) Init(8)
> IntegerRange(1, 65536) Param Optimization
> The maximum ratio between array size and switch branches for a switch
> conversion to take place.
> diff --git a/gcc/varasm.cc b/gcc/varasm.cc
> index
> fec792ec2326f3fb631e5d8b3538f52a57347d66..2c4669f629fcf24848d8dc6e7a5fe681a0a5b66c
> 100644
> --- a/gcc/varasm.cc
> +++ b/gcc/varasm.cc
> @@ -873,6 +873,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
> && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
> && align <= MAX_MERGEABLE_BITSIZE
> && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
> + && len >= param_string_merging_threshold
> && TREE_STRING_LENGTH (decl) == len)
> {
> scalar_int_mode mode;
> @@ -927,6 +928,7 @@ mergeable_constant_section (unsigned HOST_WIDE_INT
> size_bits,
> newsize = HOST_WIDE_INT_1U << ceil_log2 (size_bits);
> if (HAVE_GAS_SHF_MERGE && flag_merge_constants
> && newsize <= MAX_MERGEABLE_BITSIZE
> + && (newsize / BITS_PER_UNIT) >= param_constant_merging_threshold
> && align >= 8
> && align <= newsize
> && (align & (align - 1)) == 0)
>