Files
TheRock/rocm-systems/projects/hip-tests/catch/unit/atomics/atomic_builtin_kernels.cc
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

442 lines
21 KiB
C++

/*
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
*
* SPDX-License-Identifier: MIT
*/
#include <hip_test_common.hh>
constexpr int kMemOrder = __ATOMIC_RELAXED;
constexpr int kMemScope = __HIP_MEMORY_SCOPE_SYSTEM;
// Trivially-copyable class.
class DummyTC {
public:
__device__ DummyTC() {}
__device__ ~DummyTC() = default;
__device__ DummyTC(const DummyTC&) = default;
__device__ DummyTC& operator=(const DummyTC&) = default;
__device__ DummyTC(DummyTC&&) = default;
__device__ DummyTC& operator=(DummyTC&&) = default;
};
class Dummy {
public:
__device__ Dummy() {}
__device__ ~Dummy() {}
};
__global__ void StoreCompileKernel(int* x) {
// Valid combinations
__hip_atomic_store(x, 1, __ATOMIC_RELAXED, kMemScope);
__hip_atomic_store(x, 1, __ATOMIC_RELEASE, kMemScope);
__hip_atomic_store(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
__hip_atomic_store(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
__hip_atomic_store(*x, 1, kMemOrder, kMemScope);
// Consume not allowed by C++1 for store
__hip_atomic_store(x, 1, __ATOMIC_CONSUME, kMemScope);
// Acquire not allowed by C++11 for store
__hip_atomic_store(x, 1, __ATOMIC_ACQUIRE, kMemScope);
// Acquire-Release not allowed by C++11 for store
__hip_atomic_store(x, 1, __ATOMIC_ACQ_REL, kMemScope);
// Memory order is out of bounds
__hip_atomic_store(x, 1, -1, kMemScope);
__hip_atomic_store(x, 1, 10, kMemScope);
// Memory scope is out of bounds
__hip_atomic_store(x, 1, kMemOrder, -1);
__hip_atomic_store(x, 1, kMemOrder, 10);
// Storing an object that is not trivially-copyable
Dummy dummy_a{};
Dummy dummy_b{};
__hip_atomic_store(&dummy_a, dummy_b, kMemOrder, kMemScope);
// Storing an object that is trivially-copyable
DummyTC dummytc_a{};
DummyTC dummytc_b{};
__hip_atomic_store(&dummytc_a, dummytc_b, kMemOrder, kMemScope);
}
__global__ void LoadCompileKernel(int* x, int* y) {
// Valid combinations
*y = __hip_atomic_load(x, __ATOMIC_RELAXED, kMemScope);
*y = __hip_atomic_load(x, __ATOMIC_CONSUME, kMemScope);
*y = __hip_atomic_load(x, __ATOMIC_ACQUIRE, kMemScope);
*y = __hip_atomic_load(x, __ATOMIC_SEQ_CST, kMemScope);
// Value instead of pointer to the atomic builtin for 1st parameter
*y = __hip_atomic_load(*x, kMemOrder, kMemScope);
// Release not allowed by C++11 for load
*y = __hip_atomic_load(x, __ATOMIC_RELEASE, kMemScope);
// Acquire-Release not allowed by C++11 for load
*y = __hip_atomic_load(x, __ATOMIC_ACQ_REL, kMemScope);
// Memory order is out of bounds
*y = __hip_atomic_load(x, -1, kMemScope);
*y = __hip_atomic_load(x, 10, kMemScope);
// Memory scope is out of bounds
*y = __hip_atomic_load(x, kMemOrder, -1);
*y = __hip_atomic_load(x, kMemOrder, 10);
// Loading an object that is not trivially-copyable
Dummy dummy_a{};
Dummy dummy_b{};
dummy_a = __hip_atomic_load(&dummy_b, kMemOrder, kMemScope);
// Loading an object that is trivially-copyable
DummyTC dummytc_a{};
DummyTC dummytc_b{};
dummytc_a = __hip_atomic_load(&dummytc_b, kMemOrder, kMemScope);
}
__global__ void CompareWeakCompileKernel(int* x, int* expected) {
bool res{false};
// Valid combinations
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_CONSUME, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_CONSUME, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_ACQUIRE, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_RELEASE, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_ACQ_REL, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_ACQ_REL,
kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST,
kMemScope);
// Release not allowed on fail by C++11
res = __hip_atomic_compare_exchange_weak(x, expected, 1, kMemOrder, __ATOMIC_RELEASE, kMemScope);
// Acquire-Release not allowed on fail by C++11
res = __hip_atomic_compare_exchange_weak(x, expected, 1, kMemOrder, __ATOMIC_ACQ_REL, kMemScope);
// Fail stronger than success
res = __hip_atomic_compare_exchange_weak(x, expected, 1, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST,
kMemScope);
// Pointer to a non-const type
res = __hip_atomic_compare_exchange_weak(reinterpret_cast<const int*>(x), expected, 1, kMemOrder,
kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
res = __hip_atomic_compare_exchange_weak(*x, expected, 1, kMemOrder, kMemOrder, kMemScope);
// Memory order on success is out of bounds
res = __hip_atomic_compare_exchange_weak(x, expected, 1, -1, kMemOrder, kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, 10, kMemOrder, kMemScope);
// Memory order on failure is out of bounds
res = __hip_atomic_compare_exchange_weak(x, expected, 1, kMemOrder, -1, kMemScope);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, kMemOrder, 10, kMemScope);
// Memory scope is out of bounds
res = __hip_atomic_compare_exchange_weak(x, expected, 1, kMemOrder, kMemOrder, -1);
res = __hip_atomic_compare_exchange_weak(x, expected, 1, kMemOrder, kMemOrder, 10);
// User-defined class is not trivially-copyable and therefore cannot be atomically copied
Dummy dummy_a{};
Dummy dummy_b{};
Dummy dummy_c{};
res = __hip_atomic_compare_exchange_weak(&dummy_a, &dummy_b, dummy_c, kMemOrder, kMemOrder,
kMemScope);
// User-defined class is trivially-copyable and can be atomically copied
DummyTC dummytc_a{};
DummyTC dummytc_b{};
DummyTC dummytc_c{};
res = __hip_atomic_compare_exchange_weak(&dummytc_a, &dummytc_b, dummytc_c, kMemOrder, kMemOrder,
kMemScope);
}
__global__ void CompareStrongCompileKernel(int* x, int* expected) {
bool res{false};
// Valid combinations
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_CONSUME, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_CONSUME, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_ACQUIRE, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_RELEASE, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_ACQ_REL, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_CONSUME,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_ACQ_REL,
kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST,
kMemScope);
// Release not allowed on fail by C++11
res =
__hip_atomic_compare_exchange_strong(x, expected, 1, kMemOrder, __ATOMIC_RELEASE, kMemScope);
// Acquire-Release not allowed on fail by C++11
res =
__hip_atomic_compare_exchange_strong(x, expected, 1, kMemOrder, __ATOMIC_ACQ_REL, kMemScope);
// Fail stronger than success
res = __hip_atomic_compare_exchange_strong(x, expected, 1, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST,
kMemScope);
// Pointer to a non-const type
res = __hip_atomic_compare_exchange_strong(reinterpret_cast<const int*>(x), expected, 1,
kMemOrder, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin for 1st parameter
res = __hip_atomic_compare_exchange_strong(*x, expected, 1, kMemOrder, kMemOrder, kMemScope);
// Memory order on success is out of bounds
res = __hip_atomic_compare_exchange_strong(x, expected, 1, -1, kMemOrder, kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, 10, kMemOrder, kMemScope);
// Memory order on failure is out of bounds
res = __hip_atomic_compare_exchange_strong(x, expected, 1, kMemOrder, -1, kMemScope);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, kMemOrder, 10, kMemScope);
// Memory scope is out of bounds
res = __hip_atomic_compare_exchange_strong(x, expected, 1, kMemOrder, kMemOrder, -1);
res = __hip_atomic_compare_exchange_strong(x, expected, 1, kMemOrder, kMemOrder, 10);
// User-defined class is not trivially-copyable and therefore cannot be atomically copied
Dummy dummy_a{};
Dummy dummy_b{};
Dummy dummy_c{};
res = __hip_atomic_compare_exchange_strong(&dummy_a, &dummy_b, dummy_c, kMemOrder, kMemOrder,
kMemScope);
// User-defined class is trivially-copyable and can be atomically copied
DummyTC dummytc_a{};
DummyTC dummytc_b{};
DummyTC dummytc_c{};
res = __hip_atomic_compare_exchange_strong(&dummytc_a, &dummytc_b, dummytc_c, kMemOrder,
kMemOrder, kMemScope);
}
__global__ void ExchangeCompileKernel(int* x) {
int old{};
// Valid combinations
old = __hip_atomic_exchange(x, 1, __ATOMIC_RELAXED, kMemScope);
old = __hip_atomic_exchange(x, 1, __ATOMIC_CONSUME, kMemScope);
old = __hip_atomic_exchange(x, 1, __ATOMIC_ACQUIRE, kMemScope);
old = __hip_atomic_exchange(x, 1, __ATOMIC_RELEASE, kMemScope);
old = __hip_atomic_exchange(x, 1, __ATOMIC_ACQ_REL, kMemScope);
old = __hip_atomic_exchange(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
old = __hip_atomic_exchange(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
old = __hip_atomic_exchange(*x, 1, kMemOrder, kMemScope);
// Memory order out of bounds
old = __hip_atomic_exchange(x, 1, -1, kMemScope);
old = __hip_atomic_exchange(x, 1, 10, kMemScope);
// Memory scope out of bounds
old = __hip_atomic_exchange(x, 1, kMemOrder, -1);
old = __hip_atomic_exchange(x, 1, kMemOrder, 10);
// User-defined class is not trivially-copyable and therefore cannot be atomically copied
Dummy dummy_a{};
Dummy dummy_b{};
dummy_b = __hip_atomic_exchange(&dummy_a, dummy_b, kMemOrder, kMemScope);
// User-defined class is trivially-copyable and can be atomically copied
DummyTC dummytc_a{};
DummyTC dummytc_b{};
dummytc_b = __hip_atomic_exchange(&dummytc_a, dummytc_b, kMemOrder, kMemScope);
}
__global__ void FetchAddCompileKernel(int* x) {
int old{};
// Valid combinations
old = __hip_atomic_fetch_add(x, 1, __ATOMIC_RELAXED, kMemScope);
old = __hip_atomic_fetch_add(x, 1, __ATOMIC_CONSUME, kMemScope);
old = __hip_atomic_fetch_add(x, 1, __ATOMIC_ACQUIRE, kMemScope);
old = __hip_atomic_fetch_add(x, 1, __ATOMIC_RELEASE, kMemScope);
old = __hip_atomic_fetch_add(x, 1, __ATOMIC_ACQ_REL, kMemScope);
old = __hip_atomic_fetch_add(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
old = __hip_atomic_fetch_add(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
old = __hip_atomic_fetch_add(*x, 1, kMemOrder, kMemScope);
// Memory order out of bounds
old = __hip_atomic_fetch_add(x, 1, -1, kMemScope);
old = __hip_atomic_fetch_add(x, 1, 10, kMemScope);
// Memory scope out of bounds
old = __hip_atomic_fetch_add(x, 1, kMemOrder, -1);
old = __hip_atomic_fetch_add(x, 1, kMemOrder, 10);
Dummy dummy{};
old = __hip_atomic_fetch_add(&dummy, 1, kMemOrder, kMemScope);
}
__global__ void FetchAndCompileKernel(int* x) {
int old{};
// Valid combinations
old = __hip_atomic_fetch_and(x, 1, __ATOMIC_RELAXED, kMemScope);
old = __hip_atomic_fetch_and(x, 1, __ATOMIC_CONSUME, kMemScope);
old = __hip_atomic_fetch_and(x, 1, __ATOMIC_ACQUIRE, kMemScope);
old = __hip_atomic_fetch_and(x, 1, __ATOMIC_RELEASE, kMemScope);
old = __hip_atomic_fetch_and(x, 1, __ATOMIC_ACQ_REL, kMemScope);
old = __hip_atomic_fetch_and(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
old = __hip_atomic_fetch_and(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
old = __hip_atomic_fetch_and(*x, 1, kMemOrder, kMemScope);
// Memory order out of bounds
old = __hip_atomic_fetch_and(x, 1, -1, kMemScope);
old = __hip_atomic_fetch_and(x, 1, 10, kMemScope);
// Memory scope out of bounds
old = __hip_atomic_fetch_and(x, 1, kMemOrder, -1);
old = __hip_atomic_fetch_and(x, 1, kMemOrder, 10);
// Value must be an integer
Dummy dummy{};
old = __hip_atomic_fetch_and(&dummy, 1, kMemOrder, kMemScope);
float float_var{1.5f};
old = __hip_atomic_fetch_and(&float_var, 1, kMemOrder, kMemScope);
double double_var{1.5};
old = __hip_atomic_fetch_and(&double_var, 1, kMemOrder, kMemScope);
}
__global__ void FetchOrCompileKernel(int* x) {
int old{};
// Valid combinations
old = __hip_atomic_fetch_or(x, 1, __ATOMIC_RELAXED, kMemScope);
old = __hip_atomic_fetch_or(x, 1, __ATOMIC_CONSUME, kMemScope);
old = __hip_atomic_fetch_or(x, 1, __ATOMIC_ACQUIRE, kMemScope);
old = __hip_atomic_fetch_or(x, 1, __ATOMIC_RELEASE, kMemScope);
old = __hip_atomic_fetch_or(x, 1, __ATOMIC_ACQ_REL, kMemScope);
old = __hip_atomic_fetch_or(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
old = __hip_atomic_fetch_or(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
old = __hip_atomic_fetch_or(*x, 1, kMemOrder, kMemScope);
// Memory order out of bounds
old = __hip_atomic_fetch_or(x, 1, -1, kMemScope);
old = __hip_atomic_fetch_or(x, 1, 10, kMemScope);
// Memory scope out of bounds
old = __hip_atomic_fetch_or(x, 1, kMemOrder, -1);
old = __hip_atomic_fetch_or(x, 1, kMemOrder, 10);
// Value must be an integer
Dummy dummy{};
old = __hip_atomic_fetch_or(&dummy, 1, kMemOrder, kMemScope);
float float_var{1.5f};
old = __hip_atomic_fetch_or(&float_var, 1, kMemOrder, kMemScope);
double double_var{1.5};
old = __hip_atomic_fetch_or(&double_var, 1, kMemOrder, kMemScope);
}
__global__ void FetchXorCompileKernel(int* x) {
int old{};
// Valid combinations
old = __hip_atomic_fetch_xor(x, 1, __ATOMIC_RELAXED, kMemScope);
old = __hip_atomic_fetch_xor(x, 1, __ATOMIC_CONSUME, kMemScope);
old = __hip_atomic_fetch_xor(x, 1, __ATOMIC_ACQUIRE, kMemScope);
old = __hip_atomic_fetch_xor(x, 1, __ATOMIC_RELEASE, kMemScope);
old = __hip_atomic_fetch_xor(x, 1, __ATOMIC_ACQ_REL, kMemScope);
old = __hip_atomic_fetch_xor(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
old = __hip_atomic_fetch_xor(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
old = __hip_atomic_fetch_xor(*x, 1, kMemOrder, kMemScope);
// Memory order out of bounds
old = __hip_atomic_fetch_xor(x, 1, -1, kMemScope);
old = __hip_atomic_fetch_xor(x, 1, 10, kMemScope);
// Memory scope out of bounds
old = __hip_atomic_fetch_xor(x, 1, kMemOrder, -1);
old = __hip_atomic_fetch_xor(x, 1, kMemOrder, 10);
// Value must be an integer
Dummy dummy{};
old = __hip_atomic_fetch_xor(&dummy, 1, kMemOrder, kMemScope);
float float_var{1.5f};
old = __hip_atomic_fetch_xor(&float_var, 1, kMemOrder, kMemScope);
double double_var{1.5};
old = __hip_atomic_fetch_xor(&double_var, 1, kMemOrder, kMemScope);
}
__global__ void FetchMaxCompileKernel(int* x) {
int old{};
// Valid combinations
old = __hip_atomic_fetch_max(x, 1, __ATOMIC_RELAXED, kMemScope);
old = __hip_atomic_fetch_max(x, 1, __ATOMIC_CONSUME, kMemScope);
old = __hip_atomic_fetch_max(x, 1, __ATOMIC_ACQUIRE, kMemScope);
old = __hip_atomic_fetch_max(x, 1, __ATOMIC_RELEASE, kMemScope);
old = __hip_atomic_fetch_max(x, 1, __ATOMIC_ACQ_REL, kMemScope);
old = __hip_atomic_fetch_max(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
old = __hip_atomic_fetch_max(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
old = __hip_atomic_fetch_max(*x, 1, kMemOrder, kMemScope);
// Memory order out of bounds
old = __hip_atomic_fetch_max(x, 1, -1, kMemScope);
old = __hip_atomic_fetch_max(x, 1, 10, kMemScope);
// Memory scope out of bounds
old = __hip_atomic_fetch_max(x, 1, kMemOrder, -1);
old = __hip_atomic_fetch_max(x, 1, kMemOrder, 10);
// Value must be integer or floating point type
Dummy dummy{};
old = __hip_atomic_fetch_max(&dummy, 1, kMemOrder, kMemScope);
}
__global__ void FetchMinCompileKernel(int* x) {
int old{};
// Valid combinations
old = __hip_atomic_fetch_min(x, 1, __ATOMIC_RELAXED, kMemScope);
old = __hip_atomic_fetch_min(x, 1, __ATOMIC_CONSUME, kMemScope);
old = __hip_atomic_fetch_min(x, 1, __ATOMIC_ACQUIRE, kMemScope);
old = __hip_atomic_fetch_min(x, 1, __ATOMIC_RELEASE, kMemScope);
old = __hip_atomic_fetch_min(x, 1, __ATOMIC_ACQ_REL, kMemScope);
old = __hip_atomic_fetch_min(x, 1, __ATOMIC_SEQ_CST, kMemScope);
// Pointer to a non-const type
old = __hip_atomic_fetch_min(reinterpret_cast<const int*>(x), 1, kMemOrder, kMemScope);
// Value instead of pointer to the atomic builtin
old = __hip_atomic_fetch_min(*x, 1, kMemOrder, kMemScope);
// Memory order out of bounds
old = __hip_atomic_fetch_min(x, 1, -1, kMemScope);
old = __hip_atomic_fetch_min(x, 1, 10, kMemScope);
// Memory scope out of bounds
old = __hip_atomic_fetch_min(x, 1, kMemOrder, -1);
old = __hip_atomic_fetch_min(x, 1, kMemOrder, 10);
// Value must be integer or floating point type
Dummy dummy{};
old = __hip_atomic_fetch_min(&dummy, 1, kMemOrder, kMemScope);
}