Commit graph

1149 commits

Author SHA1 Message Date
Matt Arsenault
55df598539
libclc: Fix signed 0 handling in sincospi (#211260) 2026-07-23 06:24:44 +02:00
Matt Arsenault
6793bb48ac
libclc: Fix UB in trig functions with nan inputs (#211047) 2026-07-22 06:41:39 +02:00
Petr Hosek
e192ec42b4
[CMake] Warn when the version of CMake is older than 3.31.0 (#204203)
This is a preparation to raise the minimum required CMake version to
3.31.0 in LLVM 24.

See
https://discourse.llvm.org/t/rfc-raising-minimum-required-cmake-version-to-3-31/91086.
2026-06-29 11:16:27 -07:00
Wenju He
89ac672f5b
[libclc] Delete wrong implementation nvptx clc_isinf (#205699)
The file calls __nv_isinf which return 1 for true on vector input, while
the generic clc_isinf which return -1 for true on vector input. Using
nvptx clc_isinf in OpenCL isinf violates OpenCL spec.

Found the issue in https://github.com/intel/llvm/pull/22413
2026-06-25 08:47:23 +08:00
Joseph Huber
cac31111d3
[libclc] Use unchecked division for f64 AMDGPU reciprocal (#203809)
Summary:
This matches what the AMD device libraries does. We can avoid extra
steps by only performing the two steps of the Newton-Raphson
approximation of 1 / x. The exceptional cases should not appear in these
math functions, this is local to AMDGPU, and I verified they are bitwise
identical to the AMD math functions with parity in performance now.
2026-06-15 07:26:32 -05:00
Joseph Huber
303400f080
[libclc] Use __CLC_SCALAR instead of nonexistant __CLC_SCALAR1 for sin (#203807)
Summary:
This seems to be a typo? Every other case is guarded by `__CLC_SCALAR`
but this case had a `1` after it. Removing this improved performance on
sin/cos/tan to match the ROCm version.
2026-06-14 20:33:36 -05:00
Joseph Huber
8b6551e493
[libclc] Use FMA for the pi reconstruction in acos / atan (#203804)
Summary:
This should recombine the split constant for this case. The performance
should be negligible for such large math functions, we get an extra add,
but in exchange the results should improve 1 ULP.

This was primarily done to match what AMD's math libraries do, with this
change we are byte-for-byte identical in output.
2026-06-14 20:32:57 -05:00
Joseph Huber
375b70bafe
[libclc] Improve performance and precision of reciprocal functions (#203805)
Summary:
Small change to improve the performance and output of functions using
the reciprocol. This makes these functions *byte-for-byte* identical
with their OCML counterparts in ROCm.

Additionally ensure tanpi is correctly rounded to match ROCm.
2026-06-14 20:32:00 -05:00
Wenju He
985e49989f
[libclc][Test] Don't hard code clang path in update_libclc_tests.py (#201806)
In #201773, build folder is `redhat-linux-build` rather than `build`.
Detect clang from PATH. Also add --clang-binary option to specify clang path.
2026-06-06 07:18:19 +08:00
Wenju He
e8753fdde7
[libclc][Test] Add -fno-discard-value-names to RUN line (#201808)
Entry block label could be missing. Add -fno-discard-value-names to make
sure it exists.

Resolves #201773
2026-06-06 07:17:55 +08:00
Wenju He
517a0755f5
[libclc] Fix LIBCLC_OUTPUT_LIBRARY_DIR when find_package(LLVM) fails (#201816)
If we configure llvm from llvm-project/build folder, find_package(LLVM)
succeeds, `LLVM_LIBRARY_OUTPUT_INTDIR` is `build/./lib` and
`LLVM_BINARY_DIR` is `build`.

However, in #201773, find_package(LLVM) fails due to
LLVM_LIBDIR_SUFFIX=64, LLVM_LIBRARY_OUTPUT_INTDIR is
`redhat-linux-build/runtimes/runtimes-nvptx64-nvidia-cuda-bins/lib64`
and LLVM_BINARY_DIR is `redhat-linux-build`.

Use LLVM_BINARY_DIR, which is stable for both cases, for libclc output dir.

Fixes #201773
2026-06-06 07:17:42 +08:00
Wenju He
6a7b887615
[libclc] Use generic spirv*-unknown-unknown clang triple for SPIR-V targets (#199618)
spirv-diff shows only numbering change to
spirv64-unknown-unknown/libclc.spv. No change in `llvm-spirv -to-text`
outputs. llvm-diff shows no change on reverse-translated bitcode files.

Also fixes a bug that spirv32-unknown-unknown was incorrectly using
64-bit triple.

Update README.md to use the generic target triple for SPIR-V targets.
2026-06-03 16:01:00 +08:00
michaelselehov
5945eacb93
[libclc][test] Update math/cos.cl check lines after #199981 revert (#200353)
The libclc lit test 'math/cos.cl' (introduced by #197151 with
auto-generated FileCheck assertions) started failing on the staging
buildbot after the revert in #199981 of the AMDGPU ABI coercion change
(#185083). The revert restores the older codegen path, which produces a
slightly different IR shape for the select instruction inside the cos()
implementation:

  - the select's 'contract' fast-math flag is no longer present, and
  - the result is named %.v.i.i instead of a numbered SSA temporary.

Regenerate the AMDGCN CHECK lines with
libclc/test/update_libclc_tests.py to reflect the post-revert IR. After
this change, all 10 libclc tests in check-libclc-amdgcn-amd-amdhsa-llvm
pass.

Note: running update_libclc_tests.py also produces a purely cosmetic
diff in math/rsqrt.cl (it renames a few FileCheck capture names like
META13 to META12 to match the actual metadata indices); those capture
renames are not required for the test to pass and are not included here
to keep the change minimal.

Co-authored-by: mselehov <mselehov@amd.com>
2026-05-29 11:16:27 -07:00
Wenju He
767f01e091
[libclc] Use float sw_fma for spirv*-mesa-mesa3d targets (#199626)
This partially reverts 39f3d72b72, which changes almost all targets to
use __builtin_elementwise_fma.
The same revert was done for clspv in 1d719edd99.

Restore __clc_runtime_has_hw_fma32 so that Mesa can dynamically change
its behavior to enable native fma for specific hardware.

Fixes #198542
2026-05-29 13:28:17 +08:00
Wenju He
9cc6c9375f
[libclc] Optimize and vectorize signbit (#199497)
Replace element-wise scalarizing implementation with bitcast and shift.
For example,
define hidden range(i32 -1, 1) <2 x i32> @_Z7signbitDv2_f(<2 x float>
noundef %0) #0 {
  %2 = bitcast <2 x float> %0 to <2 x i32>
  %3 = extractelement <2 x i32> %2, i64 0
  %4 = lshr i32 %3, 31
  %5 = insertelement <2 x i32> poison, i32 %4, i64 0
  %6 = extractelement <2 x i32> %2, i64 1
  %7 = lshr i32 %6, 31
  %8 = insertelement <2 x i32> %5, i32 %7, i64 1
  %9 = icmp ne <2 x i32> %8, zeroinitializer
  %10 = sext <2 x i1> %9 to <2 x i32>
  ret <2 x i32> %10
}
is changed to:
define hidden noundef range(i32 -1, 1) <2 x i32> @_Z7signbitDv2_f(<2 x
float> noundef %0) #0 {
  %2 = bitcast <2 x float> %0 to <2 x i32>
  %3 = ashr <2 x i32> %2, splat (i32 31)
  ret <2 x i32> %3
}
2026-05-28 08:06:47 +08:00
Wenju He
0de4a8cd41
[libclc] Fix .cl tests in standalone build (#199164)
libclc standalone build puts libclc.bc in ${CMAKE_CURRENT_BINARY_DIR}/
${TARGET_TRIPLE} dir. check-libclc fails because .cl test is looking for
libclc in clang resource dir.
Fix them by adding `--libclc-lib=:{path}` flag for standalone build,
where `path` is path to libclc.bc.
Note: this flag is not used in in-tree build.
2026-05-23 07:30:59 +08:00
Wenju He
05c1a266b8
[libclc][NFC] Use clc/shared/ternary_def.inc for bitselect (#198495)
Delete opencl/lib/generic/relational/bitselect.inc
2026-05-20 09:27:39 +08:00
Wenju He
bf9916a5b0
[libclc][CMake] Use set instead of APPEND for LIBCLC_ARCHS_ALL initialization (#197866) 2026-05-15 17:46:44 +08:00
Wenju He
3d7c5e0bbd
[libclc] Move sources collection into libclc_add_builtin_library, merge opencl library creation into libclc_add_library (#197654)
Merging opencl library creation into libclc_add_library undos part of
change in 14bf8e7.
This simplifies creating different libraries by invoking
libclc_add_library multiple times, without the need of splitting
intermediate library creation and its finalization.

add_subdirectory(clc) and add_subdirectory(opencl) only updates sources
list of existing library target, so it is safe to move inside
libclc_add_builtin_library.
2026-05-15 10:17:35 +08:00
Joseph Huber
f230e44ab8
[libclc] Add optimized DPP scan functions for AMDGPU (#197543)
Summary:
This uses the update_dpp function to efficiently provide scans. DPP
allows for swizzling within a group of 16, so we do four of those,
followed by a permlane on GFX10, or a native DPP shift on GFX9.

 Right now these are not actually used because we do not compile for
 multiple targets yet, but I verified them by setting
 `CMAKE_CLC_FLAGS=mcpu=gfx1030` or similar. The intention is to have
 these waiting as a motivational implementation once we start doing
 variable builds.

 The output is optimal as far as I am aware. Here is the example for
 gfx1030 generation:

 ```asm
_Z28sub_group_scan_inclusive_addi: ; @_Z28sub_group_scan_inclusive_addi
; %bb.0:
	s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
	v_mov_b32_e32 v1, 0
	s_mov_b32 s4, s33
	s_mov_b32 s33, s32
	s_mov_b32 s33, s4
v_add_nc_u32_dpp v0, v0, v0 row_shr:1 row_mask:0xf bank_mask:0xf
bound_ctrl:1
v_add_nc_u32_dpp v0, v0, v0 row_shr:2 row_mask:0xf bank_mask:0xf
bound_ctrl:1
v_add_nc_u32_dpp v0, v0, v0 row_shr:4 row_mask:0xf bank_mask:0xf
bound_ctrl:1
v_add_nc_u32_dpp v0, v0, v0 row_shr:8 row_mask:0xf bank_mask:0xf
bound_ctrl:1
	v_permlanex16_b32 v1, v0, -1, -1
v_add_nc_u32_dpp v0, v1, v0 quad_perm:[0,1,2,3] row_mask:0xa
bank_mask:0xf
	s_setpc_b64 s[30:31]
 ```
2026-05-13 15:26:30 -05:00
Wenju He
f6007cf3ad
[libclc] Move external-funcs.test to static file and use IR checks for .cl tests (#197151)
This PR supercedes #87989.

Moving external-funcs.test to static file simplifies
test/CMakeLists.txt. Static files follows llvm standard lit pattern and
enables fine-grained check of missing symbols in specific libraries.

.cl test files uses %target, %cpu and %check_prefix, which are replaced
with specific values during `ninja check-libclc` or `llvm-lit
build/runtimes/runtimes-${triple}-llvm-bins/libclc/test`. This allows
checking outputs of multiple triples in the same test file.

Add script libclc/test/update_libclc_tests.py, which wraps
utils/update_cc_test_checks.py to update CHECK lines in libclc .cl tests
for a given arch. Example usage:
`libclc/test/update_libclc_tests.py amdgpu`

Assisted-by: Claude Sonnet 4.6

---------

Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
2026-05-13 18:21:36 +08:00
Joseph Huber
9b6e77dfb6
[libclc] Apply hidden visibility to amdgpu / nvptx builds (#197235)
Summary:
    This is not currently used because we force `--internalize` for
llvm-link, but if you ever want to link this normally we'd need hidden
visibility. SPIR-V does not currently handle hidden visibility, as it is
    an extension still under discussion, so it is omitted for now.
2026-05-12 20:29:25 -05:00
Joseph Huber
4106333fe0
[libclc] Create a static .a file in addition to the .bc file (#197247)
Summary:
This changes the libraries to be object libraries instead of static
libraries. We can then just link these into final static libraries that
contain everything we need.

The desire here is that we'd need static libraries if we wanted to move
away from `-mlink-builtin-bitcode` appraoches.

Effectively we'll have `libclc.a` next to `libclc.bc` and the idea is
that we could alternatively link it and let the target linker handle it.
2026-05-12 20:29:06 -05:00
Joseph Huber
9a39c60406
[libclc] Consolidate amdgpu and amdgcn architectures consistently (#197233)
Summary:
Currently we did not pass all checks with amdgpu triple as we did with
amdgcn. SPIR-V set this pattern so let's make it consistent.
2026-05-12 12:20:50 -05:00
Joseph Huber
14bf8e76c0
[libclc] Base the build around add_sources instead of source list (#197034)
Summary:
The current build uses a curated + deduplicated source list. This PR
seeks to simplify this a little bit and canonicalize the behavior.

Now we create the target up-front, `clc` and `opencl`. We add the
directories which add sources to this target. We normalize the
architecture to the variants. We always add target specific versions
first. When we add sources we check if the file already exists and defer
to the architecture specific one.

This normalized the behavior, the directories are now laid out like this
`clc/<arch>/<os>`. We normalize these to `amdgpu`, `nvptx`, and `spirv`
respectively. We use the OS for the newly created vulkan target. We now
control variants via checking if the directory for that exists, so it's
nested more naturally.

Hopefully this makes more sense, the goal is to exercise the fact that
we have individual builds now. Previously this did not work because you
could not add_subdirectory more than once.
2026-05-12 07:04:11 -05:00
Konrad Kleine
363c871c8b
libclc: group spirv archs in LIBCLC_ARCHS_SPIRV (#196911)
This was done do remove repetitive comparisons.
2026-05-11 12:33:44 +02:00
Joseph Huber
6ef9671006
[libclc] Canonicalize 'clspv' to the 'spirv-unknown-vulkan' triple (#196351)
Summary:
The libclc project has clspv support for exporting OpenCL standard
library utilities to Vulkan consumers. This was previously exposed as a
hack into the build system that renamed the triple and relied on macro
defines. Recent changes allowed us to use `vulkan` as an OS for the
spir-V target. This should make the intention more clear and allow the
system to inherit the same triple handling the other targets use.

Tested the build, but I will need @rjodinchr and @alan-baker to verify.
2026-05-08 08:41:58 -05:00
Konrad Kleine
016894861f
[libclc] Use spirv[64]-mesa-mesa3d triple in README.md (#196483)
Now that #194607 landed we use a normalized triple in the README for the
SPIRV targets. Before `spirv-mesa3d-` and `spirv64-mesa3d-` were being
used and those will be normalized to `spirv-unknown-mesa3d` and
`spirv64-unknown-mesa3d` by the following command in
`runtimes/CMakeLists.txt` with this command:

```console
$ clang --target=spirv-mesa3d- -print-target-triple
spirv-unknown-mesa3d
```

This is because in `llvm/lib/TargetParser/Triple.cpp` the term `mesa3d`
is recognized as an OS and placed in third position. The install path
for `libclc.spv` there ends up in `spirv-unknown-mesa3d/libclc.spv`.

With this change we suggest to use triples that "survive" the
normalization:

```console
$ clang --target=spirv-mesa-mesa3d -print-target-triple
spirv-mesa-mesa3d
```

See also this discussion:
https://github.com/llvm/llvm-project/pull/194607#issuecomment-4378126607
2026-05-08 11:18:45 +02:00
Joseph Huber
87d42c13cd
[libclc] Fix using normalized triple for the directory name (#194607)
Summary:
libclc needs to normalize triples, mostly on account of the fact that
things like spv and clspv aren't real triples but are used anyway. That
is, we convert the user-value to whatever is passed to `--target=`. The
problem is that we were not using the normal triple for the installation
directory, so something like `spirv64-mesa32-unknown` would be installed
in `spirv64--`.

This *might* have the side effect of putting these in
`spirv64-unknown-unknown`. I actually do not know if that's a problem
with the clang handling, I'll double check.
2026-05-07 10:40:56 -05:00
Joseph Huber
e7164d4224
[libclc] Only check the triple architecture for libclc (#194149)
Summary:
Previously, `nvptx64--` would reject `nvptx64-unknown-unknown`. Two
options, either normalize all the triples in CMake, or just check the
architecture. I went with the former because it makes it easier for
people to pass different values.
2026-04-25 20:52:20 -05:00
Joseph Huber
eb17a2e19c
[libclc] Make sure PACKAGE_VERSION is set for libclc (#193966)
Summary:
This can be unset because CMake does not expose this as a raw variable
when you use the find_package interface. If it is not set as in the case
of standalone builds the clang resource directory won't be found
2026-04-24 10:41:28 -05:00
Joseph Huber
6c7d16c0bf
[libclc] Use 'LLVM_DEFAULT_TARGET_TRIPLE' instead of 'LLVM_RUNTIMES_TARGET' (#193969)
Summary:
The 'LLVM_RUNTIMES_TARGET' variable is the raw value used by the LLVM
CMake. It can contain multilib arguments which will not compile when
used as a triple. The more canonical value is
`LLVM_DEFAULT_TARGET_TRIPLE`, which is used by flang-rt, libc, openmp,
etc.
2026-04-24 08:54:09 -05:00
Wenju He
969247cc47
[libclc] Allow testing unresolved symbols on multiple libraries (#193647)
Our downstream generates multiple libraries for a single target. This
change allows testing multiple libraries.
2026-04-24 08:46:06 +08:00
Wenju He
f3192382c3
[libclc][CMake] Remove CMAKE_C_COMPILER_ID check (#186717)
When LLVM_TARGETS_TO_BUILD does not contain the host target, runtime
build can not identify a compatible target triple for the host compiler.
CMAKE_C_COMPILER is set to clang, and CMAKE_C_COMPILER_ID is empty
although the compiler is functional.

Remove CMAKE_C_COMPILER_ID check. CMakeTestCLCCompiler.cmake already
provides a real functional guard.

This change ensures valid configurations can proceed, e.g.:
LLVM_TARGETS_TO_BUILD=AMDGPU;
RUNTIMES_amdgcn-amd-amdhsa-llvm_LLVM_ENABLE_RUNTIMES=libclc;
LLVM_RUNTIME_TARGETS="amdgcn-amd-amdhsa-llvm".

Note CMAKE_C_COMPILER_WORKS is always true after `project(Runtimes C CXX
ASM)` in runtimes/CMakeLists.txt.
2026-04-24 08:45:51 +08:00
Victor Mustya
daf814c431
[libclc] Fix atomic_fetch_add/sub overloads for uintptr_t (#192570)
The overloads taking the memory order and/or scope parameters should
have the `_explicit` suffix, according to the OpenCL C specification.
2026-04-16 23:41:51 +00:00
Wenju He
c1fc739b5d
[libclc] Only add test folder when LLVM_INCLUDE_TESTS is ON (#191948) 2026-04-15 08:45:49 +08:00
Wenju He
19d1b348f0
[libclc][CMake][NFC] Delete dead code LLVM_PACKAGE_VERSION (#191943)
Use of LLVM_PACKAGE_VERSION in AddLibclc.cmake was dropped by e20ae16ce6.
2026-04-15 08:45:29 +08:00
Wenju He
18f63d1375
[runtimes] Aggregate per-target runtime checks in top-level check-${runtime_name} (#191743)
When a per-target runtime build exports a
check-${runtime_name}-${target} proxy, make the top-level
check-${runtime_name} target depend on it, creating
check-${runtime_name} on demand (it may not exist).

This applies regardless of whether the runtime comes from the default
LLVM_ENABLE_RUNTIMES set or from a target-specific
RUNTIMES_<target>_LLVM_ENABLE_RUNTIMES override.

This allows a single `check-${runtime_name}` command to trigger all
per-target tests for that runtime.
2026-04-15 08:45:04 +08:00
Wenju He
12f636d442
Revert "[libclc][CMake] Use clang/llvm-ar on Windows (#186726)" (#191745)
This reverts commit 4abb927bac.

The code is not needed since 121f5a96ff because the C compiler is now
always just-built clang in in-tree build. In addition, CMAKE_AR is
llvm-ar and CMAKE_RANLIB is llvm-ranlib.
2026-04-14 10:40:51 +08:00
Wenju He
121f5a96ff
[libclc] Enable LLVM_RUNTIME_TARGETS in build system (#189892)
libclc target is now passed in from LLVM_RUNTIME_TARGETS.

The old configure flow based on `-DLLVM_ENABLE_RUNTIMES=libclc` is
deprecated because libclc no longer has a default target.
`-DLLVM_ENABLE_RUNTIMES=libclc -DLLVM_RUNTIME_TARGETS="<target-triple>"`
still works but it is considered legacy.

The new standard build requires:
Each target must now be selected explicitly on the CMake command line
through the runtimes target-specific cache entry and
LLVM_RUNTIME_TARGETS.
For example:
-DRUNTIMES_amdgcn-amd-amdhsa-llvm_LLVM_ENABLE_RUNTIMES=libclc
-DLLVM_RUNTIME_TARGETS="amdgcn-amd-amdhsa-llvm"
-DRUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES=libclc
-DLLVM_RUNTIME_TARGETS="nvptx64-nvidia-cuda"
-DRUNTIMES_clspv--_LLVM_ENABLE_RUNTIMES=libclc
-DLLVM_RUNTIME_TARGETS="clspv--"
-DRUNTIMES_clspv64--_LLVM_ENABLE_RUNTIMES=libclc
-DLLVM_RUNTIME_TARGETS="clspv64--"
-DRUNTIMES_spirv-mesa3d-_LLVM_ENABLE_RUNTIMES=libclc
-DLLVM_RUNTIME_TARGETS="spirv-mesa3d-"
-DRUNTIMES_spirv64-mesa3d-_LLVM_ENABLE_RUNTIMES=libclc
-DLLVM_RUNTIME_TARGETS="spirv64-mesa3d-"

To build multiple targets, pass them as a semicolon-separated list in
`LLVM_RUNTIME_TARGETS` and provide a matching
`RUNTIMES_<target-triple>_LLVM_ENABLE_RUNTIMES=libclc` entry for each
target.

Updated README.md to document the new build flow.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-13 08:19:08 +08:00
Wenju He
7b94b9ae13
[libclc] Refine generic __clc_get_sub_group_size with fast full sub-group path (#188895)
Add a fast path for the common case that total work-group size is
multiple of max sub-group size.

The fallback path is ported from amdgpu/workitem/clc_get_sub_group_size.cl.

Compiler can generate predicated instructions for the fallback path to
avoid branches.
2026-04-13 08:16:06 +08:00
Matt Arsenault
eed1f2749d
libclc: Use special division for atan2 for DAZ (#190248)
The AMDGPU DAZ fdiv works fine in this case, so there's
maybe something better we could do here.
2026-04-02 22:18:17 +02:00
Matt Arsenault
15bc5b0267
libclc: Simplify fract implementation (#189080) 2026-03-28 00:16:07 +01:00
Wenju He
7be9972cb2
[libclc] Fix llvm-spirv dependency when llvm-spirv is built in-tree (#188896)
When SPIRV-LLVM-Translator is built in-tree (i.e., placed in
llvm/projects folder), llvm-spirv target exists.

Drop legacy llvm-spirv_target dependency (was for non-runtime build) and
add llvm-spirv to runtimes dependencies.
2026-03-28 07:06:23 +08:00
Romaric Jodin
e0a1e78738
libclc: do not use int64 in sincos helpers (#188056)
int64 is optional, thus we do not want to force its usage for clspv.
2026-03-27 18:36:31 +08:00
Matt Arsenault
35781a7d43
libclc: Partially implement nonuniform subgroup reduce functions (#188929)
For AMDGPU these are identical to the uniform case. Stub out the missing
cases with traps to avoid test failures from undefined symbols while
keeping the structure consistent.
2026-03-27 09:47:44 +00:00
Matt Arsenault
56e1510d21
libclc: Add work group scan functions (#188829) 2026-03-27 09:53:35 +01:00
Matt Arsenault
1a32a4185b
libclc: Add subgroup scan functions (#188828)
Add the base implementation using ds_swizzle which should work
on all subtargets. There are at least 2 more paths available for
newer targets.
2026-03-27 09:37:27 +01:00
Matt Arsenault
8430e9e8f0
libclc: Update atan2pi (#188707)
This was originally ported from rocm device libs in
37406a209c. Merge in more
recent changes.
2026-03-27 08:59:00 +01:00
Matt Arsenault
8e9e9228d4
libclc: Fix missing overloads for atomic_fetch_add/sub (#188478) 2026-03-27 08:27:36 +01:00