Files
Jan André Reuter 083d2c4b1f [Offload][OpenMP] Accept omp_initial_device for runtime calls (#205290)
In OpenMP v5.2, the constant `omp_initial_device` was introduced, which
was defined as a value of `-1`.
Support for this value was added to Clang and Flang in
09cd294482 and
3c14034c55.

However, runtime calls are not aware of this constant. As such,
execution of a runtime function, passing `omp_initial_device` as the
`device_num`, would abort with e.g.,:

```
omptarget fatal error -1: "invalid value" device number '-1' out of range, only 1 devices available
```

To fix this issue, also extend the host device checks in the API
functions to also check for `omp_initial_device`.
For testing, extend API tests using `omp_get_initial_device()` to also
test `omp_initial_device` and extend `omp_device_uid.c` to check if the
UID for `omp_initial_device` and `omp_get_initial_device()` matches.

Partially addresses https://github.com/llvm/llvm-project/issues/192980
(see
https://github.com/llvm/llvm-project/issues/192980#issuecomment-4404241994)

---------

Signed-off-by: Jan André Reuter <j.reuter@fz-juelich.de>
Signed-off-by: Jan André Reuter <jan@zyten.de>
2026-06-30 17:01:01 +02:00

100 lines
3.8 KiB
C++

//===---------- private.h - Target independent OpenMP target RTL ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Private function declarations and helper macros for debugging output.
//
//===----------------------------------------------------------------------===//
#ifndef _OMPTARGET_PRIVATE_H
#define _OMPTARGET_PRIVATE_H
#include "Shared/Debug.h"
#include "Shared/SourceInfo.h"
#include "OpenMP/InternalTypes.h"
#include "OpenMP/omp.h"
#include "device.h"
#include "omptarget.h"
#include <cstdint>
extern int target(ident_t *Loc, DeviceTy &Device, void *HostPtr,
KernelArgsTy &KernelArgs, AsyncInfoTy &AsyncInfo);
extern int target_activate_rr(DeviceTy &Device, uint64_t MemorySize,
void *ReqAddr, bool IsRecord, bool SaveOutput,
bool EmitReport, const char *OutputDirPath);
extern int
target_replay(ident_t *Loc, DeviceTy &Device, void *HostPtr, void *DeviceMemory,
int64_t DeviceMemorySize, void *ReuseDeviceAlloc,
const llvm::offloading::EntryTy *Globals, int32_t NumGlobals,
void **TgtArgs, ptrdiff_t *TgtOffsets, int32_t NumArgs,
int32_t NumTeams, int32_t ThreadLimit, uint32_t SharedMemorySize,
uint64_t LoopTripCount, AsyncInfoTy &AsyncInfo,
KernelReplayOutcomeTy *ReplayOutcome);
extern void handleTargetOutcome(bool Success, ident_t *Loc);
////////////////////////////////////////////////////////////////////////////////
/// Print out the names and properties of the arguments to each kernel
static inline void
printKernelArguments(const ident_t *Loc, const int64_t DeviceId,
const int32_t ArgNum, const int64_t *ArgSizes,
const int64_t *ArgTypes, const map_var_info_t *ArgNames,
const char *RegionType) {
SourceInfo Info(Loc);
INFO(OMP_INFOTYPE_ALL, DeviceId, "%s at %s:%d:%d with %d arguments:\n",
RegionType, Info.getFilename(), Info.getLine(), Info.getColumn(),
ArgNum);
for (int32_t I = 0; I < ArgNum; ++I) {
const map_var_info_t VarName = (ArgNames) ? ArgNames[I] : nullptr;
const char *Type = nullptr;
const char *Implicit =
(ArgTypes[I] & OMP_TGT_MAPTYPE_IMPLICIT) ? "(implicit)" : "";
if (ArgTypes[I] & OMP_TGT_MAPTYPE_ATTACH &&
ArgTypes[I] & OMP_TGT_MAPTYPE_ALWAYS)
Type = "attach:always";
else if (ArgTypes[I] & OMP_TGT_MAPTYPE_ATTACH)
Type = "attach";
else if (ArgTypes[I] & OMP_TGT_MAPTYPE_TO &&
ArgTypes[I] & OMP_TGT_MAPTYPE_FROM)
Type = "tofrom";
else if (ArgTypes[I] & OMP_TGT_MAPTYPE_TO)
Type = "to";
else if (ArgTypes[I] & OMP_TGT_MAPTYPE_FROM)
Type = "from";
else if (ArgTypes[I] & OMP_TGT_MAPTYPE_PRIVATE)
Type = "private";
else if (ArgTypes[I] & OMP_TGT_MAPTYPE_LITERAL)
Type = "firstprivate";
else if (ArgSizes[I] != 0)
Type = "alloc";
else
Type = "use_address";
INFO(OMP_INFOTYPE_ALL, DeviceId, "%s(%s)[%" PRId64 "] %s\n", Type,
getNameFromMapping(VarName).c_str(), ArgSizes[I], Implicit);
}
}
////////////////////////////////////////////////////////////////////////////////
/// Checks if the passed device is the initial device (i.e., host device)
/// While the device number is defined as the value of the total number of
/// host devices (i.e. omp_get_initial_device()), the alias omp_initial_device
/// can be used as well (Ref. OpenMP v5.2, p.23 l.33 - p.24 l.6).
static inline bool isInitialDevice(const int &DeviceNum) {
return DeviceNum == omp_get_initial_device() ||
DeviceNum == omp_initial_device;
}
#endif