Hi,
On Mon, Sep 21 2026, Josef Melcr wrote:
> Assume bodies don't fit in most of the heuristics of the IPA passes.
> They are usually not profitable, but since they are purely an
> optimization tool and don't make it into the binary anyway , we want to
> make the most of them. This patch introduces several bypasses for
> checks which would prevent their optimizations, be it cloning or
> parameter splitting.
>
> gcc/ChangeLog:
>
> * ipa-cp.cc (good_cloning_opportunity_p): Special case assume
> functions.
> * ipa-sra.cc (adjust_parameter_descriptions): Likewise.
> * tree-sra.cc (analyze_all_variable_accesses): Likewise.
>
> Signed-off-by: Josef Melcr <[email protected]>
> ---
> gcc/ipa-cp.cc | 10 ++++++++++
> gcc/ipa-sra.cc | 12 +++++++++---
> gcc/tree-sra.cc | 4 +++-
> 3 files changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
> index d0428d04684..71cac065cce 100644
> --- a/gcc/ipa-cp.cc
> +++ b/gcc/ipa-cp.cc
> @@ -3463,6 +3463,16 @@ good_cloning_opportunity_p (struct cgraph_node *node,
> sreal time_benefit,
> return false;
> }
>
> + /* Assume bodies don't make it into the final binary, so they have no real
> + size. Special case them, as cloning them is always a good idea. */
> + if (node->assume_function)
> + {
> + if (dump_file && (dump_flags & TDF_DETAILS))
> + fprintf (dump_file, " good_cloning_opportunity_p: Always clone "
> + "assume body functions.\n");
> + return true;
> + }
> +
I'm afraid you also need to split the check above this because the check
for !opt_for_fn (node->decl, flag_ipa_cp_clone) should remain to be the
first (the "prohibited" case) but the other ones ("definitely not good")
need to be below this, otherwise this would never trigger in PGO builds?
> gcc_assert (size_cost > 0);
>
> ipa_node_params *info = ipa_node_params_sum->get (node);
> diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
> index a663900fc1d..f26a7ee3ee5 100644
> --- a/gcc/ipa-sra.cc
> +++ b/gcc/ipa-sra.cc
> @@ -2574,8 +2574,11 @@ process_scan_results (cgraph_node *node, struct
> function *fun,
> * param_size_limit);
> }
>
> - if (nonarg_acc_size > optimistic_limit
> - || (!desc->by_ref && nonarg_acc_size == param_size_limit))
> + /* Assume functions have no real replacements, no calls to them will
> make
> + it into the binary, so limits don't matter. */
> + if (!node->assume_function
> + && (nonarg_acc_size > optimistic_limit
> + || (!desc->by_ref && nonarg_acc_size == param_size_limit)))
> {
> disqualify_split_candidate (desc, "Would result into a too big set "
> "of replacements even in best "
OK
> @@ -4439,7 +4442,10 @@ adjust_parameter_descriptions (cgraph_node *node,
> isra_func_summary *ifs)
> param_ipa_sra_ptrwrap_growth_factor);
> desc->param_size_limit = extra_factor * desc->param_size_limit;
> }
> - if (size_would_violate_limit_p (desc, desc->size_reached))
> + /* Don't disqualify assume bodies, as they don't make into the final
> + binary anyway. */
> + if (!node->assume_function
> + && size_would_violate_limit_p (desc, desc->size_reached))
> desc->split_candidate = false;
> }
>
OK
> diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc
> index f951a38442a..0adf6c7b6c7 100644
> --- a/gcc/tree-sra.cc
> +++ b/gcc/tree-sra.cc
> @@ -3915,7 +3915,9 @@ analyze_all_variable_accesses (void)
> fprintf (dump_file, "\n");
> }
> }
> - else
> + /* Don't disqualify assume bodies. Assumes don't have any writes, but
> + scalarizing their arguments is important for later IPA. */
> + else if (!cfun->assume_function)
> disqualify_candidate (var, "No scalar replacements to be created.");
> }
This is quite unexpected, what is the reason to do this?
Martin