Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / openmp / libomptarget / DeviceRTL / src / Misc.cpp
blob87d568779b401eaf82e1408d61d3c0dd642f6a7f
1 //===--------- Misc.cpp - OpenMP device misc interfaces ----------- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //
10 //===----------------------------------------------------------------------===//
12 #include "Configuration.h"
13 #include "Types.h"
15 #include "Debug.h"
17 #pragma omp begin declare target device_type(nohost)
19 namespace ompx {
20 namespace impl {
22 double getWTick();
24 double getWTime();
26 /// AMDGCN Implementation
27 ///
28 ///{
29 #pragma omp begin declare variant match(device = {arch(amdgcn)})
31 double getWTick() {
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();
38 double getWTime() {
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
53 ///
54 ///{
55 #pragma omp begin declare variant match( \
56 device = {arch(nvptx, nvptx64)}, \
57 implementation = {extension(match_any)})
59 double getWTick() {
60 // Timer precision is 1ns
61 return ((double)1E-9);
64 double getWTime() {
65 unsigned long long nsecs;
66 asm volatile("mov.u64 %0, %%globaltimer;" : "=l"(nsecs));
67 return (double)nsecs * getWTick();
70 #pragma omp end declare variant
72 /// Lookup a device-side function using a host pointer /p HstPtr using the table
73 /// provided by the device plugin. The table is an ordered pair of host and
74 /// device pointers sorted on the value of the host pointer.
75 void *indirectCallLookup(void *HstPtr) {
76 if (!HstPtr)
77 return nullptr;
79 struct IndirectCallTable {
80 void *HstPtr;
81 void *DevPtr;
83 IndirectCallTable *Table =
84 reinterpret_cast<IndirectCallTable *>(config::getIndirectCallTablePtr());
85 uint64_t TableSize = config::getIndirectCallTableSize();
87 // If the table is empty we assume this is device pointer.
88 if (!Table || !TableSize)
89 return HstPtr;
91 uint32_t Left = 0;
92 uint32_t Right = TableSize;
94 // If the pointer is definitely not contained in the table we exit early.
95 if (HstPtr < Table[Left].HstPtr || HstPtr > Table[Right - 1].HstPtr)
96 return HstPtr;
98 while (Left != Right) {
99 uint32_t Current = Left + (Right - Left) / 2;
100 if (Table[Current].HstPtr == HstPtr)
101 return Table[Current].DevPtr;
103 if (HstPtr < Table[Current].HstPtr)
104 Right = Current;
105 else
106 Left = Current;
109 // If we searched the whole table and found nothing this is a device pointer.
110 return HstPtr;
113 } // namespace impl
114 } // namespace ompx
116 /// Interfaces
118 ///{
120 extern "C" {
121 int32_t __kmpc_cancellationpoint(IdentTy *, int32_t, int32_t) { return 0; }
123 int32_t __kmpc_cancel(IdentTy *, int32_t, int32_t) { return 0; }
125 double omp_get_wtick(void) { return ompx::impl::getWTick(); }
127 double omp_get_wtime(void) { return ompx::impl::getWTime(); }
129 void *__llvm_omp_indirect_call_lookup(void *HstPtr) {
130 return ompx::impl::indirectCallLookup(HstPtr);
134 ///}
135 #pragma omp end declare target