Skip to content

Commit f7a9dd1

Browse files
committed
[OpenMP] Unconditionally provide an RPC client interface for OpenMP
Summary: This patch adds an RPC interface that lives directly in the OpenMP device runtime. This allows OpenMP to implement custom opcodes. Currently this is only providing the host call interface, which is the raw version of reverse offloading. Previously this lived in `libc/` as an extension which is not the correct place. The interface here uses a weak symbol for the RPC client by the same name that the `libc` interface uses. This means that it will defer to the libc one if both are present so we don't need to set up multiple instances. The presense of this symbol is what controls whether or not we set up the RPC server. Because this is an external symbol it normally won't be optimized out, so there's a special pass in OpenMPOpt that deletes this symbol if it is unused during linking. That means at `O0` the RPC server will always be present now, but will be removed trivially if it's not used at O1 and higher.
1 parent 054f914 commit f7a9dd1

File tree

6 files changed

+72
-6
lines changed

6 files changed

+72
-6
lines changed

offload/DeviceRTL/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ set(bc_flags -c -foffload-lto -std=c++17 -fvisibility=hidden
131131
-DOMPTARGET_DEVICE_RUNTIME
132132
-I${include_directory}
133133
-I${devicertl_base_directory}/../include
134+
-I${LLVM_MAIN_SRC_DIR}/../libc
134135
${LIBOMPTARGET_LLVM_INCLUDE_DIRS_DEVICERTL}
135136
)
136137

@@ -275,6 +276,7 @@ function(compileDeviceRTLLibrary target_cpu target_name target_triple)
275276
target_compile_definitions(${ide_target_name} PRIVATE SHARED_SCRATCHPAD_SIZE=512)
276277
target_include_directories(${ide_target_name} PRIVATE
277278
${include_directory}
279+
${LLVM_MAIN_SRC_DIR}/../libc
278280
${devicertl_base_directory}/../include
279281
${LIBOMPTARGET_LLVM_INCLUDE_DIRS}
280282
)

offload/DeviceRTL/src/Misc.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "Allocator.h"
1313
#include "Configuration.h"
1414
#include "DeviceTypes.h"
15+
#include "Shared/RPCOpcodes.h"
16+
#include "shared/rpc.h"
1517

1618
#include "Debug.h"
1719

@@ -110,6 +112,12 @@ void *indirectCallLookup(void *HstPtr) {
110112
return HstPtr;
111113
}
112114

115+
/// The openmp client instance used to communicate with the server.
116+
/// FIXME: This is marked as 'retain' so that it is not removed via
117+
/// `-mlink-builtin-bitcode`
118+
[[gnu::visibility("protected"), gnu::weak,
119+
gnu::retain]] rpc::Client Client asm("__llvm_rpc_client");
120+
113121
} // namespace impl
114122
} // namespace ompx
115123

@@ -156,6 +164,20 @@ void omp_free(void *ptr, omp_allocator_handle_t allocator) {
156164
return;
157165
}
158166
}
167+
168+
unsigned long long __llvm_omp_host_call(void *fn, void *data, size_t size) {
169+
rpc::Client::Port Port = ompx::impl::Client.open<OFFLOAD_HOST_CALL>();
170+
Port.send_n(data, size);
171+
Port.send([=](rpc::Buffer *buffer, uint32_t) {
172+
buffer->data[0] = reinterpret_cast<uintptr_t>(fn);
173+
});
174+
unsigned long long Ret;
175+
Port.recv([&](rpc::Buffer *Buffer, uint32_t) {
176+
Ret = static_cast<unsigned long long>(Buffer->data[0]);
177+
});
178+
Port.close();
179+
return Ret;
180+
}
159181
}
160182

161183
///}

offload/DeviceRTL/src/exports

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ malloc
1515
free
1616
memcmp
1717
printf
18+
__llvm_rpc_client
1819
__assert_fail

