On Fri, 4 Sep 2026, [email protected] wrote:

> From: Kyrylo Tkachov <[email protected]>
> 
> LIM store motion does not update EH information.  can_sm_ref_p rejects a
> reference when tree_could_throw_p says that it can throw.  That query treats a
> bare memory reference as a load.  A safe load does not prove that a store to
> the same address cannot trap.
> 
> The later store-specific check only requires a trapping store to execute on
> every loop iteration.  It does not protect its EH region when the store is
> moved out of the loop.
> 
> Compute the store trap result once.  When exception handling is enabled and
> the function can throw non-call exceptions, reject every trapping store.  Keep
> the existing execution test for the other cases.
> 
> Bootstrapped and tested on aarch64-unknown-linux-gnu.

OK.

Thanks,
Richard.

> gcc/ChangeLog:
> 
>       * tree-ssa-loop-im.cc (can_sm_ref_p): Reject a trapping store when
>       non-call exceptions are enabled.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/tree-ssa/noncall-store-1.C: New test.
> 
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
>  .../g++.dg/tree-ssa/noncall-store-1.C         | 20 +++++++++++++++++++
>  gcc/tree-ssa-loop-im.cc                       | 16 +++++++++++----
>  2 files changed, 32 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/tree-ssa/noncall-store-1.C
> 
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/noncall-store-1.C 
> b/gcc/testsuite/g++.dg/tree-ssa/noncall-store-1.C
> new file mode 100644
> index 00000000000..fc6a7684671
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/noncall-store-1.C
> @@ -0,0 +1,20 @@
> +// A store through the this parameter can throw a non-call exception even 
> when
> +// the function has no local exception handler.
> +
> +// { dg-do compile }
> +// { dg-options "-O2 -fnon-call-exceptions -fdump-tree-lim2-details" }
> +
> +struct S
> +{
> +  int value;
> +  void loop (int);
> +};
> +
> +void
> +S::loop (int n)
> +{
> +  for (int i = 0; i < n; ++i)
> +    value = i;
> +}
> +
> +// { dg-final { scan-tree-dump-not "Executing store motion" "lim2" } }
> diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
> index 19523fb157a..f38a5831b58 100644
> --- a/gcc/tree-ssa-loop-im.cc
> +++ b/gcc/tree-ssa-loop-im.cc
> @@ -3351,6 +3351,8 @@ ref_in_loop_hot_body::operator () (mem_ref_loc *loc)
>  static bool
>  can_sm_ref_p (class loop *loop, im_mem_ref *ref)
>  {
> +  bool store_could_trap;
> +
>    /* Can't hoist unanalyzable refs.  */
>    if (!MEM_ANALYZABLE (ref))
>      return false;
> @@ -3365,12 +3367,18 @@ can_sm_ref_p (class loop *loop, im_mem_ref *ref)
>        || !for_each_index (&ref->mem.ref, may_move_till, loop))
>      return false;
>  
> -  /* If it can throw fail, we do not properly update EH info.  */
> -  if (tree_could_throw_p (ref->mem.ref))
> +  store_could_trap = lhs_could_trap_p (ref->mem.ref);
> +
> +  /* Do not move a load or store that can throw.  Store motion does not
> +     update EH information.  */
> +  if (tree_could_throw_p (ref->mem.ref)
> +      || (flag_exceptions
> +       && cfun->can_throw_non_call_exceptions
> +       && store_could_trap))
>      return false;
>  
> -  /* If the store can trap, it must be always executed in LOOP.  */
> -  if (lhs_could_trap_p (ref->mem.ref)
> +  /* If a store can trap, it must be always executed in LOOP.  */
> +  if (store_could_trap
>        /* ???  We can at least use false here, allowing loads?  We
>        are forcing conditional stores if the ref is not always
>        stored to later anyway.  So this would only guard
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to