[1/2] testsuite: Add dg-require-atomic-exchange non-atomic code

Message ID 20231004025538.489F220439@pchp3.se.axis.com
State Accepted
Headers
Series [1/2] testsuite: Add dg-require-atomic-exchange non-atomic code |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Hans-Peter Nilsson Oct. 4, 2023, 2:55 a.m. UTC
  > From: Christophe Lyon <christophe.lyon@linaro.org>
> Date: Tue, 3 Oct 2023 15:20:39 +0200

> Maybe we need a new variant of dg-require-thread-fence ?

Yes: many of the dg-require-thread-fence users need
something stronger.  Tested arm-eabi together with the next
patch (2/2) with
RUNTESTFLAGS=--target_board=arm-sim/-mthumb/-march=armv6s-m/-mtune=cortex-m0/-mfloat-abi=soft/-mfpu=auto\
conformance.exp=29_atomics/\*

(Incidentally, in the patch context is seen
dg-require-atomic-builtins which is a misnomer: it should
rather be named "dg-require-lock-atomic-builtins-free".)

Ok to commit?

-- >8 --
Some targets (armv6) support inline atomic load and store,
i.e. dg-require-thread-fence matches, but not atomic like
atomic exchange.  This directive will replace uses of
dg-require-thread-fence where an atomic exchange operation
is actually used.

	* testsuite/lib/dg-options.exp (dg-require-atomic-exchange): New proc.
	* testsuite/lib/libstdc++.exp (check_v3_target_atomic_exchange): Ditto.
---
 libstdc++-v3/testsuite/lib/dg-options.exp |  9 ++++++
 libstdc++-v3/testsuite/lib/libstdc++.exp  | 35 +++++++++++++++++++++++
 2 files changed, 44 insertions(+)
  

Comments

Jonathan Wakely Oct. 4, 2023, 8:13 a.m. UTC | #1
On Wed, 4 Oct 2023 at 03:56, Hans-Peter Nilsson <hp@axis.com> wrote:
>
> > From: Christophe Lyon <christophe.lyon@linaro.org>
> > Date: Tue, 3 Oct 2023 15:20:39 +0200
>
> > Maybe we need a new variant of dg-require-thread-fence ?
>
> Yes: many of the dg-require-thread-fence users need
> something stronger.  Tested arm-eabi together with the next
> patch (2/2) with
> RUNTESTFLAGS=--target_board=arm-sim/-mthumb/-march=armv6s-m/-mtune=cortex-m0/-mfloat-abi=soft/-mfpu=auto\
> conformance.exp=29_atomics/\*
>
> (Incidentally, in the patch context is seen
> dg-require-atomic-builtins which is a misnomer: it should
> rather be named "dg-require-lock-atomic-builtins-free".)

dg-require-lock-free-atomic-builtins or
dg-require-atomic-builtins-lock-free, surely?


>
> Ok to commit?
>
> -- >8 --
> Some targets (armv6) support inline atomic load and store,
> i.e. dg-require-thread-fence matches, but not atomic like
> atomic exchange.  This directive will replace uses of
> dg-require-thread-fence where an atomic exchange operation
> is actually used.
>
>         * testsuite/lib/dg-options.exp (dg-require-atomic-exchange): New proc.
>         * testsuite/lib/libstdc++.exp (check_v3_target_atomic_exchange): Ditto.

OK

