]> git.ipfire.org Git - thirdparty/gcc.git/blob - liboffloadmic/runtime/offload_omp_target.cpp
PR c++/87554 - ICE with extern template and reference member.
[thirdparty/gcc.git] / liboffloadmic / runtime / offload_omp_target.cpp
1 /*
2 Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30
31 #include <omp.h>
32 #include "offload.h"
33 #include "compiler_if_target.h"
34
35 // OpenMP API
36
37 void omp_set_default_device(int num) __GOMP_NOTHROW
38 {
39 }
40
41 int omp_get_default_device(void) __GOMP_NOTHROW
42 {
43 return mic_index;
44 }
45
46 int omp_get_num_devices() __GOMP_NOTHROW
47 {
48 return mic_engines_total;
49 }
50
51 // OpenMP 4.5 APIs
52
53 // COI supports 3-dim multiD transfers
54 #define MAX_ARRAY_RANK 3
55
56 DLL_LOCAL void omp_target_alloc_target(
57 void *ofld_
58 )
59 {
60 OFFLOAD ofld = (OFFLOAD) ofld_;
61 VarDesc vars[2] = {0};
62 size_t size;
63 void* memory;
64
65 vars[0].type.src = c_data;
66 vars[0].type.dst = c_data;
67 vars[0].direction.bits = c_parameter_in;
68 vars[0].ptr = &size;
69
70 vars[1].type.src = c_data;
71 vars[1].type.dst = c_data;
72 vars[1].direction.bits = c_parameter_out;
73 vars[1].ptr = &memory;
74
75 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
76 OFFLOAD_DEBUG_TRACE(2, "omp_target_alloc(%lld)\n", size);
77 // We do not check for malloc returning NULL because the
78 // specification of this API includes the possibility of failure.
79 // The user will check the returned result
80 memory = malloc(size);
81 OFFLOAD_DEBUG_TRACE(2, "omp_target_alloc allocated at %p\n", memory);
82 OFFLOAD_TARGET_LEAVE(ofld);
83 }
84
85 DLL_LOCAL void omp_target_free_target(
86 void *ofld_
87 )
88 {
89 OFFLOAD ofld = (OFFLOAD) ofld_;
90 VarDesc vars[1] = {0};
91 void* memory;
92
93 vars[0].type.src = c_data;
94 vars[0].type.dst = c_data;
95 vars[0].direction.bits = c_parameter_in;
96 vars[0].ptr = &memory;
97
98 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
99 OFFLOAD_DEBUG_TRACE(2, "omp_target_free(%p)\n", memory);
100 free(memory);
101 OFFLOAD_DEBUG_TRACE(2, "omp_target_free freed\n");
102 OFFLOAD_TARGET_LEAVE(ofld);
103 }
104
105 DLL_LOCAL void omp_target_memcpy_target(
106 void *ofld_
107 )
108 {
109 OFFLOAD ofld = (OFFLOAD) ofld_;
110 VarDesc vars[3] = {0};
111 void* dst;
112 void* src;
113 size_t length;
114
115 vars[0].type.src = c_data;
116 vars[0].type.dst = c_data;
117 vars[0].direction.bits = c_parameter_in;
118 vars[0].ptr = &dst;
119
120 vars[1].type.src = c_data;
121 vars[1].type.dst = c_data;
122 vars[1].direction.bits = c_parameter_in;
123 vars[1].ptr = &src;
124
125 vars[2].type.src = c_data;
126 vars[2].type.dst = c_data;
127 vars[2].direction.bits = c_parameter_in;
128 vars[2].ptr = &length;
129
130 OFFLOAD_TARGET_ENTER(ofld, 3, vars, NULL);
131 OFFLOAD_DEBUG_TRACE(2, "omp_target_memcpy(%p, %p, %lld)\n",
132 dst, src, length);
133 memcpy(dst, src, length);
134
135 OFFLOAD_DEBUG_TRACE(2, "omp_target_memcpy done\n");
136 OFFLOAD_TARGET_LEAVE(ofld);
137 }
138
139 static size_t bytesize_at_this_dimension(
140 size_t element_size,
141 int num_dims,
142 const size_t* dimensions
143 )
144 {
145 if (num_dims > 1) {
146 return dimensions[1] *
147 bytesize_at_this_dimension(
148 element_size, num_dims-1, dimensions+1);
149 } else {
150 return element_size;
151 }
152 }
153
154 static void memcpy_rect(
155 char *dst,
156 char *src,
157 size_t element_size,
158 int num_dims,
159 const size_t *volume,
160 const size_t *dst_offsets,
161 const size_t *src_offsets,
162 const size_t *dst_dimensions,
163 const size_t *src_dimensions
164 )
165 {
166 if (num_dims > 1) {
167 int count = volume[0];
168 int dst_index = dst_offsets[0];
169 int src_index = src_offsets[0];
170 size_t dst_element_size =
171 bytesize_at_this_dimension(element_size, num_dims, dst_dimensions);
172 size_t src_element_size =
173 bytesize_at_this_dimension(element_size, num_dims, src_dimensions);
174 for (; count>0; dst_index++, src_index++, count--) {
175 memcpy_rect(dst+dst_element_size*dst_index,
176 src+src_element_size*src_index,
177 element_size, num_dims-1, volume+1,
178 dst_offsets+1, src_offsets+1,
179 dst_dimensions+1, src_dimensions+1);
180 }
181 } else {
182 memcpy(dst+dst_offsets[0]*element_size,
183 src+src_offsets[0]*element_size,
184 element_size * volume[0]);
185 }
186 }
187
188 DLL_LOCAL void omp_target_memcpy_rect_target(
189 void *ofld_
190 )
191 {
192 OFFLOAD ofld = (OFFLOAD) ofld_;
193 VarDesc vars[1] = {0};
194 struct parameters {
195 void *dst;
196 void *src;
197 size_t element_size;
198 int num_dims;
199 size_t array_info[MAX_ARRAY_RANK*5];
200 } parameters;
201
202 vars[0].type.src = c_data;
203 vars[0].type.dst = c_data;
204 vars[0].direction.bits = c_parameter_in;
205 vars[0].ptr = &parameters;
206
207 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
208 OFFLOAD_DEBUG_TRACE(2, "omp_target_memcpy_rect(%p, %p, %lld, %d)\n",
209 parameters.dst, parameters.src,
210 parameters.element_size, parameters.num_dims);
211 memcpy_rect(
212 (char*)parameters.dst, (char*)parameters.src, parameters.element_size,
213 parameters.num_dims,
214 &parameters.array_info[0],
215 &parameters.array_info[parameters.num_dims],
216 &parameters.array_info[parameters.num_dims*2],
217 &parameters.array_info[parameters.num_dims*3],
218 &parameters.array_info[parameters.num_dims*4]);
219
220 OFFLOAD_DEBUG_TRACE(2, "omp_target_memcpy_rect done\n");
221 OFFLOAD_TARGET_LEAVE(ofld);
222 }
223
224 // End of OpenMP 4.5 APIs
225
226
227 // OpenMP API wrappers
228
229 static void omp_send_int_to_host(
230 void *ofld_,
231 int setting
232 )
233 {
234 OFFLOAD ofld = (OFFLOAD) ofld_;
235 VarDesc vars[1] = {0};
236
237 vars[0].type.src = c_data;
238 vars[0].type.dst = c_data;
239 vars[0].direction.bits = c_parameter_out;
240 vars[0].ptr = &setting;
241
242 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
243 OFFLOAD_TARGET_LEAVE(ofld);
244 }
245
246 static int omp_get_int_from_host(
247 void *ofld_
248 )
249 {
250 OFFLOAD ofld = (OFFLOAD) ofld_;
251 VarDesc vars[1] = {0};
252 int setting;
253
254 vars[0].type.src = c_data;
255 vars[0].type.dst = c_data;
256 vars[0].direction.bits = c_parameter_in;
257 vars[0].ptr = &setting;
258
259 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
260 OFFLOAD_TARGET_LEAVE(ofld);
261
262 return setting;
263 }
264
265 DLL_LOCAL void omp_set_num_threads_lrb(
266 void *ofld
267 )
268 {
269 int num_threads;
270
271 num_threads = omp_get_int_from_host(ofld);
272 omp_set_num_threads(num_threads);
273 }
274
275 DLL_LOCAL void omp_get_max_threads_lrb(
276 void *ofld
277 )
278 {
279 int num_threads;
280
281 num_threads = omp_get_max_threads();
282 omp_send_int_to_host(ofld, num_threads);
283 }
284
285 DLL_LOCAL void omp_get_num_procs_lrb(
286 void *ofld
287 )
288 {
289 int num_procs;
290
291 num_procs = omp_get_num_procs();
292 omp_send_int_to_host(ofld, num_procs);
293 }
294
295 DLL_LOCAL void omp_set_dynamic_lrb(
296 void *ofld
297 )
298 {
299 int dynamic;
300
301 dynamic = omp_get_int_from_host(ofld);
302 omp_set_dynamic(dynamic);
303 }
304
305 DLL_LOCAL void omp_get_dynamic_lrb(
306 void *ofld
307 )
308 {
309 int dynamic;
310
311 dynamic = omp_get_dynamic();
312 omp_send_int_to_host(ofld, dynamic);
313 }
314
315 DLL_LOCAL void omp_set_nested_lrb(
316 void *ofld
317 )
318 {
319 int nested;
320
321 nested = omp_get_int_from_host(ofld);
322 omp_set_nested(nested);
323 }
324
325 DLL_LOCAL void omp_get_nested_lrb(
326 void *ofld
327 )
328 {
329 int nested;
330
331 nested = omp_get_nested();
332 omp_send_int_to_host(ofld, nested);
333 }
334
335 DLL_LOCAL void omp_set_schedule_lrb(
336 void *ofld_
337 )
338 {
339 OFFLOAD ofld = (OFFLOAD) ofld_;
340 VarDesc vars[2] = {0};
341 omp_sched_t kind;
342 int modifier;
343
344 vars[0].type.src = c_data;
345 vars[0].type.dst = c_data;
346 vars[0].direction.bits = c_parameter_in;
347 vars[0].ptr = &kind;
348
349 vars[1].type.src = c_data;
350 vars[1].type.dst = c_data;
351 vars[1].direction.bits = c_parameter_in;
352 vars[1].ptr = &modifier;
353
354 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
355 omp_set_schedule(kind, modifier);
356 OFFLOAD_TARGET_LEAVE(ofld);
357 }
358
359 DLL_LOCAL void omp_get_schedule_lrb(
360 void *ofld_
361 )
362 {
363 OFFLOAD ofld = (OFFLOAD) ofld_;
364 VarDesc vars[2] = {0};
365 omp_sched_t kind;
366 int modifier;
367
368 vars[0].type.src = c_data;
369 vars[0].type.dst = c_data;
370 vars[0].direction.bits = c_parameter_out;
371 vars[0].ptr = &kind;
372
373 vars[1].type.src = c_data;
374 vars[1].type.dst = c_data;
375 vars[1].direction.bits = c_parameter_out;
376 vars[1].ptr = &modifier;
377
378 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
379 omp_get_schedule(&kind, &modifier);
380 OFFLOAD_TARGET_LEAVE(ofld);
381 }
382
383 // lock API functions
384
385 DLL_LOCAL void omp_init_lock_lrb(
386 void *ofld_
387 )
388 {
389 OFFLOAD ofld = (OFFLOAD) ofld_;
390 VarDesc vars[1] = {0};
391 omp_lock_target_t lock;
392
393 vars[0].type.src = c_data;
394 vars[0].type.dst = c_data;
395 vars[0].direction.bits = c_parameter_out;
396 vars[0].ptr = &lock;
397
398 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
399 omp_init_lock(&lock.lock);
400 OFFLOAD_TARGET_LEAVE(ofld);
401 }
402
403 DLL_LOCAL void omp_destroy_lock_lrb(
404 void *ofld_
405 )
406 {
407 OFFLOAD ofld = (OFFLOAD) ofld_;
408 VarDesc vars[1] = {0};
409 omp_lock_target_t lock;
410
411 vars[0].type.src = c_data;
412 vars[0].type.dst = c_data;
413 vars[0].direction.bits = c_parameter_in;
414 vars[0].ptr = &lock;
415
416 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
417 omp_destroy_lock(&lock.lock);
418 OFFLOAD_TARGET_LEAVE(ofld);
419 }
420
421 DLL_LOCAL void omp_set_lock_lrb(
422 void *ofld_
423 )
424 {
425 OFFLOAD ofld = (OFFLOAD) ofld_;
426 VarDesc vars[1] = {0};
427 omp_lock_target_t lock;
428
429 vars[0].type.src = c_data;
430 vars[0].type.dst = c_data;
431 vars[0].direction.bits = c_parameter_inout;
432 vars[0].ptr = &lock;
433
434 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
435 omp_set_lock(&lock.lock);
436 OFFLOAD_TARGET_LEAVE(ofld);
437 }
438
439 DLL_LOCAL void omp_unset_lock_lrb(
440 void *ofld_
441 )
442 {
443 OFFLOAD ofld = (OFFLOAD) ofld_;
444 VarDesc vars[1] = {0};
445 omp_lock_target_t lock;
446
447 vars[0].type.src = c_data;
448 vars[0].type.dst = c_data;
449 vars[0].direction.bits = c_parameter_inout;
450 vars[0].ptr = &lock;
451
452 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
453 omp_unset_lock(&lock.lock);
454 OFFLOAD_TARGET_LEAVE(ofld);
455 }
456
457 DLL_LOCAL void omp_test_lock_lrb(
458 void *ofld_
459 )
460 {
461 OFFLOAD ofld = (OFFLOAD) ofld_;
462 VarDesc vars[2] = {0};
463 omp_lock_target_t lock;
464 int result;
465
466 vars[0].type.src = c_data;
467 vars[0].type.dst = c_data;
468 vars[0].direction.bits = c_parameter_inout;
469 vars[0].ptr = &lock;
470
471 vars[1].type.src = c_data;
472 vars[1].type.dst = c_data;
473 vars[1].direction.bits = c_parameter_out;
474 vars[1].ptr = &result;
475
476 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
477 result = omp_test_lock(&lock.lock);
478 OFFLOAD_TARGET_LEAVE(ofld);
479 }
480
481 // nested lock API functions
482
483 DLL_LOCAL void omp_init_nest_lock_lrb(
484 void *ofld_
485 )
486 {
487 OFFLOAD ofld = (OFFLOAD) ofld_;
488 VarDesc vars[1] = {0};
489 omp_nest_lock_target_t lock;
490
491 vars[0].type.src = c_data;
492 vars[0].type.dst = c_data;
493 vars[0].direction.bits = c_parameter_out;
494 vars[0].ptr = &lock;
495
496 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
497 omp_init_nest_lock(&lock.lock);
498 OFFLOAD_TARGET_LEAVE(ofld);
499 }
500
501 DLL_LOCAL void omp_destroy_nest_lock_lrb(
502 void *ofld_
503 )
504 {
505 OFFLOAD ofld = (OFFLOAD) ofld_;
506 VarDesc vars[1] = {0};
507 omp_nest_lock_target_t lock;
508
509 vars[0].type.src = c_data;
510 vars[0].type.dst = c_data;
511 vars[0].direction.bits = c_parameter_in;
512 vars[0].ptr = &lock;
513
514 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
515 omp_destroy_nest_lock(&lock.lock);
516 OFFLOAD_TARGET_LEAVE(ofld);
517 }
518
519 DLL_LOCAL void omp_set_nest_lock_lrb(
520 void *ofld_
521 )
522 {
523 OFFLOAD ofld = (OFFLOAD) ofld_;
524 VarDesc vars[1] = {0};
525 omp_nest_lock_target_t lock;
526
527 vars[0].type.src = c_data;
528 vars[0].type.dst = c_data;
529 vars[0].direction.bits = c_parameter_inout;
530 vars[0].ptr = &lock;
531
532 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
533 omp_set_nest_lock(&lock.lock);
534 OFFLOAD_TARGET_LEAVE(ofld);
535 }
536
537 DLL_LOCAL void omp_unset_nest_lock_lrb(
538 void *ofld_
539 )
540 {
541 OFFLOAD ofld = (OFFLOAD) ofld_;
542 VarDesc vars[1] = {0};
543 omp_nest_lock_target_t lock;
544
545 vars[0].type.src = c_data;
546 vars[0].type.dst = c_data;
547 vars[0].direction.bits = c_parameter_inout;
548 vars[0].ptr = &lock;
549
550 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
551 omp_unset_nest_lock(&lock.lock);
552 OFFLOAD_TARGET_LEAVE(ofld);
553 }
554
555 DLL_LOCAL void omp_test_nest_lock_lrb(
556 void *ofld_
557 )
558 {
559 OFFLOAD ofld = (OFFLOAD) ofld_;
560 VarDesc vars[2] = {0};
561 omp_nest_lock_target_t lock;
562 int result;
563
564 vars[0].type.src = c_data;
565 vars[0].type.dst = c_data;
566 vars[0].direction.bits = c_parameter_inout;
567 vars[0].ptr = &lock;
568
569 vars[1].type.src = c_data;
570 vars[1].type.dst = c_data;
571 vars[1].direction.bits = c_parameter_out;
572 vars[1].ptr = &result;
573
574 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
575 result = omp_test_nest_lock(&lock.lock);
576 OFFLOAD_TARGET_LEAVE(ofld);
577 }
578
579 // Target-side stubs for the host functions (to avoid unresolveds)
580 // These are needed for the offloadm table
581
582 void omp_set_num_threads_target(
583 TARGET_TYPE target_type,
584 int target_number,
585 int num_threads
586 )
587 {
588 }
589
590 int omp_get_max_threads_target(
591 TARGET_TYPE target_type,
592 int target_number
593 )
594 {
595 return 0;
596 }
597
598 int omp_get_num_procs_target(
599 TARGET_TYPE target_type,
600 int target_number
601 )
602 {
603 return 0;
604 }
605
606 void omp_set_dynamic_target(
607 TARGET_TYPE target_type,
608 int target_number,
609 int num_threads
610 )
611 {
612 }
613
614 int omp_get_dynamic_target(
615 TARGET_TYPE target_type,
616 int target_number
617 )
618 {
619 return 0;
620 }
621
622 void omp_set_nested_target(
623 TARGET_TYPE target_type,
624 int target_number,
625 int num_threads
626 )
627 {
628 }
629
630 int omp_get_nested_target(
631 TARGET_TYPE target_type,
632 int target_number
633 )
634 {
635 return 0;
636 }
637
638 void omp_set_schedule_target(
639 TARGET_TYPE target_type,
640 int target_number,
641 omp_sched_t kind,
642 int modifier
643 )
644 {
645 }
646
647 void omp_get_schedule_target(
648 TARGET_TYPE target_type,
649 int target_number,
650 omp_sched_t *kind,
651 int *modifier
652 )
653 {
654 }
655
656 void omp_init_lock_target(
657 TARGET_TYPE target_type,
658 int target_number,
659 omp_lock_target_t *lock
660 )
661 {
662 }
663
664 void omp_destroy_lock_target(
665 TARGET_TYPE target_type,
666 int target_number,
667 omp_lock_target_t *lock
668 )
669 {
670 }
671
672 void omp_set_lock_target(
673 TARGET_TYPE target_type,
674 int target_number,
675 omp_lock_target_t *lock
676 )
677 {
678 }
679
680 void omp_unset_lock_target(
681 TARGET_TYPE target_type,
682 int target_number,
683 omp_lock_target_t *lock
684 )
685 {
686 }
687
688 int omp_test_lock_target(
689 TARGET_TYPE target_type,
690 int target_number,
691 omp_lock_target_t *lock
692 )
693 {
694 return 0;
695 }
696
697 void omp_init_nest_lock_target(
698 TARGET_TYPE target_type,
699 int target_number,
700 omp_nest_lock_target_t *lock
701 )
702 {
703 }
704
705 void omp_destroy_nest_lock_target(
706 TARGET_TYPE target_type,
707 int target_number,
708 omp_nest_lock_target_t *lock
709 )
710 {
711 }
712
713 void omp_set_nest_lock_target(
714 TARGET_TYPE target_type,
715 int target_number,
716 omp_nest_lock_target_t *lock
717 )
718 {
719 }
720
721 void omp_unset_nest_lock_target(
722 TARGET_TYPE target_type,
723 int target_number,
724 omp_nest_lock_target_t *lock
725 )
726 {
727 }
728
729 int omp_test_nest_lock_target(
730 TARGET_TYPE target_type,
731 int target_number,
732 omp_nest_lock_target_t *lock
733 )
734 {
735 return 0;
736 }