[Openmp-commits] [openmp] [OpenMP][NFC] Move mapping related code into OpenMP/Mapping.cpp (PR #75239)
via Openmp-commits
openmp-commits at lists.llvm.org
Tue Dec 12 11:46:07 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-openmp
Author: Johannes Doerfert (jdoerfert)
<details>
<summary>Changes</summary>
DeviceTy provides an abstraction for "middle-level" operations that can be done with a offload device. Mapping was tied into it but is not strictly necessary. Other languages do not track mapping, and even OpenMP can be used completely without mapping. This simply moves the relevant code into the OpenMP/Mapping.cpp as part of a new class MappingInfoTy. Each device still has one, but it does not clutter the device.cpp anymore.
---
Patch is 68.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/75239.diff
7 Files Affected:
- (modified) openmp/libomptarget/include/ExclusiveAccess.h (+1)
- (modified) openmp/libomptarget/include/OpenMP/Mapping.h (+91)
- (modified) openmp/libomptarget/include/device.h (+15-81)
- (modified) openmp/libomptarget/src/OpenMP/API.cpp (+10-9)
- (modified) openmp/libomptarget/src/OpenMP/Mapping.cpp (+486-2)
- (modified) openmp/libomptarget/src/device.cpp (+13-494)
- (modified) openmp/libomptarget/src/omptarget.cpp (+26-24)
``````````diff
diff --git a/openmp/libomptarget/include/ExclusiveAccess.h b/openmp/libomptarget/include/ExclusiveAccess.h
index 33f59903637db..09b3aac6059db 100644
--- a/openmp/libomptarget/include/ExclusiveAccess.h
+++ b/openmp/libomptarget/include/ExclusiveAccess.h
@@ -11,6 +11,7 @@
#ifndef OMPTARGET_EXCLUSIVE_ACCESS
#define OMPTARGET_EXCLUSIVE_ACCESS
+#include <cassert>
#include <cstddef>
#include <cstdint>
#include <mutex>
diff --git a/openmp/libomptarget/include/OpenMP/Mapping.h b/openmp/libomptarget/include/OpenMP/Mapping.h
index 9a1ecb8087920..4bd676fc658a7 100644
--- a/openmp/libomptarget/include/OpenMP/Mapping.h
+++ b/openmp/libomptarget/include/OpenMP/Mapping.h
@@ -13,6 +13,7 @@
#ifndef OMPTARGET_OPENMP_MAPPING_H
#define OMPTARGET_OPENMP_MAPPING_H
+#include "ExclusiveAccess.h"
#include "Shared/EnvironmentVar.h"
#include "omptarget.h"
@@ -443,4 +444,94 @@ int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
void **ArgMappers, AsyncInfoTy &AsyncInfo,
bool FromMapper = false);
+struct MappingInfoTy {
+ MappingInfoTy(DeviceTy &Device) : Device(Device) {}
+
+ /// Host data to device map type with a wrapper key indirection that allows
+ /// concurrent modification of the entries without invalidating the underlying
+ /// entries.
+ using HostDataToTargetListTy =
+ std::set<HostDataToTargetMapKeyTy, std::less<>>;
+
+ /// The HDTTMap is a protected object that can only be accessed by one thread
+ /// at a time.
+ ProtectedObj<HostDataToTargetListTy> HostDataToTargetMap;
+
+ /// The type used to access the HDTT map.
+ using HDTTMapAccessorTy = decltype(HostDataToTargetMap)::AccessorTy;
+
+ /// Lookup the mapping of \p HstPtrBegin in \p HDTTMap. The accessor ensures
+ /// exclusive access to the HDTT map.
+ LookupResult lookupMapping(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
+ int64_t Size,
+ HostDataToTargetTy *OwnedTPR = nullptr);
+
+ /// Get the target pointer based on host pointer begin and base. If the
+ /// mapping already exists, the target pointer will be returned directly. In
+ /// addition, if required, the memory region pointed by \p HstPtrBegin of size
+ /// \p Size will also be transferred to the device. If the mapping doesn't
+ /// exist, and if unified shared memory is not enabled, a new mapping will be
+ /// created and the data will also be transferred accordingly. nullptr will be
+ /// returned because of any of following reasons:
+ /// - Data allocation failed;
+ /// - The user tried to do an illegal mapping;
+ /// - Data transfer issue fails.
+ TargetPointerResultTy getTargetPointer(
+ HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, void *HstPtrBase,
+ int64_t TgtPadding, int64_t Size, map_var_info_t HstPtrName,
+ bool HasFlagTo, bool HasFlagAlways, bool IsImplicit, bool UpdateRefCount,
+ bool HasCloseModifier, bool HasPresentModifier, bool HasHoldModifier,
+ AsyncInfoTy &AsyncInfo, HostDataToTargetTy *OwnedTPR = nullptr,
+ bool ReleaseHDTTMap = true);
+
+ /// Return the target pointer for \p HstPtrBegin in \p HDTTMap. The accessor
+ /// ensures exclusive access to the HDTT map.
+ void *getTgtPtrBegin(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
+ int64_t Size);
+
+ /// Return the target pointer begin (where the data will be moved).
+ /// Used by targetDataBegin, targetDataEnd, targetDataUpdate and target.
+ /// - \p UpdateRefCount and \p UseHoldRefCount controls which and if the entry
+ /// reference counters will be decremented.
+ /// - \p MustContain enforces that the query must not extend beyond an already
+ /// mapped entry to be valid.
+ /// - \p ForceDelete deletes the entry regardless of its reference counting
+ /// (unless it is infinite).
+ /// - \p FromDataEnd tracks the number of threads referencing the entry at
+ /// targetDataEnd for delayed deletion purpose.
+ [[nodiscard]] TargetPointerResultTy
+ getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool UpdateRefCount,
+ bool UseHoldRefCount, bool MustContain = false,
+ bool ForceDelete = false, bool FromDataEnd = false);
+
+ /// Remove the \p Entry from the data map. Expect the entry's total reference
+ /// count to be zero and the caller thread to be the last one using it. \p
+ /// HDTTMap ensure the caller holds exclusive access and can modify the map.
+ /// Return \c OFFLOAD_SUCCESS if the map entry existed, and return \c
+ /// OFFLOAD_FAIL if not. It is the caller's responsibility to skip calling
+ /// this function if the map entry is not expected to exist because \p
+ /// HstPtrBegin uses shared memory.
+ [[nodiscard]] int eraseMapEntry(HDTTMapAccessorTy &HDTTMap,
+ HostDataToTargetTy *Entry, int64_t Size);
+
+ /// Deallocate the \p Entry from the device memory and delete it. Return \c
+ /// OFFLOAD_SUCCESS if the deallocation operations executed successfully, and
+ /// return \c OFFLOAD_FAIL otherwise.
+ [[nodiscard]] int deallocTgtPtrAndEntry(HostDataToTargetTy *Entry,
+ int64_t Size);
+
+ int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
+ int disassociatePtr(void *HstPtrBegin);
+
+ /// Print information about the transfer from \p HstPtr to \p TgtPtr (or vice
+ /// versa if \p H2D is false). If there is an existing mapping, or if \p Entry
+ /// is set, the associated metadata will be printed as well.
+ void printCopyInfo(void *TgtPtr, void *HstPtr, int64_t Size, bool H2D,
+ HostDataToTargetTy *Entry,
+ MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr);
+
+private:
+ DeviceTy &Device;
+};
+
#endif // OMPTARGET_OPENMP_MAPPING_H
diff --git a/openmp/libomptarget/include/device.h b/openmp/libomptarget/include/device.h
index a84551accaf92..d28d3c508faf5 100644
--- a/openmp/libomptarget/include/device.h
+++ b/openmp/libomptarget/include/device.h
@@ -53,19 +53,6 @@ struct DeviceTy {
bool HasMappedGlobalData = false;
- /// Host data to device map type with a wrapper key indirection that allows
- /// concurrent modification of the entries without invalidating the underlying
- /// entries.
- using HostDataToTargetListTy =
- std::set<HostDataToTargetMapKeyTy, std::less<>>;
-
- /// The HDTTMap is a protected object that can only be accessed by one thread
- /// at a time.
- ProtectedObj<HostDataToTargetListTy> HostDataToTargetMap;
-
- /// The type used to access the HDTT map.
- using HDTTMapAccessorTy = decltype(HostDataToTargetMap)::AccessorTy;
-
PendingCtorsDtorsPerLibrary PendingCtorsDtors;
std::mutex PendingGlobalsMtx;
@@ -80,71 +67,8 @@ struct DeviceTy {
/// Try to initialize the device and return any failure.
llvm::Error init();
- // Return true if data can be copied to DstDevice directly
- bool isDataExchangable(const DeviceTy &DstDevice);
-
- /// Lookup the mapping of \p HstPtrBegin in \p HDTTMap. The accessor ensures
- /// exclusive access to the HDTT map.
- LookupResult lookupMapping(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
- int64_t Size,
- HostDataToTargetTy *OwnedTPR = nullptr);
-
- /// Get the target pointer based on host pointer begin and base. If the
- /// mapping already exists, the target pointer will be returned directly. In
- /// addition, if required, the memory region pointed by \p HstPtrBegin of size
- /// \p Size will also be transferred to the device. If the mapping doesn't
- /// exist, and if unified shared memory is not enabled, a new mapping will be
- /// created and the data will also be transferred accordingly. nullptr will be
- /// returned because of any of following reasons:
- /// - Data allocation failed;
- /// - The user tried to do an illegal mapping;
- /// - Data transfer issue fails.
- TargetPointerResultTy getTargetPointer(
- HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, void *HstPtrBase,
- int64_t TgtPadding, int64_t Size, map_var_info_t HstPtrName,
- bool HasFlagTo, bool HasFlagAlways, bool IsImplicit, bool UpdateRefCount,
- bool HasCloseModifier, bool HasPresentModifier, bool HasHoldModifier,
- AsyncInfoTy &AsyncInfo, HostDataToTargetTy *OwnedTPR = nullptr,
- bool ReleaseHDTTMap = true);
-
- /// Return the target pointer for \p HstPtrBegin in \p HDTTMap. The accessor
- /// ensures exclusive access to the HDTT map.
- void *getTgtPtrBegin(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,
- int64_t Size);
-
- /// Return the target pointer begin (where the data will be moved).
- /// Used by targetDataBegin, targetDataEnd, targetDataUpdate and target.
- /// - \p UpdateRefCount and \p UseHoldRefCount controls which and if the entry
- /// reference counters will be decremented.
- /// - \p MustContain enforces that the query must not extend beyond an already
- /// mapped entry to be valid.
- /// - \p ForceDelete deletes the entry regardless of its reference counting
- /// (unless it is infinite).
- /// - \p FromDataEnd tracks the number of threads referencing the entry at
- /// targetDataEnd for delayed deletion purpose.
- [[nodiscard]] TargetPointerResultTy
- getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool UpdateRefCount,
- bool UseHoldRefCount, bool MustContain = false,
- bool ForceDelete = false, bool FromDataEnd = false);
-
- /// Remove the \p Entry from the data map. Expect the entry's total reference
- /// count to be zero and the caller thread to be the last one using it. \p
- /// HDTTMap ensure the caller holds exclusive access and can modify the map.
- /// Return \c OFFLOAD_SUCCESS if the map entry existed, and return \c
- /// OFFLOAD_FAIL if not. It is the caller's responsibility to skip calling
- /// this function if the map entry is not expected to exist because \p
- /// HstPtrBegin uses shared memory.
- [[nodiscard]] int eraseMapEntry(HDTTMapAccessorTy &HDTTMap,
- HostDataToTargetTy *Entry, int64_t Size);
-
- /// Deallocate the \p Entry from the device memory and delete it. Return \c
- /// OFFLOAD_SUCCESS if the deallocation operations executed successfully, and
- /// return \c OFFLOAD_FAIL otherwise.
- [[nodiscard]] int deallocTgtPtrAndEntry(HostDataToTargetTy *Entry,
- int64_t Size);
-
- int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
- int disassociatePtr(void *HstPtrBegin);
+ /// Provide access to the mapping handler.
+ MappingInfoTy &getMappingInfo() { return MappingInfo; }
__tgt_target_table *loadBinary(__tgt_device_image *Img);
@@ -159,6 +83,7 @@ struct DeviceTy {
/// be used (host, shared, device).
void *allocData(int64_t Size, void *HstPtr = nullptr,
int32_t Kind = TARGET_ALLOC_DEFAULT);
+
/// Deallocates memory which \p TgtPtrBegin points at and returns
/// OFFLOAD_SUCCESS/OFFLOAD_FAIL when succeeds/fails. p Kind dictates what
/// allocator should be used (host, shared, device).
@@ -170,12 +95,16 @@ struct DeviceTy {
int32_t submitData(void *TgtPtrBegin, void *HstPtrBegin, int64_t Size,
AsyncInfoTy &AsyncInfo,
HostDataToTargetTy *Entry = nullptr,
- DeviceTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);
+ MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);
+
// Copy data from device back to host
int32_t retrieveData(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size,
AsyncInfoTy &AsyncInfo,
HostDataToTargetTy *Entry = nullptr,
- DeviceTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);
+ MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);
+
+ // Return true if data can be copied to DstDevice directly
+ bool isDataExchangable(const DeviceTy &DstDevice);
// Copy data from current device to destination device directly
int32_t dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr,
@@ -240,7 +169,12 @@ struct DeviceTy {
void deinit();
/// All offload entries available on this device.
- llvm::DenseMap<llvm::StringRef, OffloadEntryTy *> DeviceOffloadEntries;
+ using DeviceOffloadEntriesMapTy =
+ llvm::DenseMap<llvm::StringRef, OffloadEntryTy *>;
+ ProtectedObj<DeviceOffloadEntriesMapTy> DeviceOffloadEntries;
+
+ /// Handler to collect and organize host-2-device mapping information.
+ MappingInfoTy MappingInfo;
};
#endif
diff --git a/openmp/libomptarget/src/OpenMP/API.cpp b/openmp/libomptarget/src/OpenMP/API.cpp
index b73315f2b77a3..1769404faf888 100644
--- a/openmp/libomptarget/src/OpenMP/API.cpp
+++ b/openmp/libomptarget/src/OpenMP/API.cpp
@@ -150,9 +150,9 @@ EXTERN int omp_target_is_present(const void *Ptr, int DeviceNum) {
// only check 1 byte. Cannot set size 0 which checks whether the pointer (zero
// lengh array) is mapped instead of the referred storage.
TargetPointerResultTy TPR =
- DeviceOrErr->getTgtPtrBegin(const_cast<void *>(Ptr), 1,
- /*UpdateRefCount=*/false,
- /*UseHoldRefCount=*/false);
+ DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1,
+ /*UpdateRefCount=*/false,
+ /*UseHoldRefCount=*/false);
int Rc = TPR.isPresent();
DP("Call to omp_target_is_present returns %d\n", Rc);
return Rc;
@@ -544,8 +544,8 @@ EXTERN int omp_target_associate_ptr(const void *HostPtr, const void *DevicePtr,
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());
void *DeviceAddr = (void *)((uint64_t)DevicePtr + (uint64_t)DeviceOffset);
- int Rc = DeviceOrErr->associatePtr(const_cast<void *>(HostPtr),
- const_cast<void *>(DeviceAddr), Size);
+ int Rc = DeviceOrErr->getMappingInfo().associatePtr(
+ const_cast<void *>(HostPtr), const_cast<void *>(DeviceAddr), Size);
DP("omp_target_associate_ptr returns %d\n", Rc);
return Rc;
}
@@ -571,7 +571,8 @@ EXTERN int omp_target_disassociate_ptr(const void *HostPtr, int DeviceNum) {
if (!DeviceOrErr)
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());
- int Rc = DeviceOrErr->disassociatePtr(const_cast<void *>(HostPtr));
+ int Rc = DeviceOrErr->getMappingInfo().disassociatePtr(
+ const_cast<void *>(HostPtr));
DP("omp_target_disassociate_ptr returns %d\n", Rc);
return Rc;
}
@@ -603,9 +604,9 @@ EXTERN void *omp_get_mapped_ptr(const void *Ptr, int DeviceNum) {
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());
TargetPointerResultTy TPR =
- DeviceOrErr->getTgtPtrBegin(const_cast<void *>(Ptr), 1,
- /*UpdateRefCount=*/false,
- /*UseHoldRefCount=*/false);
+ DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1,
+ /*UpdateRefCount=*/false,
+ /*UseHoldRefCount=*/false);
if (!TPR.isPresent()) {
DP("Ptr " DPxMOD "is not present on device %d, returning nullptr.\n",
DPxPTR(Ptr), DeviceNum);
diff --git a/openmp/libomptarget/src/OpenMP/Mapping.cpp b/openmp/libomptarget/src/OpenMP/Mapping.cpp
index c7cb5b6b1e4c4..a5c24810e0af9 100644
--- a/openmp/libomptarget/src/OpenMP/Mapping.cpp
+++ b/openmp/libomptarget/src/OpenMP/Mapping.cpp
@@ -10,13 +10,15 @@
#include "OpenMP/Mapping.h"
+#include "PluginManager.h"
#include "Shared/Debug.h"
+#include "Shared/Requirements.h"
#include "device.h"
/// Dump a table of all the host-target pointer pairs on failure
void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device) {
- DeviceTy::HDTTMapAccessorTy HDTTMap =
- Device.HostDataToTargetMap.getExclusiveAccessor();
+ MappingInfoTy::HDTTMapAccessorTy HDTTMap =
+ Device.getMappingInfo().HostDataToTargetMap.getExclusiveAccessor();
if (HDTTMap->empty())
return;
@@ -38,3 +40,485 @@ void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device) {
Info.getLine(), Info.getColumn());
}
}
+
+int MappingInfoTy::associatePtr(void *HstPtrBegin, void *TgtPtrBegin,
+ int64_t Size) {
+ HDTTMapAccessorTy HDTTMap = HostDataToTargetMap.getExclusiveAccessor();
+
+ // Check if entry exists
+ auto It = HDTTMap->find(HstPtrBegin);
+ if (It != HDTTMap->end()) {
+ HostDataToTargetTy &HDTT = *It->HDTT;
+ std::lock_guard<HostDataToTargetTy> LG(HDTT);
+ // Mapping already exists
+ bool IsValid = HDTT.HstPtrEnd == (uintptr_t)HstPtrBegin + Size &&
+ HDTT.TgtPtrBegin == (uintptr_t)TgtPtrBegin;
+ if (IsValid) {
+ DP("Attempt to re-associate the same device ptr+offset with the same "
+ "host ptr, nothing to do\n");
+ return OFFLOAD_SUCCESS;
+ }
+ REPORT("Not allowed to re-associate a different device ptr+offset with "
+ "the same host ptr\n");
+ return OFFLOAD_FAIL;
+ }
+
+ // Mapping does not exist, allocate it with refCount=INF
+ const HostDataToTargetTy &NewEntry =
+ *HDTTMap
+ ->emplace(new HostDataToTargetTy(
+ /*HstPtrBase=*/(uintptr_t)HstPtrBegin,
+ /*HstPtrBegin=*/(uintptr_t)HstPtrBegin,
+ /*HstPtrEnd=*/(uintptr_t)HstPtrBegin + Size,
+ /*TgtAllocBegin=*/(uintptr_t)TgtPtrBegin,
+ /*TgtPtrBegin=*/(uintptr_t)TgtPtrBegin,
+ /*UseHoldRefCount=*/false, /*Name=*/nullptr,
+ /*IsRefCountINF=*/true))
+ .first->HDTT;
+ DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD
+ ", HstEnd=" DPxMOD ", TgtBegin=" DPxMOD ", DynRefCount=%s, "
+ "HoldRefCount=%s\n",
+ DPxPTR(NewEntry.HstPtrBase), DPxPTR(NewEntry.HstPtrBegin),
+ DPxPTR(NewEntry.HstPtrEnd), DPxPTR(NewEntry.TgtPtrBegin),
+ NewEntry.dynRefCountToStr().c_str(), NewEntry.holdRefCountToStr().c_str());
+ (void)NewEntry;
+
+ // Notify the plugin about the new mapping.
+ return Device.notifyDataMapped(HstPtrBegin, Size);
+}
+
+int MappingInfoTy::disassociatePtr(void *HstPtrBegin) {
+ HDTTMapAccessorTy HDTTMap = HostDataToTargetMap.getExclusiveAccessor();
+
+ auto It = HDTTMap->find(HstPtrBegin);
+ if (It == HDTTMap->end()) {
+ REPORT("Association not found\n");
+ return OFFLOAD_FAIL;
+ }
+ // Mapping exists
+ HostDataToTargetTy &HDTT = *It->HDTT;
+ std::lock_guard<HostDataToTargetTy> LG(HDTT);
+
+ if (HDTT.getHoldRefCount()) {
+ // This is based on OpenACC 3.1, sec 3.2.33 "acc_unmap_data", L3656-3657:
+ // "It is an error to call acc_unmap_data if the structured reference
+ // count for the pointer is not zero."
+ REPORT("Trying to disassociate a pointer with a non-zero hold reference "
+ "count\n");
+ return OFFLOAD_FAIL;
+ }
+
+ if (HDTT.isDynRefCountInf()) {
+ DP("Association found, removing it\n");
+ void *Event = HDTT.getEvent();
+ delete &HDTT;
+ if (Event)
+ Device.destroyEvent(Event);
+ HDTTMap->erase(It);
+ return Device.notifyDataUnmapped(HstPtrBegin);
+ }
+
+ REPORT("Trying to disassociate a pointer which was not mapped via "
+ "omp_target_associate_ptr\n");
+ return OFFLOAD_FAIL;
+}
+
+LookupResult MappingInfoTy::lookupMapping(HDTTMapAccessorTy &HDTTMap,
+ void *HstPtrBegin, int64_t Size,
+ HostDataToTargetTy *OwnedTPR) {
+
+ uintptr_t HP = (uintptr_t)HstPtrBegin;
+ LookupResult LR;
+
+ DP("Looking up mapping(HstPtrBegin=" DPxMOD ", Size=%" PRId64 ")...\n",
+ DPxPTR(HP), Size);
+
+ if (HDTTMap->empty())
+ return LR;
+
+ auto Upper = HDTTMap->upper_bound(HP);
+
+ if (Size == 0) {
+ // specification v5.1 Pointer Initialization for Device Data Environments
+ // upper_bound satisfies
+ // std::prev(upper)->HDTT.HstPtrBegin <= hp < upper->HDTT.HstPtrBegin
+ if (Upper != HDTTMap->begin()) {
+ LR.TPR.setEntry(std::prev(Upper)->HDTT, OwnedTPR);
+ // the left side of extended address range is satisified.
+ // hp >= LR.TPR.getEntry()->HstPtrBegin || hp >=
+ // LR.TPR.getEntry()->H...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/75239
More information about the Openmp-commits
mailing list