From: Matthew Malcomson <mmalcom...@nvidia.com>

N.b. including docs maintainers to ask about whether this flag should be
documented in invoke.texi -- I suspect that would be determined partly
based on the feedback I get on this patch about whether it should be
something mostly for the testsuite and otherwise internally derived
based on other factors or whether it should be something available for a
user to adjust directly.

-------------- >8 ------- 8< -----------
As it stands the floating point exception handling needs to include
libatomic.  I plan to include libatomic by default when compiling as per
PR/81358.  However even that won't help when a target has no libatomic.

Bare metal cross compilers get built without libatomic often.  Rather
than disable this feature for bare metal targets we provide a fallback
through a command line argument that allows disabling the emition of
floating point exception handling code in calls to __atomic_fetch_add
and similar.

This is also useful for the testsuite, since it enables more testing of
this feature on targets which have not built libatomic.

N.b. I would appreciate any feedback about how one should handle such a
situation when working with C11 _Atomic types.  They have the same
problem that they require libatomic and sometimes libatomic is not
available.  Is this just something that will stay as a known limitation
for certain platforms?  Is there something in the works to make it more
viable?

Similarly I would open the question up to others about whether it seems
sensible to turn this flag on by default when the compiler is configured
with `--disable-libatomic`.  I'm not confident on that since I don't
know how often people disable building libatomic and instead test
against a system libatomic.

gcc/c-family/ChangeLog:

        * c-common.cc (atomic_alttyped_fetch_using_cas_loop): Avoid
        emitting floating point exception handling code if new flag
        given.
        * c.opt: Introduce new -fatomic-fp-fetchop-exceptions flag.

gcc/testsuite/ChangeLog:

        * gcc.dg/atomic-op-fp.c: Use new flag to avoid requiring
        libatomic when libatomic is not available.
        * gcc.dg/atomic-op-fpf.c: Likewise.
        * gcc.dg/atomic-op-fpf128.c: Likewise.
        * gcc.dg/atomic-op-fpf16.c: Likewise.
        * gcc.dg/atomic-op-fpf16b.c: Likewise.
        * gcc.dg/atomic-op-fpf32.c: Likewise.
        * gcc.dg/atomic-op-fpf32x.c: Likewise.
        * gcc.dg/atomic-op-fpf64.c: Likewise.
        * gcc.dg/atomic-op-fpf64x.c: Likewise.
        * gcc.dg/atomic-op-fpl.c: Likewise.
        * gcc.dg/atomic-op-fp-fenv-flag.c: New test.