offload/include/Shared/RPCOpcodes.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===-- Shared/RPCOpcodes.h - Offload specific RPC opcodes ----- 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+
// Defines RPC opcodes that are specifically used by the OpenMP device runtime.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef OMPTARGET_SHARED_RPC_OPCODES_H
14+
#define OMPTARGET_SHARED_RPC_OPCODES_H
15+
16+
#define LLVM_OFFLOAD_RPC_BASE 'o'
17+
#define LLVM_OFFLOAD_OPCODE(n) (LLVM_OFFLOAD_RPC_BASE << 24 | n)
18+
19+
typedef enum {
20+
OFFLOAD_HOST_CALL = LLVM_OFFLOAD_OPCODE(0),
21+
} offload_opcode_t;
22+
23+
#undef LLVM_OFFLOAD_OPCODE
24+
25+
#endif // OMPTARGET_SHARED_RPC_OPCODES_H

offload/plugins-nextgen/common/src/RPC.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "RPC.h"
1010

1111
#include "Shared/Debug.h"
12+
#include "Shared/RPCOpcodes.h"
1213

1314
#include "PluginInterface.h"
1415

@@ -93,6 +94,22 @@ Error RPCServerTy::runServer(plugin::GenericDeviceTy &Device) {
9394
});
9495
break;
9596
}
97+
case OFFLOAD_HOST_CALL: {
98+
uint64_t Sizes[64] = {0};
99+
unsigned long long Results[64] = {0};
100+
void *Args[64] = {nullptr};
101+
Port->recv_n(Args, Sizes, [&](uint64_t Size) { return new char[Size]; });
102+
Port->recv([&](rpc::Buffer *buffer, uint32_t ID) {
103+
using FuncPtrTy = unsigned long long (*)(void *);
104+
auto Func = reinterpret_cast<FuncPtrTy>(buffer->data[0]);
105+
Results[ID] = Func(Args[ID]);
106+
});
107+
Port->send([&](rpc::Buffer *Buffer, uint32_t ID) {
108+
Buffer->data[0] = static_cast<uint64_t>(Results[ID]);
109+
delete[] reinterpret_cast<char *>(Args[ID]);
110+
});
111+
break;
112+
}
96113
default:
97114
// Let the `libc` library handle any other unhandled opcodes.
98115
Status = handle_libc_opcodes(*Port, Device.getWarpSize());

offload/test/libc/host_call.c renamed to offload/test/api/omp_host_call.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
// RUN: %libomptarget-compile-run-and-check-generic
22

3-
// REQUIRES: libc
4-
53
#include <assert.h>
64
#include <omp.h>
75
#include <stdio.h>
86

97
#pragma omp begin declare variant match(device = {kind(gpu)})
108
// Extension provided by the 'libc' project.
11-
unsigned long long rpc_host_call(void *fn, void *args, size_t size);
12-
#pragma omp declare target to(rpc_host_call) device_type(nohost)
9+
unsigned long long __llvm_omp_host_call(void *fn, void *args, size_t size);
10+
#pragma omp declare target to(__llvm_omp_host_call) device_type(nohost)
1311
#pragma omp end declare variant
1412

1513
#pragma omp begin declare variant match(device = {kind(cpu)})
1614
// Dummy host implementation to make this work for all targets.
17-
unsigned long long rpc_host_call(void *fn, void *args, size_t size) {
15+
unsigned long long __llvm_omp_host_call(void *fn, void *args, size_t size) {
1816
return ((unsigned long long (*)(void *))fn)(args);
1917
}
2018
#pragma omp end declare variant
@@ -58,7 +56,8 @@ int main() {
5856
#pragma omp parallel num_threads(2)
5957
{
6058
args_t args = {omp_get_thread_num(), omp_get_team_num()};
61-
unsigned long long res = rpc_host_call(fn_ptr, &args, sizeof(args_t));
59+
unsigned long long res =
60+
__llvm_omp_host_call(fn_ptr, &args, sizeof(args_t));
6261
printf("Result: %d\n", (int)res);
6362
}
6463
}

0 commit comments

Comments
 (0)