blob: 2bc430b32c2350b51c87521ac7196b889f31b0ed [file] [log] [blame]
Jim Cownie33f7b242014-04-09 15:40:23 +00001//===----------------------------------------------------------------------===//
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
11#include "compiler_if_host.h"
12
13#include <malloc.h>
14#ifndef TARGET_WINNT
15#include <alloca.h>
16#endif // TARGET_WINNT
17
18// Global counter on host.
19// This variable is used if P2OPT_offload_do_data_persistence == 2.
20// The variable used to identify offload constructs contained in one procedure.
21// Increment of OFFLOAD_CALL_COUNT is inserted at entries of HOST routines with
22// offload constructs.
23static int offload_call_count = 0;
24
25extern "C" OFFLOAD OFFLOAD_TARGET_ACQUIRE(
26 TARGET_TYPE target_type,
27 int target_number,
28 int is_optional,
29 _Offload_status* status,
30 const char* file,
31 uint64_t line
32)
33{
34 bool retval;
35 OFFLOAD ofld;
36
37 // initialize status
38 if (status != 0) {
39 status->result = OFFLOAD_UNAVAILABLE;
40 status->device_number = -1;
41 status->data_sent = 0;
42 status->data_received = 0;
43 }
44
45 // make sure libray is initialized
46 retval = __offload_init_library();
47
48 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library
49 OffloadHostTimerData * timer_data = OFFLOAD_TIMER_INIT(file, line);
50
51 OFFLOAD_TIMER_START(timer_data, c_offload_host_total_offload);
52
53 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize);
54
Alp Tokerc2d5e612014-06-01 18:28:36 +000055 // initialize all devices is init_type is on_offload_all
Jim Cownie33f7b242014-04-09 15:40:23 +000056 if (retval && __offload_init_type == c_init_on_offload_all) {
57 for (int i = 0; i < mic_engines_total; i++) {
58 mic_engines[i].init();
59 }
60 }
61 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize);
62
63 OFFLOAD_TIMER_START(timer_data, c_offload_host_target_acquire);
64
65 if (target_type == TARGET_HOST) {
66 // Host always available
67 retval = true;
68 }
69 else if (target_type == TARGET_MIC) {
70 if (target_number >= -1) {
71 if (retval) {
72 if (target_number >= 0) {
73 // User provided the device number
74 target_number = target_number % mic_engines_total;
75 }
76 else {
77 // use device 0
78 target_number = 0;
79 }
80
81 // reserve device in ORSL
82 if (is_optional) {
83 if (!ORSL::try_reserve(target_number)) {
84 target_number = -1;
85 }
86 }
87 else {
88 if (!ORSL::reserve(target_number)) {
89 target_number = -1;
90 }
91 }
92
93 // initialize device
94 if (target_number >= 0 &&
95 __offload_init_type == c_init_on_offload) {
96 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize);
97 mic_engines[target_number].init();
98 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize);
99 }
100 }
101 else {
102 // fallback to CPU
103 target_number = -1;
104 }
105
106 if (target_number < 0 || !retval) {
107 if (!is_optional && status == 0) {
108 LIBOFFLOAD_ERROR(c_device_is_not_available);
109 exit(1);
110 }
111
112 retval = false;
113 }
114 }
115 else {
116 LIBOFFLOAD_ERROR(c_invalid_device_number);
117 exit(1);
118 }
119 }
120
121 if (retval) {
122 ofld = new OffloadDescriptor(target_number, status,
123 !is_optional, false, timer_data);
124 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data, target_number);
125 Offload_Report_Prolog(timer_data);
126 OFFLOAD_DEBUG_TRACE_1(2, timer_data->offload_number, c_offload_start,
127 "Starting offload: target_type = %d, "
128 "number = %d, is_optional = %d\n",
129 target_type, target_number, is_optional);
130
131 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire);
132 }
133 else {
134 ofld = NULL;
135
136 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire);
137 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_total_offload);
138 offload_report_free_data(timer_data);
139 }
140
141 return ofld;
142}
143
144extern "C" OFFLOAD OFFLOAD_TARGET_ACQUIRE1(
145 const int* device_num,
146 const char* file,
147 uint64_t line
148)
149{
150 int target_number;
151
152 // make sure libray is initialized and at least one device is available
153 if (!__offload_init_library()) {
154 LIBOFFLOAD_ERROR(c_device_is_not_available);
155 exit(1);
156 }
157
158 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library
159
160 OffloadHostTimerData * timer_data = OFFLOAD_TIMER_INIT(file, line);
161
162 OFFLOAD_TIMER_START(timer_data, c_offload_host_total_offload);
163
164 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize);
165
166 if (__offload_init_type == c_init_on_offload_all) {
167 for (int i = 0; i < mic_engines_total; i++) {
168 mic_engines[i].init();
169 }
170 }
171
172 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize);
173
174 OFFLOAD_TIMER_START(timer_data, c_offload_host_target_acquire);
175
176 // use default device number if it is not provided
177 if (device_num != 0) {
178 target_number = *device_num;
179 }
180 else {
181 target_number = __omp_device_num;
182 }
183
184 // device number should be a non-negative integer value
185 if (target_number < 0) {
186 LIBOFFLOAD_ERROR(c_omp_invalid_device_num);
187 exit(1);
188 }
189
190 // should we do this for OpenMP?
191 target_number %= mic_engines_total;
192
193 // reserve device in ORSL
194 if (!ORSL::reserve(target_number)) {
195 LIBOFFLOAD_ERROR(c_device_is_not_available);
196 exit(1);
197 }
198
199 // initialize device(s)
200 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize);
201
202 if (__offload_init_type == c_init_on_offload) {
203 mic_engines[target_number].init();
204 }
205
206 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize);
207
208 OFFLOAD ofld =
209 new OffloadDescriptor(target_number, 0, true, true, timer_data);
210
211 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data, target_number);
212
213 Offload_Report_Prolog(timer_data);
214
215 OFFLOAD_DEBUG_TRACE_1(2, timer_data->offload_number, c_offload_start,
216 "Starting OpenMP offload, device = %d\n",
217 target_number);
218
219 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire);
220
221 return ofld;
222}
223
224int offload_offload_wrap(
225 OFFLOAD ofld,
226 const char *name,
227 int is_empty,
228 int num_vars,
229 VarDesc *vars,
230 VarDesc2 *vars2,
231 int num_waits,
232 const void **waits,
233 const void **signal,
234 int entry_id,
235 const void *stack_addr
236)
237{
238 bool ret = ofld->offload(name, is_empty, vars, vars2, num_vars,
239 waits, num_waits, signal, entry_id, stack_addr);
240 if (!ret || signal == 0) {
241 delete ofld;
242 }
243 return ret;
244}
245
246extern "C" int OFFLOAD_OFFLOAD1(
247 OFFLOAD ofld,
248 const char *name,
249 int is_empty,
250 int num_vars,
251 VarDesc *vars,
252 VarDesc2 *vars2,
253 int num_waits,
254 const void **waits,
255 const void **signal
256)
257{
258 return offload_offload_wrap(ofld, name, is_empty,
259 num_vars, vars, vars2,
260 num_waits, waits,
261 signal, NULL, NULL);
262}
263
264extern "C" int OFFLOAD_OFFLOAD2(
265 OFFLOAD ofld,
266 const char *name,
267 int is_empty,
268 int num_vars,
269 VarDesc *vars,
270 VarDesc2 *vars2,
271 int num_waits,
272 const void** waits,
273 const void** signal,
274 int entry_id,
275 const void *stack_addr
276)
277{
278 return offload_offload_wrap(ofld, name, is_empty,
279 num_vars, vars, vars2,
280 num_waits, waits,
281 signal, entry_id, stack_addr);
282}
283
284extern "C" int OFFLOAD_OFFLOAD(
285 OFFLOAD ofld,
286 const char *name,
287 int is_empty,
288 int num_vars,
289 VarDesc *vars,
290 VarDesc2 *vars2,
291 int num_waits,
292 const void **waits,
293 const void *signal,
294 int entry_id,
295 const void *stack_addr
296)
297{
298 // signal is passed by reference now
299 const void **signal_new = (signal != 0) ? &signal : 0;
300 const void **waits_new = 0;
301 int num_waits_new = 0;
302
303 // remove NULL values from the list of signals to wait for
304 if (num_waits > 0) {
305 waits_new = (const void**) alloca(sizeof(void*) * num_waits);
306 for (int i = 0; i < num_waits; i++) {
307 if (waits[i] != 0) {
308 waits_new[num_waits_new++] = waits[i];
309 }
310 }
311 }
312
313 return OFFLOAD_OFFLOAD1(ofld, name, is_empty,
314 num_vars, vars, vars2,
315 num_waits_new, waits_new,
316 signal_new);
317}
318
319extern "C" int OFFLOAD_CALL_COUNT()
320{
321 offload_call_count++;
322 return offload_call_count;
323}