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)
