Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
025d36e
[OpenMP] Adds omp_target_is_accessible routine
nicebert May 2, 2025
b33b27e
Update offload/libomptarget/OpenMP/API.cpp
nicebert Jul 28, 2025
bf01578
Fix comment spelling
nicebert Jul 28, 2025
d20f4d5
[OpenMP] Adds omp_target_is_accessible routine
nicebert May 2, 2025
cb87242
[OpenMP] Adds omp_target_is_accessible routine
nicebert May 2, 2025
03d45cc
Merge branch 'feat/omp_target_is_accessible' of github.com:nicebert/l…
nicebert Jul 31, 2025
21b1d6a
Merge branch 'main' into feat/omp_target_is_accessible
nicebert Jul 31, 2025
95ab6fe
[OpenMP] Reverts omp_get_initial_device changes
nicebert Aug 1, 2025
2436211
Merge branch 'feat/omp_target_is_accessible' of github.com:nicebert/l…
nicebert Aug 1, 2025
c92c94f
Merge branch 'main' into feat/omp_target_is_accessible
nicebert Aug 1, 2025
eeb7604
Merge branch 'main' into feat/omp_target_is_accessible
nicebert Aug 6, 2025
9d97424
[OpenMP] Adds omp_target_is_accessible routine
nicebert May 2, 2025
34acf27
Update offload/libomptarget/OpenMP/API.cpp
nicebert Jul 28, 2025
d4ecaf6
Fix comment spelling
nicebert Jul 28, 2025
2792290
[OpenMP] Adds omp_target_is_accessible routine
nicebert May 2, 2025
712bdd1
[OpenMP] Reverts omp_get_initial_device changes
nicebert Aug 1, 2025
dd15747
[OpenMP] Rework implementation to be conform to OpenMP 6.0
nicebert Sep 15, 2025
108e4b9
Merge branch 'feat/omp_target_is_accessible' of github.com:nicebert/l…
nicebert Sep 15, 2025
e9dccd6
Applies git-clang-format
nicebert Sep 17, 2025
4345232
Merge branch 'main' into feat/omp_target_is_accessible
nicebert Sep 17, 2025
4b51745
Fixes formatting and comment issues.
nicebert Sep 19, 2025
0ef2e79
Merge branch 'feat/omp_target_is_accessible' of github.com:nicebert/l…
nicebert Sep 19, 2025
454df9e
Merge branch 'main' into feat/omp_target_is_accessible
nicebert Sep 19, 2025
79dd36f
[OpenMP] Fixes check for host device number
nicebert Sep 19, 2025
0ccae1d
Merge branch 'feat/omp_target_is_accessible' of github.com:nicebert/l…
nicebert Sep 19, 2025
588c394
Fixes formatting
nicebert Sep 19, 2025
b751e75
Merge branch 'main' into feat/omp_target_is_accessible
nicebert Sep 19, 2025
584553e
Merge branch 'main' into feat/omp_target_is_accessible
nicebert Sep 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/docs/OpenMPSupport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| device | device-specific environment variables | :none:`unclaimed` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| device | omp_target_is_accessible routine | :none:`unclaimed` | |
| device | omp_target_is_accessible routine | :part:`worked on` | https://github.com/llvm/llvm-project/pull/138294 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| device | omp_get_mapped_ptr routine | :good:`done` | D141545 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
Expand Down
3 changes: 3 additions & 0 deletions offload/include/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ struct DeviceTy {
/// Ask the device whether the runtime should use auto zero-copy.
bool useAutoZeroCopy();

/// Ask the device whether it supports unified memory.
bool supportsUnifiedMemory();

/// Check if there are pending images for this device.
bool hasPendingImages() const { return HasPendingImages; }

Expand Down
1 change: 1 addition & 0 deletions offload/include/omptarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ int omp_get_initial_device(void);
void *omp_target_alloc(size_t Size, int DeviceNum);
void omp_target_free(void *DevicePtr, int DeviceNum);
int omp_target_is_present(const void *Ptr, int DeviceNum);
int omp_target_is_accessible(const void *Ptr, size_t Size, int DeviceNum);
int omp_target_memcpy(void *Dst, const void *Src, size_t Length,
size_t DstOffset, size_t SrcOffset, int DstDevice,
int SrcDevice);
Expand Down
45 changes: 44 additions & 1 deletion offload/libomptarget/OpenMP/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ EXTERN int omp_get_device_num(void) {
EXTERN int omp_get_initial_device(void) {
TIMESCOPE();
OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
int HostDevice = omp_get_num_devices();
int NumDevices = omp_get_num_devices();
int HostDevice = NumDevices == 0 ? -1 : NumDevices;
DP("Call to omp_get_initial_device returning %d\n", HostDevice);
return HostDevice;
}
Expand Down Expand Up @@ -195,6 +196,48 @@ EXTERN int omp_target_is_present(const void *Ptr, int DeviceNum) {
return Rc;
}

/// Check whether a pointer is accessible from a device.
/// the functionality is available in OpenMP 5.1 and later
/// OpenMP 5.1
/// omp_target_is_accessible checks whether a host pointer is accessible from a
/// device OpenMP 6.0 removes restriction on pointer, allowing any pointer
/// interpreted as a pointer in the address space of the given device.
EXTERN int omp_target_is_accessible(const void *Ptr, size_t Size,
int DeviceNum) {
TIMESCOPE();
OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0)));
DP("Call to omp_target_is_accessible for device %d, address " DPxMOD
", size %zu\n",
DeviceNum, DPxPTR(Ptr), Size);

