[PATCH 0/8] Implement integer atomic fetch min/max in GCC
Soumya AR
soumyaa@nvidia.com
Tue Sep 2 09:01:40 GMT 2025
Really sorry for the re-ping, but my other patches got blocked by the mailing
list. Wasn't sure if it made it to your inbox, so sending again.
> On 2 Sep 2025, at 12:03 PM, soumyaa@nvidia.com wrote:
>
> External email: Use caution opening links or attachments
>
>
> From: Soumya AR <soumyaa@nvidia.com>
>
> Hi,
>
> This patch series implements support for integer atomic fetch min/max operations
> in GCC, backing the C++26 std::atomic<int>::fetch_max and
> std::atomic<int>::fetch_min operations.
>
> CC'ed in: The following maintainers according to parts of the compiler modified
>
> - middle-end maintainers: Patches 1-4 involve several tweaks in the middle-end.
> So do parts of Patch 8.
> - runtime library maintainers: Patch 5 (extends libatomic) and Patch 7
> (extends libstdc++).
> - aarch64 maintainers: Patch 6 (extends aarch64 backend).
> - Patch 8 extends various compiler components to handle atomic fetch min/max
> CC'ing David Malcolm and Jakub Jelinek for analyzer and asan modifications
> respectively.
> CC'ing Andrew MacLeod for tree-ssa modifications.
> - Additionally including some contributors who have contributed to similar
> relevant areas.
>
> Please let me know if there would be anyone else appropriate to CC for this.
>
> I've highlighted key changes from each patch below, but kindly do read through
> the commit messages for each patch for more information.
>
> ---
>
> 1. builtin: Add builtin types and function declarations for integer atomic fetch
> min/max
>
> At RTL level, we distinguish between signed and unsigned min/max operations
> based on the optab: SMIN/SMAX or UMIN/UMAX.
>
> To model the same behaviour at a builtin level, we define:
> BUILT_IN_ATOMIC_FETCH_MIN_N, BUILT_IN_ATOMIC_FETCH_MAX_N,
> BUILT_IN_ATOMIC_MIN_FETCH_N, BUILT_IN_ATOMIC_MAX_FETCH_N,
> BUILT_IN_ATOMIC_FETCH_{S,U}MIN_N, BUILT_IN_ATOMIC_FETCH_{S,U}MAX_N,
> BUILT_IN_ATOMIC_{S,U}MIN_FETCH_N, BUILT_IN_ATOMIC_{S,U}MAX_FETCH_N
> and the sized variants for the signed builtins.
>
> ---
>
> 2. optabs: Add sync optabs for atomic min/max operations
>
> Adds optab definitions for both legacy __sync and __atomic min/max operations.
>
> Rather than adding special clauses for the case where these optabs for the
> legacy builtins do not exist, we define optabs for all operations and rely on
> existing mechanisms to check whether these optabs are implemented or not.
>
> This means that although unlikely, if backends do implement these optabs, they
> should work correctly.
>
> ---
>
> 3. c,c++: Expand atomic min/max builtins to CAS loops
>
> When handling atomic builtins, we handle fetch_after variants as fetch_before
> OP val. To issue this compensation code, we call expand_simple_binop(), which
> calls expand_binop().
>
> Therefore, expand_binop() is extended to handle min/max operations, either via a
> conditional move or a compare and branch sequence. To do this, we migrate the
> code from expand_expr_real_2() to expand_binop() for min/max operations.
>
> ---
>
> 4. middle-end + aarch64: Sanity tests for atomic min/max operations
>
> Regression tests for the above CAS implementation (tested via aarch64).
> Additionally, gcc.dg/atomic-op-*.c tests are also extended with min/max for
> target independent tests.
>
> ---
>
> 5. libatomic: Add support for atomic fetch min/max builtins
>
> We implement __atomic_fetch_{min,max} and __atomic_{min,max}_fetch operations in
> libatomic for both signed and unsigned integer types.
>
> This patch takes significant design decisions which are highlighted in more
> detail in the patch.
>
> - We introduce STYPE for signed operations alongside the existing UTYPE, with
> BUILTIN_TYPE resolving to the appropriate type based on the operation.
> - Extend DECLARE_ALL_SIZED macro to handle both signed and unsigned types.
> - Some tweaks in fop_n.c to make fallbacks work for min/max.
>
> IMP: Note that the naming convention used for libcalls in this change
> (__atomic_fetch_{s,u}min/max_<size>) was also coordinated with LLVM community.
>
> ---
>
> 6. aarch64: Add backend support for atomic fetch min/max operations
>
> This patch adds aarch64 support for atomic min/max operations via the following
> execution paths.
>
> - LSE inline: When LSE is available at compile time, emits native atomic min/max
> instructions (ldsmin, ldsmax, ldumin, ldumax).
> - Outline atomics: Runtime CPU feature detection via libgcc functions that
> dispatch to either LSE instructions or LL/SC sequences.
> - Inline LL/SC: When outline atomics are disabled (-mno-outline-atomics) on
> non-LSE target, emits inline load-exclusive/store-exclusive sequences.
>
> ---
>
> 7. libstdc++: Use new atomic fetch min/max builtins in std::atomic
>
> Enables C++26's atomic min/max operations in libstdc++ through the newly added
> compiler builtins.
>
> We use concepts to follow the same pattern as existing atomic_fetch_add/sub
> operations.
>
> IMP: These functions are currently not guarded by C++26 feature checks, how
> should we implement this?
>
> ---
>
> 8. middle-end: Extend compiler infrastructure for atomic min/max builtins
>
> - Extendend asan, gimple-ssa-warn, and analyzer for atomic min/max.
> - The analyzer currently doesn't recognize ternary ops as MIN_EXPR/MAX_EXPR, so
> analyzer tests use constants to verify correct min/max computation in memory.
> - tsan emits unsupported warnings for atomic min/max
> - tree-ssa-forwprop optimizes __atomic_fetch_min/max followed by min/max
> to the more efficient __atomic_min/max_fetch when the old value isn't needed.
>
> ---
>
> Testing:
>
> Bootstrapped and regression tested on x86_64 and AArch64.
> Cross compiler regression tested on arm-linux.
> Cross compiler regression tested on AArch64 linux with Qemu emulating a
> machine that does not have LSE.
>
> ---
>
> Soumya AR (8):
> builtin: Add builtin types and function declarations for integer
> atomic fetch min/max
> optabs: Add sync optabs for atomic min/max operations
> c,c++: Expand atomic min/max builtins to CAS loops
> middle-end + aarch64: Sanity tests for atomic min/max operations
> libatomic: Add support for atomic fetch min/max builtins
> aarch64: Add backend support for atomic fetch min/max operations
> libstdc++: Use new atomic fetch min/max builtins in std::atomic
> middle-end: Extend compiler infrastructure for atomic min/max builtins
>
> gcc/analyzer/kf.cc | 85 +++++
> gcc/asan.cc | 40 ++
> gcc/builtin-types.def | 11 +
> gcc/builtins.cc | 116 ++++++
> gcc/c-family/c-common.cc | 50 +++
> gcc/config/aarch64/aarch64-protos.h | 4 +
> gcc/config/aarch64/aarch64.cc | 51 +++
> gcc/config/aarch64/atomics.md | 54 ++-
> gcc/config/aarch64/iterators.md | 30 +-
> gcc/expr.cc | 88 +----
> gcc/fortran/types.def | 11 +
> gcc/gimple-ssa-warn-access.cc | 8 +
> gcc/optabs.cc | 143 ++++++-
> gcc/optabs.def | 24 ++
> gcc/sync-builtins.def | 164 ++++++++
> .../c-c++-common/asan/atomic-max-invalid.c | 19 +
> gcc/testsuite/gcc.dg/Wstringop-overflow-78.c | 106 ++++++
> .../gcc.dg/analyzer/atomic-builtins-1.c | 207 ++++++++++
> gcc/testsuite/gcc.dg/atomic-op-1.c | 353 +++++++++++++++++
> gcc/testsuite/gcc.dg/atomic-op-2.c | 353 +++++++++++++++++
> gcc/testsuite/gcc.dg/atomic-op-3.c | 353 +++++++++++++++++
> gcc/testsuite/gcc.dg/atomic-op-4.c | 353 +++++++++++++++++
> gcc/testsuite/gcc.dg/atomic-op-5.c | 355 ++++++++++++++++++
> .../gcc.dg/tree-ssa/atomic-minmax-forwprop.c | 56 +++
> gcc/testsuite/gcc.dg/tsan/atomic-minmax.c | 48 +++
> .../gcc.target/aarch64/atomic-minmax-lse.c | 122 ++++++
> .../gcc.target/aarch64/atomic-minmax-nolse.c | 196 ++++++++++
> .../gcc.target/aarch64/atomic-minmax.c | 128 +++++++
> .../gcc.target/aarch64/atomic-minmax.x | 185 +++++++++
> gcc/tree-ssa-forwprop.cc | 7 +
> gcc/tsan.cc | 56 ++-
> libatomic/Makefile.am | 3 +-
> libatomic/Makefile.in | 4 +-
> libatomic/acinclude.m4 | 19 +
> libatomic/auto-config.h.in | 33 +-
> libatomic/config/linux/aarch64/atomic_16.S | 126 +++++++
> libatomic/configure | 346 +++++++++++++++++
> libatomic/configure.ac | 1 +
> libatomic/fop_n.c | 118 +++++-
> libatomic/fsmax_n.c | 29 ++
> libatomic/fsmin_n.c | 29 ++
> libatomic/fumax_n.c | 28 ++
> libatomic/fumin_n.c | 28 ++
> libatomic/libatomic.map | 44 +++
> libatomic/libatomic_i.h | 26 +-
> libatomic/testsuite/libatomic.c/atomic-op-1.c | 353 +++++++++++++++++
> libatomic/testsuite/libatomic.c/atomic-op-2.c | 353 +++++++++++++++++
> libatomic/testsuite/libatomic.c/atomic-op-3.c | 353 +++++++++++++++++
> libatomic/testsuite/libatomic.c/atomic-op-4.c | 353 +++++++++++++++++
> libatomic/testsuite/libatomic.c/atomic-op-5.c | 355 ++++++++++++++++++
> libgcc/config/aarch64/lse.S | 62 ++-
> libgcc/config/aarch64/t-lse | 3 +-
> libstdc++-v3/include/bits/atomic_base.h | 156 ++++++++
> .../include/c_compatibility/stdatomic.h | 4 +
> libstdc++-v3/include/std/atomic | 52 +++
> .../atomic_integral/fetch_minmax.cc | 163 ++++++++
> .../atomic_integral/fetch_minmax_order.cc | 111 ++++++
> .../29_atomics/atomic_integral/nonmembers.cc | 24 ++
> .../29_atomics/atomic_ref/integral.cc | 51 ++-
> .../headers/stdatomic.h/c_compat.cc | 4 +
> 60 files changed, 6874 insertions(+), 133 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/asan/atomic-max-invalid.c
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/atomic-minmax-forwprop.c
> create mode 100644 gcc/testsuite/gcc.dg/tsan/atomic-minmax.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax-lse.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax-nolse.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax.x
> create mode 100644 libatomic/fsmax_n.c
> create mode 100644 libatomic/fsmin_n.c
> create mode 100644 libatomic/fumax_n.c
> create mode 100644 libatomic/fumin_n.c
> create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_integral/fetch_minmax.cc
> create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_integral/fetch_minmax_order.cc
>
> --
> 2.44.0
>
More information about the Libstdc++
mailing list