Signed-off-by: Matthew Malcomson <mmalcom...@nvidia.com>
---
 gcc/c-family/c-common.cc                      |  2 +-
 gcc/c-family/c.opt                            |  6 +++
 gcc/testsuite/gcc.dg/atomic-op-fp-fenv-flag.c | 44 +++++++++++++++++++
 gcc/testsuite/gcc.dg/atomic-op-fp.c           |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf.c          |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf128.c       |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf16.c        |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf16b.c       |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf32.c        |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf32x.c       |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf64.c        |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpf64x.c       |  1 +
 gcc/testsuite/gcc.dg/atomic-op-fpl.c          |  1 +
 13 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/atomic-op-fp-fenv-flag.c

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 17bdcbfedc3..50c177da4cd 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -8409,7 +8409,7 @@ atomic_alttyped_fetch_using_cas_loop (location_t loc,
   bool need_fenv
     = (flag_trapping_math && SCALAR_FLOAT_TYPE_P (nonatomic_lhs_type));
   tree hold_call = NULL_TREE, clear_call = NULL_TREE, update_call = NULL_TREE;
-  if (need_fenv)
+  if (need_fenv && flag_atomic_fp_fetchop_exceptions)
     targetm.atomic_assign_expand_fenv (&hold_call, &clear_call, &update_call);
   if (hold_call)
     add_stmt (hold_call);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 47d6f083ffe..6fc66a3bfe7 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1682,6 +1682,12 @@ fasm
 C ObjC C++ ObjC++ Var(flag_no_asm, 0)
 Recognize the \"asm\" keyword.
 
+fatomic-fp-fetchop-exceptions
+C C++ Var(flag_atomic_fp_fetchop_exceptions) Init(1)
+Choose whether __atomic_fetch_add, __atomic_fetch_sub, __atomic_add_fetch, and
+__atomic_sub_fetch on floating point types handle floating point exceptions.
+This requires linking against libatomic.
+
 ; Define extra predefined macros for use in libgcc.
 fbuilding-libgcc
 C ObjC C++ ObjC++ Undocumented Var(flag_building_libgcc)
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fp-fenv-flag.c 
b/gcc/testsuite/gcc.dg/atomic-op-fp-fenv-flag.c
new file mode 100644
index 00000000000..1bb0ea4a26b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic-op-fp-fenv-flag.c
@@ -0,0 +1,44 @@
+/* Test that atomic floating point fetch routines do not emit code to handle
+   floating point exception information when expanding to a CAS loop *if* flag
+   specifically to avoid this is provided.
+   Usually one would want to have this behaviour, but if libatomic is not
+   available then disabling it seems reasonable.  Hence providing a flag to
+   allow disabling. */
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" } */
+
+extern volatile float vf, count_f;
+extern volatile double vd, count_d;
+extern volatile long double vld, count_ld;
+
+float
+test_fetch_add_float (float ret)
+{
+  ret += __atomic_fetch_add (&vf, count_f, __ATOMIC_SEQ_CST);
+  ret += __atomic_add_fetch (&vf, count_f, __ATOMIC_SEQ_CST);
+  ret += __atomic_fetch_sub (&vf, count_f, __ATOMIC_SEQ_CST);
+  ret += __atomic_sub_fetch (&vf, count_f, __ATOMIC_SEQ_CST);
+  return ret;
+}
+
+double
+test_fetch_add_double (float ret)
+{
+  ret += __atomic_fetch_add (&vd, count_d, __ATOMIC_SEQ_CST);
+  ret += __atomic_add_fetch (&vd, count_d, __ATOMIC_SEQ_CST);
+  ret += __atomic_fetch_sub (&vd, count_d, __ATOMIC_SEQ_CST);
+  ret += __atomic_sub_fetch (&vd, count_d, __ATOMIC_SEQ_CST);
+  return ret;
+}
+
+long double
+test_fetch_add_long_double (float ret)
+{
+  ret += __atomic_fetch_add (&vld, count_ld, __ATOMIC_SEQ_CST);
+  ret += __atomic_add_fetch (&vld, count_ld, __ATOMIC_SEQ_CST);
+  ret += __atomic_fetch_sub (&vld, count_ld, __ATOMIC_SEQ_CST);
+  ret += __atomic_sub_fetch (&vld, count_ld, __ATOMIC_SEQ_CST);
+  return ret;
+}
+
+/* { dg-final { scan-assembler-not "__atomic_feraiseexcept" } } */
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fp.c 
b/gcc/testsuite/gcc.dg/atomic-op-fp.c
index 1477dbed058..9947bb91f96 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fp.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fp.c
@@ -3,6 +3,7 @@
 /* { dg-do run } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_double_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 
 /* Test the execution of the __atomic_*OP builtin routines for a double.  */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf.c
index 467fc1348f5..2a88d0a00fd 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf.c
@@ -3,6 +3,7 @@
 /* { dg-do run } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_float_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 
 /* Test the execution of the __atomic_*OP builtin routines for a float.  */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf128.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf128.c
index 86f6ab39565..abf5a1855da 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf128.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf128.c
@@ -4,6 +4,7 @@
 /* { dg-additional-options "-std=c23" } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_float128_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 /* { dg-require-effective-target float128_runtime } */
 /* { dg-add-options float128 } */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf16.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf16.c
index 81b54d819dd..375fdce8c9f 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf16.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf16.c
@@ -4,6 +4,7 @@
 /* { dg-additional-options "-std=c23" } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_float16_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 /* { dg-require-effective-target float16_runtime } */
 /* { dg-add-options float16 } */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf16b.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf16b.c
index 0ff38878d5a..13dfd9b0ac2 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf16b.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf16b.c
@@ -4,6 +4,7 @@
 /* { dg-additional-options "-std=c23" } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_bfloat16_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 /* { dg-require-effective-target bfloat16_runtime } */
 /* { dg-add-options bfloat16 } */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf32.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf32.c
index 29e59dc98c7..d9a89467a88 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf32.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf32.c
@@ -4,6 +4,7 @@
 /* { dg-additional-options "-std=c23" } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_float32_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 /* { dg-require-effective-target float32_runtime } */
 /* { dg-add-options float32 } */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf32x.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf32x.c
index 32526732846..296e34342b5 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf32x.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf32x.c
@@ -4,6 +4,7 @@
 /* { dg-additional-options "-std=c23" } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_float32x_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 /* { dg-require-effective-target float32x_runtime } */
 /* { dg-add-options float32x } */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf64.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf64.c
index be75f7c06b5..a4dbcad89b6 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf64.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf64.c
@@ -4,6 +4,7 @@
 /* { dg-additional-options "-std=c23" } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_float64_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 /* { dg-require-effective-target float64_runtime } */
 /* { dg-add-options float64 } */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpf64x.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpf64x.c
index 89ee198dfd2..6d059e32bd5 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpf64x.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpf64x.c
@@ -4,6 +4,7 @@
 /* { dg-additional-options "-std=c23" } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_float64x_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 /* { dg-require-effective-target float64x_runtime } */
 /* { dg-add-options float64x } */
 
diff --git a/gcc/testsuite/gcc.dg/atomic-op-fpl.c 
b/gcc/testsuite/gcc.dg/atomic-op-fpl.c
index 06429855ae4..d311b76c215 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-fpl.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-fpl.c
@@ -3,6 +3,7 @@
 /* { dg-do run } */
 /* Can use fallback if libatomic is available, otherwise need hardware 
support.  */
 /* { dg-require-effective-target sync_long_double_runtime { target { ! 
libatomic_available } } } */
+/* { dg-additional-options "-fno-atomic-fp-fetchop-exceptions" { target { ! 
libatomic_available } } } */
 
 /* Test the execution of the __atomic_*OP builtin routines for a long double.  
*/
 
-- 
2.43.0

Reply via email to