> ---
>  libstdc++-v3/testsuite/lib/dg-options.exp |  9 ++++++
>  libstdc++-v3/testsuite/lib/libstdc++.exp  | 35 +++++++++++++++++++++++
>  2 files changed, 44 insertions(+)
>
> diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp
> index 84ad0c65330b..b13c2f244c63 100644
> --- a/libstdc++-v3/testsuite/lib/dg-options.exp
> +++ b/libstdc++-v3/testsuite/lib/dg-options.exp
> @@ -133,6 +133,15 @@ proc dg-require-thread-fence { args } {
>      return
>  }
>
> +proc dg-require-atomic-exchange { args } {
> +    if { ![ check_v3_target_atomic_exchange ] } {
> +       upvar dg-do-what dg-do-what
> +       set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
> +       return
> +    }
> +    return
> +}
> +
>  proc dg-require-atomic-builtins { args } {
>      if { ![ check_v3_target_atomic_builtins ] } {
>         upvar dg-do-what dg-do-what
> diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
> index 608056e5068e..481f81711074 100644
> --- a/libstdc++-v3/testsuite/lib/libstdc++.exp
> +++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
> @@ -1221,6 +1221,41 @@ proc check_v3_target_thread_fence { } {
>      }]
>  }
>
> +proc check_v3_target_atomic_exchange { } {
> +    return [check_v3_target_prop_cached et_atomic_exchange {
> +       global cxxflags
> +       global DEFAULT_CXXFLAGS
> +
> +       # Set up and link a C++11 test program that depends
> +       # on atomic exchange be available for "int".
> +       set src atomic_exchange[pid].cc
> +
> +       set f [open $src "w"]
> +       puts $f "
> +        int i, j, k;
> +       int main() {
> +       __atomic_exchange (&i, &j, &k, __ATOMIC_SEQ_CST);
> +       return 0;
> +       }"
> +       close $f
> +
> +       set cxxflags_saved $cxxflags
> +       set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -Werror -std=gnu++11"
> +
> +       set lines [v3_target_compile $src /dev/null executable ""]
> +       set cxxflags $cxxflags_saved
> +       file delete $src
> +
> +       if [string match "" $lines] {
> +           # No error message, linking succeeded.
> +           return 1
> +       } else {
> +           verbose "check_v3_target_atomic_exchange: compilation failed" 2
> +           return 0
> +       }
> +    }]
> +}
> +
>  # Return 1 if atomics_bool and atomic_int are always lock-free, 0 otherwise.
>  proc check_v3_target_atomic_builtins { } {
>      return [check_v3_target_prop_cached et_atomic_builtins {
> --
> 2.30.2
>
>
> >
> > Thanks,
> >
> > Christophe
> >
> >
> > Ok to commit?
> > >
> > > -- >8 --
> > > Make __atomic_test_and_set consistent with other __atomic_ and __sync_
> > > builtins: call a matching library function instead of emitting
> > > non-atomic code when the target has no direct insn support.
> > >
> > > There's special-case code handling targetm.atomic_test_and_set_trueval
> > > != 1 trying a modified maybe_emit_sync_lock_test_and_set.  Previously,
> > > if that worked but its matching emit_store_flag_force returned NULL,
> > > we'd segfault later on.  Now that the caller handles NULL, gcc_assert
> > > here instead.
> > >
> > > While the referenced PR:s are ARM-specific, the issue is general.
> > >
> > >         PR target/107567
> > >         PR target/109166
> > >         * builtins.cc (expand_builtin) <case BUILT_IN_ATOMIC_TEST_AND_SET>:
> > >         Handle failure from expand_builtin_atomic_test_and_set.
> > >         * optabs.cc (expand_atomic_test_and_set): When all attempts fail to
> > >         generate atomic code through target support, return NULL
> > >         instead of emitting non-atomic code.  Also, for code handling
> > >         targetm.atomic_test_and_set_trueval != 1, gcc_assert result
> > >         from calling emit_store_flag_force instead of returning NULL.
> > > ---
> > >  gcc/builtins.cc |  5 ++++-
> > >  gcc/optabs.cc   | 22 +++++++---------------
> > >  2 files changed, 11 insertions(+), 16 deletions(-)
> > >
> > > diff --git a/gcc/builtins.cc b/gcc/builtins.cc
> > > index 6e4274bb2a4e..40dfd36a3197 100644
> > > --- a/gcc/builtins.cc
> > > +++ b/gcc/builtins.cc
> > > @@ -8387,7 +8387,10 @@ expand_builtin (tree exp, rtx target, rtx
> > > subtarget, machine_mode mode,
> > >        break;
> > >
> > >      case BUILT_IN_ATOMIC_TEST_AND_SET:
> > > -      return expand_builtin_atomic_test_and_set (exp, target);
> > > +      target = expand_builtin_atomic_test_and_set (exp, target);
> > > +      if (target)
> > > +       return target;
> > > +      break;
> > >
> > >      case BUILT_IN_ATOMIC_CLEAR:
> > >        return expand_builtin_atomic_clear (exp);
> > > diff --git a/gcc/optabs.cc b/gcc/optabs.cc
> > > index 8b96f23aec05..e1898da22808 100644
> > > --- a/gcc/optabs.cc
> > > +++ b/gcc/optabs.cc
> > > @@ -7080,25 +7080,17 @@ expand_atomic_test_and_set (rtx target, rtx mem,
> > > enum memmodel model)
> > >    /* Recall that the legacy lock_test_and_set optab was allowed to do
> > > magic
> > >       things with the value 1.  Thus we try again without trueval.  */
> > >    if (!ret && targetm.atomic_test_and_set_trueval != 1)
> > > -    ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, const1_rtx,
> > > model);
> > > -
> > > -  /* Failing all else, assume a single threaded environment and simply
> > > -     perform the operation.  */
> > > -  if (!ret)
> > >      {
> > > -      /* If the result is ignored skip the move to target.  */
> > > -      if (subtarget != const0_rtx)
> > > -        emit_move_insn (subtarget, mem);
> > > +      ret = maybe_emit_sync_lock_test_and_set (subtarget, mem,
> > > const1_rtx, model);
> > >
> > > -      emit_move_insn (mem, trueval);
> > > -      ret = subtarget;
> > > +      if (ret)
> > > +       {
> > > +         /* Rectify the not-one trueval.  */
> > > +         ret = emit_store_flag_force (target, NE, ret, const0_rtx, mode,
> > > 0, 1);
> > > +         gcc_assert (ret);
> > > +       }
> > >      }
> > >
> > > -  /* Recall that have to return a boolean value; rectify if trueval
> > > -     is not exactly one.  */
> > > -  if (targetm.atomic_test_and_set_trueval != 1)
> > > -    ret = emit_store_flag_force (target, NE, ret, const0_rtx, mode, 0, 1);
> > > -
> > >    return ret;
> > >  }
> > >
> > > --
> > > 2.30.2
> > >
> > >
> >
>
  

Patch

diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp
index 84ad0c65330b..b13c2f244c63 100644
--- a/libstdc++-v3/testsuite/lib/dg-options.exp
+++ b/libstdc++-v3/testsuite/lib/dg-options.exp
@@ -133,6 +133,15 @@  proc dg-require-thread-fence { args } {
     return
 }
 
+proc dg-require-atomic-exchange { args } {
+    if { ![ check_v3_target_atomic_exchange ] } {
+	upvar dg-do-what dg-do-what
+	set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+	return
+    }
+    return
+}
+
 proc dg-require-atomic-builtins { args } {
     if { ![ check_v3_target_atomic_builtins ] } {
 	upvar dg-do-what dg-do-what
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 608056e5068e..481f81711074 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -1221,6 +1221,41 @@  proc check_v3_target_thread_fence { } {
     }]
 }
 
+proc check_v3_target_atomic_exchange { } {
+    return [check_v3_target_prop_cached et_atomic_exchange {
+	global cxxflags
+	global DEFAULT_CXXFLAGS
+
+	# Set up and link a C++11 test program that depends
+	# on atomic exchange be available for "int".
+	set src atomic_exchange[pid].cc
+
+	set f [open $src "w"]
+	puts $f "
+        int i, j, k;
+	int main() {
+	__atomic_exchange (&i, &j, &k, __ATOMIC_SEQ_CST);
+	return 0;
+	}"
+	close $f
+
+	set cxxflags_saved $cxxflags
+	set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -Werror -std=gnu++11"
+
+	set lines [v3_target_compile $src /dev/null executable ""]
+	set cxxflags $cxxflags_saved
+	file delete $src
+
+	if [string match "" $lines] {
+	    # No error message, linking succeeded.
+	    return 1
+	} else {
+	    verbose "check_v3_target_atomic_exchange: compilation failed" 2
+	    return 0
+	}
+    }]
+}
+
 # Return 1 if atomics_bool and atomic_int are always lock-free, 0 otherwise.
 proc check_v3_target_atomic_builtins { } {
     return [check_v3_target_prop_cached et_atomic_builtins {