if (!Ptr) {
DP("Call to omp_target_is_accessible with NULL ptr returning false\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does spec say so?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does. OMP Specs 6.0, page 607 "If ptr is NULL, the routine returns zero". Please check the specs before asking.

return false;
}

if (DeviceNum == omp_get_initial_device()) {
DP("Call to omp_target_is_accessible on host, returning true\n");
return true;
}

// The device number must refer to a valid device
auto DeviceOrErr = PM->getDevice(DeviceNum);
if (!DeviceOrErr)
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether this is a fatal message or simple just return false? What does the spec say when the device number is invalid?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @shiltian : let's return false if the device doesn't exist. A warning is also in order.


// For OpenMP 5.1 the routine checks whether a host pointer is accessible from
// the device this requires for the device to support unified shared memory
if (DeviceOrErr->supportsUnifiedMemory()) {
DP("Device %d supports unified memory, returning true\n", DeviceNum);
return true;
}

// functionality to check whether a device pointer is accessible from a device
// (OpenMP 6.0) from the host might not be possible
DP("Device %d does not support unified memory, returning false\n", DeviceNum);
return false;
}

EXTERN int omp_target_memcpy(void *Dst, const void *Src, size_t Length,
size_t DstOffset, size_t SrcOffset, int DstDevice,
int SrcDevice) {
Expand Down
4 changes: 4 additions & 0 deletions offload/libomptarget/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,7 @@ bool DeviceTy::useAutoZeroCopy() {
return false;
return RTL->use_auto_zero_copy(RTLDeviceID);
}

bool DeviceTy::supportsUnifiedMemory() {
return RTL->supports_unified_memory(RTLDeviceID);
}
1 change: 1 addition & 0 deletions offload/libomptarget/exports
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ VERS1.0 {
omp_get_initial_device;
omp_target_alloc;
omp_target_free;
omp_target_is_accessible;
omp_target_is_present;
omp_target_memcpy;
omp_target_memcpy_rect;
Expand Down
2 changes: 2 additions & 0 deletions offload/plugins-nextgen/amdgpu/src/rtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2821,6 +2821,8 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy {
return ((IsAPU || OMPX_ApuMaps) && IsXnackEnabled);
}

bool supportsUnifiedMemoryImpl() override { return IsXnackEnabled; }

/// Getters and setters for stack and heap sizes.
Error getDeviceStackSize(uint64_t &Value) override {
Value = StackSize;
Expand Down
7 changes: 7 additions & 0 deletions offload/plugins-nextgen/common/include/PluginInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,10 @@ struct GenericDeviceTy : public DeviceAllocatorTy {
bool useAutoZeroCopy();
virtual bool useAutoZeroCopyImpl() { return false; }

/// Returns true if the device has unified memory capabilities
bool supportsUnifiedMemory();
virtual bool supportsUnifiedMemoryImpl() { return false; }

/// Allocate and construct a kernel object.
virtual Expected<GenericKernelTy &> constructKernel(const char *Name) = 0;

Expand Down Expand Up @@ -1402,6 +1406,9 @@ struct GenericPluginTy {
/// Returns if the plugin can support automatic copy.
int32_t use_auto_zero_copy(int32_t DeviceId);

/// Returns if the the device supports unified memory.
int32_t supports_unified_memory(int32_t DeviceId);

/// Look up a global symbol in the given binary.
int32_t get_global(__tgt_device_binary Binary, uint64_t Size,
const char *Name, void **DevicePtr);
Expand Down
8 changes: 8 additions & 0 deletions offload/plugins-nextgen/common/src/PluginInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1629,6 +1629,10 @@ Error GenericDeviceTy::syncEvent(void *EventPtr) {

bool GenericDeviceTy::useAutoZeroCopy() { return useAutoZeroCopyImpl(); }

bool GenericDeviceTy::supportsUnifiedMemory() {
return supportsUnifiedMemoryImpl();
}

Error GenericPluginTy::init() {
if (Initialized)
return Plugin::success();
Expand Down Expand Up @@ -2181,6 +2185,10 @@ int32_t GenericPluginTy::use_auto_zero_copy(int32_t DeviceId) {
return getDevice(DeviceId).useAutoZeroCopy();
}

int32_t GenericPluginTy::supports_unified_memory(int32_t DeviceId) {
return getDevice(DeviceId).supportsUnifiedMemory();
}

int32_t GenericPluginTy::get_global(__tgt_device_binary Binary, uint64_t Size,
const char *Name, void **DevicePtr) {
assert(Binary.handle && "Invalid device binary handle");
Expand Down
40 changes: 40 additions & 0 deletions offload/test/mapping/is_accessible.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// RUN: %libomptarget-compilexx-generic
// RUN: env HSA_XNACK=1 %libomptarget-run-generic 2>&1 \
// RUN: | %fcheck-generic

// RUN: %libomptarget-compilexx-generic
// RUN: env HSA_XNACK=0 %libomptarget-run-generic 2>&1 \
// RUN: | %fcheck-generic -check-prefix=NO_USM

// REQUIRES: unified_shared_memory
// REQUIRES: amdgpu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make this a XFAIL for nvptx instead of a requirement, since it always returns false.


// CHECK: SUCCESS
// NO_USM: Not accessible

#include <assert.h>
#include <iostream>
#include <omp.h>
#include <stdio.h>

int main() {
int n = 10000;
int *a = new int[n];
int err = 0;

// program must be executed with HSA_XNACK=1
if (!omp_target_is_accessible(a, n * sizeof(int), /*device_num=*/0))
printf("Not accessible\n");
else {
#pragma omp target teams distribute parallel for
for (int i = 0; i < n; i++)
a[i] = i;

for (int i = 0; i < n; i++)
if (a[i] != i)
err++;
}

printf("%s\n", err == 0 ? "SUCCESS" : "FAIL");
return err;
}
Loading