1 //===-------- interface.cpp - Target independent OpenMP target RTL --------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.txt for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Implementation of the interface to be used by Clang during the codegen of a
11 // target region.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include <omptarget.h>
16 
17 #include "device.h"
18 #include "private.h"
19 #include "rtl.h"
20 
21 #include <cassert>
22 #include <cstdlib>
23 
24 ////////////////////////////////////////////////////////////////////////////////
25 /// adds a target shared library to the target execution image
26 EXTERN void __tgt_register_lib(__tgt_bin_desc *desc) {
27   RTLs.RegisterLib(desc);
28 }
29 
30 ////////////////////////////////////////////////////////////////////////////////
31 /// unloads a target shared library
32 EXTERN void __tgt_unregister_lib(__tgt_bin_desc *desc) {
33   RTLs.UnregisterLib(desc);
34 }
35 
36 /// creates host-to-target data mapping, stores it in the
37 /// libomptarget.so internal structure (an entry in a stack of data maps)
38 /// and passes the data to the device.
39 EXTERN void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
40     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
41   DP("Entering data begin region for device %" PRId64 " with %d mappings\n",
42       device_id, arg_num);
43 
44   // No devices available?
45   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
46     device_id = omp_get_default_device();
47     DP("Use default device id %" PRId64 "\n", device_id);
48   }
49 
50   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
51     DP("Failed to get device %" PRId64 " ready\n", device_id);
52     return;
53   }
54 
55   DeviceTy& Device = Devices[device_id];
56 
57 #ifdef OMPTARGET_DEBUG
58   for (int i=0; i<arg_num; ++i) {
59     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
60         ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]),
61         arg_sizes[i], arg_types[i]);
62   }
63 #endif
64 
65   target_data_begin(Device, arg_num, args_base, args, arg_sizes, arg_types);
66 }
67 
68 EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
69     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
70     int32_t depNum, void *depList, int32_t noAliasDepNum,
71     void *noAliasDepList) {
72   if (depNum + noAliasDepNum > 0)
73     __kmpc_omp_taskwait(NULL, 0);
74 
75   __tgt_target_data_begin(device_id, arg_num, args_base, args, arg_sizes,
76                           arg_types);
77 }
78 
79 /// passes data from the target, releases target memory and destroys
80 /// the host-target mapping (top entry from the stack of data maps)
81 /// created by the last __tgt_target_data_begin.
82 EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
83     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
84   DP("Entering data end region with %d mappings\n", arg_num);
85 
86   // No devices available?
87   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
88     device_id = omp_get_default_device();
89   }
90 
91   RTLsMtx.lock();
92   size_t Devices_size = Devices.size();
93   RTLsMtx.unlock();
94   if (Devices_size <= (size_t)device_id) {
95     DP("Device ID  %" PRId64 " does not have a matching RTL.\n", device_id);
96     return;
97   }
98 
99   DeviceTy &Device = Devices[device_id];
100   if (!Device.IsInit) {
101     DP("Uninit device: ignore");
102     return;
103   }
104 
105 #ifdef OMPTARGET_DEBUG
106   for (int i=0; i<arg_num; ++i) {
107     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
108         ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]),
109         arg_sizes[i], arg_types[i]);
110   }
111 #endif
112 
113   target_data_end(Device, arg_num, args_base, args, arg_sizes, arg_types);
114 }
115 
116 EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
117     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types,
118     int32_t depNum, void *depList, int32_t noAliasDepNum,
119     void *noAliasDepList) {
120   if (depNum + noAliasDepNum > 0)
121     __kmpc_omp_taskwait(NULL, 0);
122 
123   __tgt_target_data_end(device_id, arg_num, args_base, args, arg_sizes,
124                         arg_types);
125 }
126 
127 EXTERN void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
128     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
129   DP("Entering data update with %d mappings\n", arg_num);
130 
131   // No devices available?
132   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
133     device_id = omp_get_default_device();
134   }
135 
136   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
137     DP("Failed to get device %" PRId64 " ready\n", device_id);
138     return;
139   }
140 
141   DeviceTy& Device = Devices[device_id];
142   target_data_update(Device, arg_num, args_base, args, arg_sizes, arg_types);
143 }
144 
145 EXTERN void __tgt_target_data_update_nowait(
146     int64_t device_id, int32_t arg_num, void **args_base, void **args,
147     int64_t *arg_sizes, int64_t *arg_types, int32_t depNum, void *depList,
148     int32_t noAliasDepNum, void *noAliasDepList) {
149   if (depNum + noAliasDepNum > 0)
150     __kmpc_omp_taskwait(NULL, 0);
151 
152   __tgt_target_data_update(device_id, arg_num, args_base, args, arg_sizes,
153                            arg_types);
154 }
155 
156 EXTERN int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num,
157     void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
158   DP("Entering target region with entry point " DPxMOD " and device Id %"
159       PRId64 "\n", DPxPTR(host_ptr), device_id);
160 
161   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
162     device_id = omp_get_default_device();
163   }
164 
165   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
166     DP("Failed to get device %" PRId64 " ready\n", device_id);
167     return OFFLOAD_FAIL;
168   }
169 
170 #ifdef OMPTARGET_DEBUG
171   for (int i=0; i<arg_num; ++i) {
172     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
173         ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]),
174         arg_sizes[i], arg_types[i]);
175   }
176 #endif
177 
178   int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
179       arg_types, 0, 0, false /*team*/);
180 
181   return rc;
182 }
183 
184 EXTERN int __tgt_target_nowait(int64_t device_id, void *host_ptr,
185     int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes,
186     int64_t *arg_types, int32_t depNum, void *depList, int32_t noAliasDepNum,
187     void *noAliasDepList) {
188   if (depNum + noAliasDepNum > 0)
189     __kmpc_omp_taskwait(NULL, 0);
190 
191   return __tgt_target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
192                       arg_types);
193 }
194 
195 EXTERN int __tgt_target_teams(int64_t device_id, void *host_ptr,
196     int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes,
197     int64_t *arg_types, int32_t team_num, int32_t thread_limit) {
198   DP("Entering target region with entry point " DPxMOD " and device Id %"
199       PRId64 "\n", DPxPTR(host_ptr), device_id);
200 
201   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
202     device_id = omp_get_default_device();
203   }
204 
205   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
206     DP("Failed to get device %" PRId64 " ready\n", device_id);
207     return OFFLOAD_FAIL;
208   }
209 
210 #ifdef OMPTARGET_DEBUG
211   for (int i=0; i<arg_num; ++i) {
212     DP("Entry %2d: Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
213         ", Type=0x%" PRIx64 "\n", i, DPxPTR(args_base[i]), DPxPTR(args[i]),
214         arg_sizes[i], arg_types[i]);
215   }
216 #endif
217 
218   int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
219       arg_types, team_num, thread_limit, true /*team*/);
220 
221   return rc;
222 }
223 
224 EXTERN int __tgt_target_teams_nowait(int64_t device_id, void *host_ptr,
225     int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes,
226     int64_t *arg_types, int32_t team_num, int32_t thread_limit, int32_t depNum,
227     void *depList, int32_t noAliasDepNum, void *noAliasDepList) {
228   if (depNum + noAliasDepNum > 0)
229     __kmpc_omp_taskwait(NULL, 0);
230 
231   return __tgt_target_teams(device_id, host_ptr, arg_num, args_base, args,
232                             arg_sizes, arg_types, team_num, thread_limit);
233 }
234 
235 
236 // The trip count mechanism will be revised - this scheme is not thread-safe.
237 EXTERN void __kmpc_push_target_tripcount(int64_t device_id,
238     uint64_t loop_tripcount) {
239   if (device_id == OFFLOAD_DEVICE_DEFAULT) {
240     device_id = omp_get_default_device();
241   }
242 
243   if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
244     DP("Failed to get device %" PRId64 " ready\n", device_id);
245     return;
246   }
247 
248   DP("__kmpc_push_target_tripcount(%" PRId64 ", %" PRIu64 ")\n", device_id,
249       loop_tripcount);
250   Devices[device_id].loopTripCnt = loop_tripcount;
251 }
252