1 //===--------- Misc.cpp - OpenMP device misc interfaces ----------- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
12 #include "Configuration.h"
17 #pragma omp begin declare target device_type(nohost)
26 /// AMDGCN Implementation
29 #pragma omp begin declare variant match(device = {arch(amdgcn)})
32 // The number of ticks per second for the AMDGPU clock varies by card and can
33 // only be retrived by querying the driver. We rely on the device environment
34 // to inform us what the proper frequency is.
35 return 1.0 / config::getClockFrequency();
39 uint64_t NumTicks
= 0;
40 if constexpr (__has_builtin(__builtin_amdgcn_s_sendmsg_rtnl
))
41 NumTicks
= __builtin_amdgcn_s_sendmsg_rtnl(0x83);
42 else if constexpr (__has_builtin(__builtin_amdgcn_s_memrealtime
))
43 NumTicks
= __builtin_amdgcn_s_memrealtime();
44 else if constexpr (__has_builtin(__builtin_amdgcn_s_memtime
))
45 NumTicks
= __builtin_amdgcn_s_memtime();
47 return static_cast<double>(NumTicks
) * getWTick();
50 #pragma omp end declare variant
52 /// NVPTX Implementation
55 #pragma omp begin declare variant match( \
56 device = {arch(nvptx, nvptx64)}, \
57 implementation = {extension(match_any)})
60 // Timer precision is 1ns
61 return ((double)1E-9);
65 uint64_t nsecs
= __nvvm_read_ptx_sreg_globaltimer();
66 return static_cast<double>(nsecs
) * getWTick();
69 #pragma omp end declare variant
71 /// Lookup a device-side function using a host pointer /p HstPtr using the table
72 /// provided by the device plugin. The table is an ordered pair of host and
73 /// device pointers sorted on the value of the host pointer.
74 void *indirectCallLookup(void *HstPtr
) {
78 struct IndirectCallTable
{
82 IndirectCallTable
*Table
=
83 reinterpret_cast<IndirectCallTable
*>(config::getIndirectCallTablePtr());
84 uint64_t TableSize
= config::getIndirectCallTableSize();
86 // If the table is empty we assume this is device pointer.
87 if (!Table
|| !TableSize
)
91 uint32_t Right
= TableSize
;
93 // If the pointer is definitely not contained in the table we exit early.
94 if (HstPtr
< Table
[Left
].HstPtr
|| HstPtr
> Table
[Right
- 1].HstPtr
)
97 while (Left
!= Right
) {
98 uint32_t Current
= Left
+ (Right
- Left
) / 2;
99 if (Table
[Current
].HstPtr
== HstPtr
)
100 return Table
[Current
].DevPtr
;
102 if (HstPtr
< Table
[Current
].HstPtr
)
108 // If we searched the whole table and found nothing this is a device pointer.
120 int32_t __kmpc_cancellationpoint(IdentTy
*, int32_t, int32_t) { return 0; }
122 int32_t __kmpc_cancel(IdentTy
*, int32_t, int32_t) { return 0; }
124 double omp_get_wtick(void) { return ompx::impl::getWTick(); }
126 double omp_get_wtime(void) { return ompx::impl::getWTime(); }
128 void *__llvm_omp_indirect_call_lookup(void *HstPtr
) {
129 return ompx::impl::indirectCallLookup(HstPtr
);
134 #pragma omp end declare target